diff options
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index bcb899a9e02..4792e810a85 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/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<IntegerType>(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<Instruction>(Cmp) + : cast<Instruction>(Add); + replaceMathCmpWithIntrinsic(Add, Cmp, InPt, Intrinsic::uadd_with_overflow); return true; } |

