return SinkCast(CI);
}
-/// Try to combine CI into a call to the llvm.uadd.with.overflow intrinsic if
-/// possible.
-///
-/// Return true if any changes were made.
-static bool CombineUAddWithOverflow(CmpInst *CI) {
+/// 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) {
+ // TODO: Why is this transform limited by this condition?
+ if (TLI.hasMultipleConditionRegisters())
+ return false;
+
Value *A, *B;
Instruction *AddI;
- if (!match(CI,
+ if (!match(Cmp,
m_UAddWithOverflow(m_Value(A), m_Value(B), m_Instruction(AddI))))
return false;
// We don't want to move around uses of condition values this late, so we we
// check if it is legal to create the call to the intrinsic in the basic
// block containing the icmp:
-
- if (AddI->getParent() != CI->getParent() && !AddI->hasOneUse())
+ if (AddI->getParent() != Cmp->getParent() && !AddI->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() == CI && "expected!");
+ assert(*AddI->user_begin() == Cmp && "expected!");
#endif
- Module *M = CI->getModule();
+ Module *M = Cmp->getModule();
Function *F = Intrinsic::getDeclaration(M, Intrinsic::uadd_with_overflow, Ty);
-
- auto *InsertPt = AddI->hasOneUse() ? CI : AddI;
-
- DebugLoc Loc = CI->getDebugLoc();
- auto *UAddWithOverflow =
- CallInst::Create(F, {A, B}, "uadd.overflow", InsertPt);
+ Instruction *InsertPt = AddI->hasOneUse() ? Cmp : AddI;
+ DebugLoc Loc = Cmp->getDebugLoc();
+ Instruction *UAddWithOverflow = CallInst::Create(F, {A, B}, "uadd.overflow",
+ InsertPt);
UAddWithOverflow->setDebugLoc(Loc);
- auto *UAdd = ExtractValueInst::Create(UAddWithOverflow, 0, "uadd", InsertPt);
+ Instruction *UAdd = ExtractValueInst::Create(UAddWithOverflow, 0, "uadd",
+ InsertPt);
UAdd->setDebugLoc(Loc);
- auto *Overflow =
- ExtractValueInst::Create(UAddWithOverflow, 1, "overflow", InsertPt);
+ Instruction *Overflow = ExtractValueInst::Create(UAddWithOverflow, 1,
+ "overflow", InsertPt);
Overflow->setDebugLoc(Loc);
-
- CI->replaceAllUsesWith(Overflow);
+ Cmp->replaceAllUsesWith(Overflow);
AddI->replaceAllUsesWith(UAdd);
- CI->eraseFromParent();
+ Cmp->eraseFromParent();
AddI->eraseFromParent();
return true;
}
/// lose; some adjustment may be wanted there.
///
/// Return true if any changes are made.
-static bool SinkCmpExpression(CmpInst *CI, const TargetLowering *TLI) {
- BasicBlock *DefBB = CI->getParent();
+static bool sinkCmpExpression(CmpInst *Cmp, const TargetLowering &TLI) {
+ if (TLI.hasMultipleConditionRegisters())
+ return false;
// Avoid sinking soft-FP comparisons, since this can move them into a loop.
- if (TLI && TLI->useSoftFloat() && isa<FCmpInst>(CI))
+ if (TLI.useSoftFloat() && isa<FCmpInst>(Cmp))
return false;
// Only insert a cmp in each block once.
DenseMap<BasicBlock*, CmpInst*> InsertedCmps;
bool MadeChange = false;
- for (Value::user_iterator UI = CI->user_begin(), E = CI->user_end();
+ for (Value::user_iterator UI = Cmp->user_begin(), E = Cmp->user_end();
UI != E; ) {
Use &TheUse = UI.getUse();
Instruction *User = cast<Instruction>(*UI);
// Figure out which BB this cmp is used in.
BasicBlock *UserBB = User->getParent();
+ BasicBlock *DefBB = Cmp->getParent();
// If this user is in the same block as the cmp, don't change the cmp.
if (UserBB == DefBB) continue;
BasicBlock::iterator InsertPt = UserBB->getFirstInsertionPt();
assert(InsertPt != UserBB->end());
InsertedCmp =
- CmpInst::Create(CI->getOpcode(), CI->getPredicate(),
- CI->getOperand(0), CI->getOperand(1), "", &*InsertPt);
+ CmpInst::Create(Cmp->getOpcode(), Cmp->getPredicate(),
+ Cmp->getOperand(0), Cmp->getOperand(1), "",
+ &*InsertPt);
// Propagate the debug info.
- InsertedCmp->setDebugLoc(CI->getDebugLoc());
+ InsertedCmp->setDebugLoc(Cmp->getDebugLoc());
}
// Replace a use of the cmp with a use of the new cmp.
}
// If we removed all uses, nuke the cmp.
- if (CI->use_empty()) {
- CI->eraseFromParent();
+ if (Cmp->use_empty()) {
+ Cmp->eraseFromParent();
MadeChange = true;
}
return MadeChange;
}
-static bool OptimizeCmpExpression(CmpInst *CI, const TargetLowering *TLI) {
- if (SinkCmpExpression(CI, TLI))
+static bool optimizeCmpExpression(CmpInst *Cmp, const TargetLowering &TLI) {
+ if (sinkCmpExpression(Cmp, TLI))
return true;
- if (CombineUAddWithOverflow(CI))
+ if (combineToUAddWithOverflow(Cmp, TLI))
return true;
return false;
}
if (CmpInst *CI = dyn_cast<CmpInst>(I))
- if (!TLI || !TLI->hasMultipleConditionRegisters())
- return OptimizeCmpExpression(CI, TLI);
+ if (TLI && optimizeCmpExpression(CI, *TLI))
+ return true;
if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
LI->setMetadata(LLVMContext::MD_invariant_group, nullptr);