Skip to content

Commit

Permalink
[SCEV] Handling for ICmp occuring in the evolution chain.
Browse files Browse the repository at this point in the history
Summary:
 If a compare instruction is same or inverse of the compare in the
 branch of the loop latch, then return a constant evolution node.
 This shall facilitate computations of loop exit counts in cases
 where compare appears in the evolution chain of induction variables.

 Will fix PR 34538

Reviewers: sanjoy, hfinkel, junryoungju

Reviewed By: sanjoy, junryoungju

Subscribers: javed.absar, llvm-commits

Differential Revision: https://reviews.llvm.org/D38494

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318050 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
jbhateja committed Nov 13, 2017
1 parent e618886 commit 5afa924
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 8 deletions.
94 changes: 87 additions & 7 deletions lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4080,6 +4080,85 @@ class SCEVInitRewriter : public SCEVRewriteVisitor<SCEVInitRewriter> {
bool Valid = true;
};

/// This class evaluates the compare condition by matching it against the
/// condition of loop latch. If there is a match we assume a true value
/// for the condition while building SCEV nodes.
class SCEVBackedgeConditionFolder
: public SCEVRewriteVisitor<SCEVBackedgeConditionFolder> {
public:
static const SCEV *rewrite(const SCEV *S, const Loop *L,
ScalarEvolution &SE) {
bool IsPosBECond;
Value *BECond = nullptr;
if (BasicBlock *Latch = L->getLoopLatch()) {
BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator());
if (BI && BI->isConditional() &&
BI->getSuccessor(0) != BI->getSuccessor(1)) {
BECond = BI->getCondition();
IsPosBECond = BI->getSuccessor(0) == L->getHeader();
} else {
return S;
}
}
SCEVBackedgeConditionFolder Rewriter(L, BECond, IsPosBECond, SE);
return Rewriter.visit(S);
}

const SCEV *visitUnknown(const SCEVUnknown *Expr) {
const SCEV *Result = Expr;
bool InvariantF = SE.isLoopInvariant(Expr, L);

if (!InvariantF) {
Instruction *I = cast<Instruction>(Expr->getValue());
switch (I->getOpcode()) {
case Instruction::Select: {
SelectInst *SI = cast<SelectInst>(I);
Optional<const SCEV *> Res =
compareWithBackedgeCondition(SI->getCondition());
if (Res.hasValue()) {
bool IsOne = cast<SCEVConstant>(Res.getValue())->getValue()->isOne();
Result = SE.getSCEV(IsOne ? SI->getTrueValue() : SI->getFalseValue());
}
break;
}
default: {
Optional<const SCEV *> Res = compareWithBackedgeCondition(I);
if (Res.hasValue())
Result = Res.getValue();
break;
}
}
}
return Result;
}

private:
explicit SCEVBackedgeConditionFolder(const Loop *L, Value *BECond,
bool IsPosBECond, ScalarEvolution &SE)
: SCEVRewriteVisitor(SE), L(L), BackedgeCond(BECond),
IsPositiveBECond(IsPosBECond) {}

Optional<const SCEV *> compareWithBackedgeCondition(Value *IC);

const Loop *L;
/// Loop back condition.
Value *BackedgeCond = nullptr;
/// Set to true if loop back is on positive branch condition.
bool IsPositiveBECond;
};

Optional<const SCEV *>
SCEVBackedgeConditionFolder::compareWithBackedgeCondition(Value *IC) {

// If value matches the backedge condition for loop latch,
// then return a constant evolution node based on loopback
// branch taken.
if (BackedgeCond == IC)
return IsPositiveBECond ? SE.getOne(Type::getInt1Ty(SE.getContext()))
: SE.getZero(Type::getInt1Ty(SE.getContext()));
return None;
}

