summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp45
1 files changed, 28 insertions, 17 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index e9611392058..a6a4ea2aff9 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1159,19 +1159,33 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI,
return SinkCast(CI);
}
-static void replaceMathCmpWithIntrinsic(BinaryOperator *BO, CmpInst *Cmp,
- Instruction *InsertPt,
+static bool replaceMathCmpWithIntrinsic(BinaryOperator *BO, CmpInst *Cmp,
Intrinsic::ID IID) {
+ // We allow matching the canonical IR (add X, C) back to (usubo X, -C).
Value *Arg0 = BO->getOperand(0);
Value *Arg1 = BO->getOperand(1);
-
- // We allow matching the canonical IR (add X, C) back to (usubo X, -C).
if (BO->getOpcode() == Instruction::Add &&
IID == Intrinsic::usub_with_overflow) {
assert(isa<Constant>(Arg1) && "Unexpected input for usubo");
Arg1 = ConstantExpr::getNeg(cast<Constant>(Arg1));
}
+ Instruction *InsertPt;
+ if (BO->hasOneUse() && BO->user_back() == Cmp) {
+ // If the math is only used by the compare, insert at the compare to keep
+ // the condition in the same block as its users. (CGP aggressively sinks
+ // compares to help out SDAG.)
+ InsertPt = Cmp;
+ } else {
+ // The math and compare may be independent instructions. Check dominance to
+ // determine the insertion point for the intrinsic.
+ DominatorTree DT(*BO->getFunction());
+ bool MathDominates = DT.dominates(BO, Cmp);
+ if (!MathDominates && !DT.dominates(Cmp, BO))
+ return false;
+ InsertPt = MathDominates ? cast<Instruction>(BO) : cast<Instruction>(Cmp);
+ }
+
IRBuilder<> Builder(InsertPt);
Value *MathOV = Builder.CreateBinaryIntrinsic(IID, Arg0, Arg1);
Value *Math = Builder.CreateExtractValue(MathOV, 0, "math");
@@ -1180,12 +1194,13 @@ static void replaceMathCmpWithIntrinsic(BinaryOperator *BO, CmpInst *Cmp,
Cmp->replaceAllUsesWith(OV);
BO->eraseFromParent();
Cmp->eraseFromParent();
+ return true;
}
/// 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) {
+ const DataLayout &DL, bool &ModifiedDT) {
Value *A, *B;
BinaryOperator *Add;
if (!match(Cmp, m_UAddWithOverflow(m_Value(A), m_Value(B), m_BinOp(Add))))
@@ -1208,9 +1223,11 @@ static bool combineToUAddWithOverflow(CmpInst *Cmp, const TargetLowering &TLI,
assert(*Add->user_begin() == Cmp && "expected!");
#endif
- Instruction *InPt = Add->hasOneUse() ? cast<Instruction>(Cmp)
- : cast<Instruction>(Add);
- replaceMathCmpWithIntrinsic(Add, Cmp, InPt, Intrinsic::uadd_with_overflow);
+ if (!replaceMathCmpWithIntrinsic(Add, Cmp, Intrinsic::uadd_with_overflow))
+ return false;
+
+ // Reset callers - do not crash by iterating over a dead instruction.
+ ModifiedDT = true;
return true;
}
@@ -1263,15 +1280,9 @@ static bool combineToUSubWithOverflow(CmpInst *Cmp, const TargetLowering &TLI,
TLI.getValueType(DL, Sub->getType())))
return false;
- // Pattern matched and profitability checked. Check dominance to determine the
- // insertion point for an intrinsic that replaces the subtract and compare.
- DominatorTree DT(*Sub->getFunction());
- bool SubDominates = DT.dominates(Sub, Cmp);
- if (!SubDominates && !DT.dominates(Cmp, Sub))
+ if (!replaceMathCmpWithIntrinsic(Sub, Cmp, Intrinsic::usub_with_overflow))
return false;
- Instruction *InPt = SubDominates ? cast<Instruction>(Sub)
- : cast<Instruction>(Cmp);
- replaceMathCmpWithIntrinsic(Sub, Cmp, InPt, Intrinsic::usub_with_overflow);
+
// Reset callers - do not crash by iterating over a dead instruction.
ModifiedDT = true;
return true;
@@ -1348,7 +1359,7 @@ static bool optimizeCmp(CmpInst *Cmp, const TargetLowering &TLI,
if (sinkCmpExpression(Cmp, TLI))
return true;
- if (combineToUAddWithOverflow(Cmp, TLI, DL))
+ if (combineToUAddWithOverflow(Cmp, TLI, DL, ModifiedDT))
return true;
if (combineToUSubWithOverflow(Cmp, TLI, DL, ModifiedDT))
OpenPOWER on IntegriCloud