From 16d0c7bf1b93a84d9da87ab9600db77675afa561 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 4 Feb 2019 16:30:46 +0000 Subject: [PATCH] [CGP] use IRBuilder to simplify code This is no-functional-change-intended although there could be intermediate variations caused by a difference in the debug info produced by setting that from the builder's insertion point. I'm updating the IR test file associated with this code just to show that the naming differences from using the builder are visible. The motivation for adding a helper function is that we are likely to extend this code to deal with other overflow ops. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353056 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenPrepare.cpp | 51 +++++++------ .../CodeGenPrepare/X86/overflow-intrinsics.ll | 72 +++++++++---------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index bcb899a9e02..4792e810a85 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -1147,55 +1147,54 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI, return SinkCast(CI); } +static void replaceMathCmpWithIntrinsic(BinaryOperator *BO, CmpInst *Cmp, + Instruction *InsertPt, + Intrinsic::ID IID) { + IRBuilder<> Builder(InsertPt); + Value *MathOV = Builder.CreateBinaryIntrinsic(IID, BO->getOperand(0), + BO->getOperand(1)); + Value *Math = Builder.CreateExtractValue(MathOV, 0, "math"); + Value *OV = Builder.CreateExtractValue(MathOV, 1, "ov"); + BO->replaceAllUsesWith(Math); + Cmp->replaceAllUsesWith(OV); + BO->eraseFromParent(); + Cmp->eraseFromParent(); +} + /// Try to combine the compare into a call to the llvm.uadd.with.overflow /// intrinsic. Return true if any changes were made. static bool combineToUAddWithOverflow(CmpInst *Cmp, const TargetLowering &TLI, const DataLayout &DL) { Value *A, *B; - Instruction *AddI; - if (!match(Cmp, - m_UAddWithOverflow(m_Value(A), m_Value(B), m_Instruction(AddI)))) + BinaryOperator *Add; + if (!match(Cmp, m_UAddWithOverflow(m_Value(A), m_Value(B), m_BinOp(Add)))) return false; // Allow the transform as long as we have an integer type that is not // obviously illegal and unsupported. - Type *Ty = AddI->getType(); + Type *Ty = Add->getType(); if (!isa(Ty)) return false; EVT CodegenVT = TLI.getValueType(DL, Ty); if (!CodegenVT.isSimple() && TLI.isOperationExpand(ISD::UADDO, CodegenVT)) return false; - // We don't want to move around uses of condition values this late, so we we + // We don't want to move around uses of condition values this late, so we // check if it is legal to create the call to the intrinsic in the basic - // block containing the icmp: - if (AddI->getParent() != Cmp->getParent() && !AddI->hasOneUse()) + // block containing the icmp. + if (Add->getParent() != Cmp->getParent() && !Add->hasOneUse()) return false; #ifndef NDEBUG // Someday m_UAddWithOverflow may get smarter, but this is a safe assumption // for now: - if (AddI->hasOneUse()) - assert(*AddI->user_begin() == Cmp && "expected!"); + if (Add->hasOneUse()) + assert(*Add->user_begin() == Cmp && "expected!"); #endif - Module *M = Cmp->getModule(); - Function *F = Intrinsic::getDeclaration(M, Intrinsic::uadd_with_overflow, Ty); - Instruction *InsertPt = AddI->hasOneUse() ? Cmp : AddI; - DebugLoc Loc = Cmp->getDebugLoc(); - Instruction *UAddWithOverflow = CallInst::Create(F, {A, B}, "uadd.overflow", - InsertPt); - UAddWithOverflow->setDebugLoc(Loc); - Instruction *UAdd = ExtractValueInst::Create(UAddWithOverflow, 0, "uadd", - InsertPt); - UAdd->setDebugLoc(Loc); - Instruction *Overflow = ExtractValueInst::Create(UAddWithOverflow, 1, - "overflow", InsertPt); - Overflow->setDebugLoc(Loc); - Cmp->replaceAllUsesWith(Overflow); - AddI->replaceAllUsesWith(UAdd); - Cmp->eraseFromParent(); - AddI->eraseFromParent(); + Instruction *InPt = Add->hasOneUse() ? cast(Cmp) + : cast(Add); + replaceMathCmpWithIntrinsic(Add, Cmp, InPt, Intrinsic::uadd_with_overflow); return true; } diff --git a/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll b/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll index 6be9661cc63..9b881866cef 100644 --- a/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll +++ b/test/Transforms/CodeGenPrepare/X86/overflow-intrinsics.ll @@ -7,10 +7,10 @@ target triple = "x86_64-apple-darwin10.0.0" define i64 @test1(i64 %a, i64 %b) nounwind ssp { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: [[Q:%.*]] = select i1 [[OVERFLOW]], i64 [[B]], i64 42 +; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1 +; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42 ; CHECK-NEXT: ret i64 [[Q]] ; %add = add i64 %b, %a @@ -21,10 +21,10 @@ define i64 @test1(i64 %a, i64 %b) nounwind ssp { define i64 @test2(i64 %a, i64 %b) nounwind ssp { ; CHECK-LABEL: @test2( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: [[Q:%.*]] = select i1 [[OVERFLOW]], i64 [[B]], i64 42 +; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1 +; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42 ; CHECK-NEXT: ret i64 [[Q]] ; %add = add i64 %b, %a @@ -35,10 +35,10 @@ define i64 @test2(i64 %a, i64 %b) nounwind ssp { define i64 @test3(i64 %a, i64 %b) nounwind ssp { ; CHECK-LABEL: @test3( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: [[Q:%.*]] = select i1 [[OVERFLOW]], i64 [[B]], i64 42 +; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1 +; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42 ; CHECK-NEXT: ret i64 [[Q]] ; %add = add i64 %b, %a @@ -52,10 +52,10 @@ define i64 @test4(i64 %a, i64 %b, i1 %c) nounwind ssp { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C:%.*]], label [[NEXT:%.*]], label [[EXIT:%.*]] ; CHECK: next: -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: [[Q:%.*]] = select i1 [[OVERFLOW]], i64 [[B]], i64 42 +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]]) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42 ; CHECK-NEXT: ret i64 [[Q]] ; CHECK: exit: ; CHECK-NEXT: ret i64 0 @@ -105,11 +105,11 @@ exit: define i1 @uaddo_i64_increment(i64 %x, i64* %p) { ; CHECK-LABEL: @uaddo_i64_increment( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: store i64 [[UADD]], i64* [[P:%.*]] -; CHECK-NEXT: ret i1 [[OVERFLOW]] +; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1 +; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]] +; CHECK-NEXT: ret i1 [[OV1]] ; %a = add i64 %x, 1 %ov = icmp eq i64 %a, 0 @@ -119,11 +119,11 @@ define i1 @uaddo_i64_increment(i64 %x, i64* %p) { define i1 @uaddo_i8_increment_noncanonical_1(i8 %x, i8* %p) { ; CHECK-LABEL: @uaddo_i8_increment_noncanonical_1( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 1, i8 [[X:%.*]]) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i8, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i8, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: store i8 [[UADD]], i8* [[P:%.*]] -; CHECK-NEXT: ret i1 [[OVERFLOW]] +; CHECK-NEXT: [[TMP1:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 1, i8 [[X:%.*]]) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1 +; CHECK-NEXT: store i8 [[MATH]], i8* [[P:%.*]] +; CHECK-NEXT: ret i1 [[OV1]] ; %a = add i8 1, %x ; commute %ov = icmp eq i8 %a, 0 @@ -133,11 +133,11 @@ define i1 @uaddo_i8_increment_noncanonical_1(i8 %x, i8* %p) { define i1 @uaddo_i32_increment_noncanonical_2(i32 %x, i32* %p) { ; CHECK-LABEL: @uaddo_i32_increment_noncanonical_2( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i32, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i32, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: store i32 [[UADD]], i32* [[P:%.*]] -; CHECK-NEXT: ret i1 [[OVERFLOW]] +; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 +; CHECK-NEXT: store i32 [[MATH]], i32* [[P:%.*]] +; CHECK-NEXT: ret i1 [[OV1]] ; %a = add i32 %x, 1 %ov = icmp eq i32 0, %a ; commute @@ -147,11 +147,11 @@ define i1 @uaddo_i32_increment_noncanonical_2(i32 %x, i32* %p) { define i1 @uaddo_i16_increment_noncanonical_3(i16 %x, i16* %p) { ; CHECK-LABEL: @uaddo_i16_increment_noncanonical_3( -; CHECK-NEXT: [[UADD_OVERFLOW:%.*]] = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 1, i16 [[X:%.*]]) -; CHECK-NEXT: [[UADD:%.*]] = extractvalue { i16, i1 } [[UADD_OVERFLOW]], 0 -; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i16, i1 } [[UADD_OVERFLOW]], 1 -; CHECK-NEXT: store i16 [[UADD]], i16* [[P:%.*]] -; CHECK-NEXT: ret i1 [[OVERFLOW]] +; CHECK-NEXT: [[TMP1:%.*]] = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 1, i16 [[X:%.*]]) +; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0 +; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1 +; CHECK-NEXT: store i16 [[MATH]], i16* [[P:%.*]] +; CHECK-NEXT: ret i1 [[OV1]] ; %a = add i16 1, %x ; commute %ov = icmp eq i16 0, %a ; commute -- 2.40.0