class SCEVShiftRewriter : public SCEVRewriteVisitor<SCEVShiftRewriter> {
public:
SCEVShiftRewriter(const Loop *L, ScalarEvolution &SE)
Expand Down Expand Up @@ -4753,7 +4832,8 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
SmallVector<const SCEV *, 8> Ops;
for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
if (i != FoundIndex)
Ops.push_back(Add->getOperand(i));
Ops.push_back(SCEVBackedgeConditionFolder::rewrite(Add->getOperand(i),
L, *this));
const SCEV *Accum = getAddExpr(Ops);

// This is not a valid addrec if the step amount is varying each
Expand All @@ -4779,33 +4859,33 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
// indices form a positive value.
if (GEP->isInBounds() && GEP->getOperand(0) == PN) {
Flags = setFlags(Flags, SCEV::FlagNW);

const SCEV *Ptr = getSCEV(GEP->getPointerOperand());
if (isKnownPositive(getMinusSCEV(getSCEV(GEP), Ptr)))
Flags = setFlags(Flags, SCEV::FlagNUW);
}

// We cannot transfer nuw and nsw flags from subtraction
// operations -- sub nuw X, Y is not the same as add nuw X, -Y
// for instance.
}

const SCEV *StartVal = getSCEV(StartValueV);
const SCEV *PHISCEV = getAddRecExpr(StartVal, Accum, L, Flags);

// Okay, for the entire analysis of this edge we assumed the PHI
// to be symbolic. We now need to go back and purge all of the
// entries for the scalars that use the symbolic expression.
forgetSymbolicName(PN, SymbolicName);
ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV;

// We can add Flags to the post-inc expression only if we
// know that it is *undefined behavior* for BEValueV to
// overflow.
if (auto *BEInst = dyn_cast<Instruction>(BEValueV))
if (isLoopInvariant(Accum, L) && isAddRecNeverPoison(BEInst, L))
(void)getAddRecExpr(getAddExpr(StartVal, Accum), Accum, L, Flags);

return PHISCEV;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Transforms/Scalar/LoopStrengthReduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2970,7 +2970,7 @@ void LSRInstance::CollectChains() {
// consider leaf IV Users. This effectively rediscovers a portion of
// IVUsers analysis but in program order this time.
if (SE.isSCEVable(I.getType()) && !isa<SCEVUnknown>(SE.getSCEV(&I)))
continue;
continue;

// Remove this instruction from any NearUsers set it may be in.
for (unsigned ChainIdx = 0, NChains = IVChainVec.size();
Expand Down
39 changes: 39 additions & 0 deletions test/Analysis/ScalarEvolution/pr34538.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; RUN: opt -scalar-evolution -loop-deletion -simplifycfg -analyze < %s | FileCheck %s --check-prefix=CHECK-ANALYSIS-1
; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s --check-prefix=CHECK-ANALYSIS-2

define i32 @pr34538() local_unnamed_addr #0 {
; CHECK-ANALYSIS-1: Loop %do.body: backedge-taken count is 10000
; CHECK-ANALYSIS-1: Loop %do.body: max backedge-taken count is 10000
; CHECK-ANALYSIS-1: Loop %do.body: Predicated backedge-taken count is 10000
entry:
br label %do.body

do.body: ; preds = %do.body, %entry
%start.0 = phi i32 [ 0, %entry ], [ %inc.start.0, %do.body ]
%cmp = icmp slt i32 %start.0, 10000
%inc = zext i1 %cmp to i32
%inc.start.0 = add nsw i32 %start.0, %inc
br i1 %cmp, label %do.body, label %do.end

do.end: ; preds = %do.body
ret i32 0
}


define i32 @foo() {
entry:
br label %do.body

do.body: ; preds = %do.body, %entry
%start.0 = phi i32 [ 0, %entry ], [ %inc.start.0, %do.body ]
%cmp = icmp slt i32 %start.0, 10000
%select_ext = select i1 %cmp, i32 2 , i32 1
%inc.start.0 = add nsw i32 %start.0, %select_ext
br i1 %cmp, label %do.body, label %do.end

do.end: ; preds = %do.body
ret i32 0
; CHECK-ANALYSIS-2: Loop %do.body: backedge-taken count is 5000
; CHECK-ANALYSIS-2: Loop %do.body: max backedge-taken count is 5000
; CHECK-ANALYSIS-2: Loop %do.body: Predicated backedge-taken count is 5000
}

0 comments on commit 5afa924

Please sign in to comment.