Skip to content

Commit

Permalink
[SimplifyIndVar] Inline makIVComparisonInvariant to eleminate code du…
Browse files Browse the repository at this point in the history
…plication [NFC]

This formulation might be slightly slower since I eagerly compute the cheap replacements.  If anyone sees this having a compile time impact, let me know and I'll use lazy population instead.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317048 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
preames committed Oct 31, 2017
1 parent fee1f22 commit 90b71c2
Showing 1 changed file with 29 additions and 51 deletions.
80 changes: 29 additions & 51 deletions lib/Transforms/Utils/SimplifyIndVar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,6 @@ namespace {

bool eliminateOverflowIntrinsic(CallInst *CI);
bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
bool isCheapLoopInvariantPredicate(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS, const Loop *L,
const SmallDenseMap<const SCEV*, Value*> &FreeExpansions,
ICmpInst::Predicate &InvariantPred,
Value *&LHSV, Value *& RHSV);
bool makeIVComparisonInvariant(ICmpInst *ICmp, Value *IVOperand);
void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
void simplifyIVRemainder(BinaryOperator *Rem, Value *IVOperand,
bool IsSigned);
Expand All @@ -98,6 +92,16 @@ namespace {
bool eliminateSDiv(BinaryOperator *SDiv);
bool strengthenOverflowingOperation(BinaryOperator *OBO, Value *IVOperand);
bool strengthenRightShift(BinaryOperator *BO, Value *IVOperand);


private:
// Wrapped around ScalarEvolution::isLoopInvariantPredicate which returns
// true only when a free expansion is available.
bool isCheapLoopInvariantPredicate(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS, const Loop *L,
const SmallDenseMap<const SCEV*, Value*> &FreeExpansions,
ICmpInst::Predicate &InvariantPred,
Value *&LHSV, Value *& RHSV);
};
}

Expand Down Expand Up @@ -187,10 +191,12 @@ bool SimplifyIndvar::isCheapLoopInvariantPredicate(ICmpInst::Predicate Pred,
return (LHSV && RHSV);
}

bool SimplifyIndvar::makeIVComparisonInvariant(ICmpInst *ICmp,
Value *IVOperand) {
/// SimplifyIVUsers helper for eliminating useless
/// comparisons against an induction variable.
void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
unsigned IVOperIdx = 0;
ICmpInst::Predicate Pred = ICmp->getPredicate();
ICmpInst::Predicate OriginalPred = Pred;
if (IVOperand != ICmp->getOperand(0)) {
// Swapped
assert(IVOperand == ICmp->getOperand(1) && "Can't find IVOperand");
Expand All @@ -204,57 +210,23 @@ bool SimplifyIndvar::makeIVComparisonInvariant(ICmpInst *ICmp,
const SCEV *S = SE->getSCEVAtScope(ICmp->getOperand(IVOperIdx), ICmpLoop);
const SCEV *X = SE->getSCEVAtScope(ICmp->getOperand(1 - IVOperIdx), ICmpLoop);

auto *PN = dyn_cast<PHINode>(IVOperand);
if (!PN)
return false;

SmallDenseMap<const SCEV*, Value*> CheapExpansions;
CheapExpansions[S] = ICmp->getOperand(IVOperIdx);
CheapExpansions[X] = ICmp->getOperand(1 - IVOperIdx);

// TODO: Support multiple entry loops? (We currently bail out of these in
// the IndVarSimplify pass)
if (auto *BB = L->getLoopPredecessor()) {
Value *Incoming = PN->getIncomingValueForBlock(BB);
const SCEV *IncomingS = SE->getSCEV(Incoming);
CheapExpansions[IncomingS] = Incoming;
}
auto *PN = dyn_cast<PHINode>(IVOperand);
if (PN)
if (auto *BB = L->getLoopPredecessor()) {
Value *Incoming = PN->getIncomingValueForBlock(BB);
const SCEV *IncomingS = SE->getSCEV(Incoming);
CheapExpansions[IncomingS] = Incoming;
}

ICmpInst::Predicate NewPred;
Value *NewLHS = nullptr, *NewRHS = nullptr;

if (!isCheapLoopInvariantPredicate(Pred, S, X, L, CheapExpansions,
NewPred, NewLHS, NewRHS))
return false;

assert(NewLHS && NewRHS);

DEBUG(dbgs() << "INDVARS: Simplified comparison: " << *ICmp << '\n');
ICmp->setPredicate(NewPred);
ICmp->setOperand(0, NewLHS);
ICmp->setOperand(1, NewRHS);
return true;
}

/// SimplifyIVUsers helper for eliminating useless
/// comparisons against an induction variable.
void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
unsigned IVOperIdx = 0;
ICmpInst::Predicate Pred = ICmp->getPredicate();
ICmpInst::Predicate OriginalPred = Pred;
if (IVOperand != ICmp->getOperand(0)) {
// Swapped
assert(IVOperand == ICmp->getOperand(1) && "Can't find IVOperand");
IVOperIdx = 1;
Pred = ICmpInst::getSwappedPredicate(Pred);
}

// Get the SCEVs for the ICmp operands (in the specific context of the
// current loop)
const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
const SCEV *S = SE->getSCEVAtScope(ICmp->getOperand(IVOperIdx), ICmpLoop);
const SCEV *X = SE->getSCEVAtScope(ICmp->getOperand(1 - IVOperIdx), ICmpLoop);

// If the condition is always true or always false, replace it with
// a constant value.
if (SE->isKnownPredicate(Pred, S, X)) {
Expand All @@ -265,8 +237,14 @@ void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
DeadInsts.emplace_back(ICmp);
DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n');
} else if (makeIVComparisonInvariant(ICmp, IVOperand)) {
// fallthrough to end of function
} else if (PN &&
isCheapLoopInvariantPredicate(Pred, S, X, L, CheapExpansions,
NewPred, NewLHS, NewRHS)) {
DEBUG(dbgs() << "INDVARS: Simplified comparison: " << *ICmp << '\n');
ICmp->setPredicate(NewPred);
assert(NewLHS && NewRHS);
ICmp->setOperand(0, NewLHS);
ICmp->setOperand(1, NewRHS);
} else if (ICmpInst::isSigned(OriginalPred) &&
SE->isKnownNonNegative(S) && SE->isKnownNonNegative(X)) {
// If we were unable to make anything above, all we can is to canonicalize
Expand Down

0 comments on commit 90b71c2

Please sign in to comment.