Skip to content

Commit

Permalink
[IndVars] Have getInsertPointForUses preserve LCSSA
Browse files Browse the repository at this point in the history
Summary:
Also add a stricter post-condition for IndVarSimplify.

Fixes PR25578.  Test case by Michael Zolotukhin.

Reviewers: hfinkel, atrick, mzolotukhin

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D15059

llvm-svn: 254977
  • Loading branch information
sanjoy committed Dec 8, 2015
1 parent b771eb6 commit 683bf07
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 14 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/Analysis/LoopInfo.h
Expand Up @@ -402,6 +402,9 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// isLCSSAForm - Return true if the Loop is in LCSSA form
bool isLCSSAForm(DominatorTree &DT) const;

/// \brief Return true if this Loop and all inner subloops are in LCSSA form.
bool isRecursivelyLCSSAForm(DominatorTree &DT) const;

/// isLoopSimplifyForm - Return true if the Loop is in the form that
/// the LoopSimplify form transforms loops to, which is sometimes called
/// normal form.
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Analysis/LoopInfo.cpp
Expand Up @@ -200,6 +200,15 @@ bool Loop::isLCSSAForm(DominatorTree &DT) const {
return true;
}

bool Loop::isRecursivelyLCSSAForm(DominatorTree &DT) const {
if (!isLCSSAForm(DT))
return false;

return std::all_of(begin(), end(), [&](const Loop *L) {
return L->isRecursivelyLCSSAForm(DT);
});
}

/// isLoopSimplifyForm - Return true if the Loop is in the form that
/// the LoopSimplify form transforms loops to, which is sometimes called
/// normal form.
Expand Down
42 changes: 28 additions & 14 deletions llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Expand Up @@ -50,6 +50,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/SimplifyIndVar.h"
using namespace llvm;

Expand Down Expand Up @@ -215,7 +216,7 @@ bool IndVarSimplify::isValidRewrite(Value *FromVal, Value *ToVal) {
/// loop. For PHI nodes, there may be multiple uses, so compute the nearest
/// common dominator for the incoming blocks.
static Instruction *getInsertPointForUses(Instruction *User, Value *Def,
DominatorTree *DT) {
DominatorTree *DT, LoopInfo *LI) {
PHINode *PHI = dyn_cast<PHINode>(User);
if (!PHI)
return User;
Expand All @@ -234,10 +235,21 @@ static Instruction *getInsertPointForUses(Instruction *User, Value *Def,
InsertPt = InsertBB->getTerminator();
}
assert(InsertPt && "Missing phi operand");
assert((!isa<Instruction>(Def) ||
DT->dominates(cast<Instruction>(Def), InsertPt)) &&
"def does not dominate all uses");
return InsertPt;

auto *DefI = dyn_cast<Instruction>(Def);
if (!DefI)
return InsertPt;

assert(DT->dominates(DefI, InsertPt) && "def does not dominate all uses");

auto *L = LI->getLoopFor(DefI->getParent());
assert(!L || L->contains(LI->getLoopFor(InsertPt->getParent())));

for (auto *DTN = (*DT)[InsertPt->getParent()]; DTN; DTN = DTN->getIDom())
if (LI->getLoopFor(DTN->getBlock()) == L)
return DTN->getBlock()->getTerminator();

llvm_unreachable("DefI dominates InsertPt!");
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -528,8 +540,8 @@ Value *IndVarSimplify::expandSCEVIfNeeded(SCEVExpander &Rewriter, const SCEV *S,
/// able to brute-force evaluate arbitrary instructions as long as they have
/// constant operands at the beginning of the loop.
void IndVarSimplify::rewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
// Verify the input to the pass in already in LCSSA form.
assert(L->isLCSSAForm(*DT));
// Check a pre-condition.
assert(L->isRecursivelyLCSSAForm(*DT) && "Indvars did not preserve LCSSA!");

SmallVector<BasicBlock*, 8> ExitBlocks;
L->getUniqueExitBlocks(ExitBlocks);
Expand Down Expand Up @@ -1167,10 +1179,11 @@ const SCEVAddRecExpr *WidenIV::getWideRecurrence(Instruction *NarrowUse) {

/// This IV user cannot be widen. Replace this use of the original narrow IV
/// with a truncation of the new wide IV to isolate and eliminate the narrow IV.
static void truncateIVUse(NarrowIVDefUse DU, DominatorTree *DT) {
static void truncateIVUse(NarrowIVDefUse DU, DominatorTree *DT, LoopInfo *LI) {
DEBUG(dbgs() << "INDVARS: Truncate IV " << *DU.WideDef
<< " for user " << *DU.NarrowUse << "\n");
IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT));
IRBuilder<> Builder(
getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT, LI));
Value *Trunc = Builder.CreateTrunc(DU.WideDef, DU.NarrowDef->getType());
DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, Trunc);
}
Expand Down Expand Up @@ -1207,7 +1220,8 @@ bool WidenIV::widenLoopCompare(NarrowIVDefUse DU) {
assert (CastWidth <= IVWidth && "Unexpected width while widening compare.");

// Widen the compare instruction.
IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT));
IRBuilder<> Builder(
getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT, LI));
DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, DU.WideDef);

// Widen the other operand of the compare, if necessary.
Expand All @@ -1229,7 +1243,7 @@ Instruction *WidenIV::widenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) {
// After SimplifyCFG most loop exit targets have a single predecessor.
// Otherwise fall back to a truncate within the loop.
if (UsePhi->getNumOperands() != 1)
truncateIVUse(DU, DT);
truncateIVUse(DU, DT, LI);
else {
PHINode *WidePhi =
PHINode::Create(DU.WideDef->getType(), 1, UsePhi->getName() + ".wide",
Expand Down Expand Up @@ -1297,7 +1311,7 @@ Instruction *WidenIV::widenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) {
// This user does not evaluate to a recurence after widening, so don't
// follow it. Instead insert a Trunc to kill off the original use,
// eventually isolating the original narrow IV so it can be removed.
truncateIVUse(DU, DT);
truncateIVUse(DU, DT, LI);
return nullptr;
}
// Assume block terminators cannot evaluate to a recurrence. We can't to
Expand Down Expand Up @@ -2165,9 +2179,9 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {

// Clean up dead instructions.
Changed |= DeleteDeadPHIs(L->getHeader(), TLI);

// Check a post-condition.
assert(L->isLCSSAForm(*DT) &&
"Indvars did not leave the loop in lcssa form!");
assert(L->isRecursivelyLCSSAForm(*DT) && "Indvars did not preserve LCSSA!");

// Verify that LFTR, and any other change have not interfered with SCEV's
// ability to compute trip count.
Expand Down
45 changes: 45 additions & 0 deletions llvm/test/Transforms/IndVarSimplify/pr25578.ll
@@ -0,0 +1,45 @@
; RUN: opt < %s -indvars -S | FileCheck %s
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

; CHECK-LABEL: @foo
define void @foo() {
entry:
br label %L1_header

L1_header:
br label %L2_header

; CHECK: L2_header:
; CHECK: %[[INDVAR:.*]] = phi i64
; CHECK: %[[TRUNC:.*]] = trunc i64 %[[INDVAR]] to i32
L2_header:
%i = phi i32 [ 0, %L1_header ], [ %i_next, %L2_latch ]
%i_prom = sext i32 %i to i64
br label %L3_header

L3_header:
br i1 undef, label %L3_latch, label %L2_exiting_1

L3_latch:
br i1 undef, label %L3_header, label %L2_exiting_2

L2_exiting_1:
br i1 undef, label %L2_latch, label %L1_latch

L2_exiting_2:
br i1 undef, label %L2_latch, label %L1_latch

L2_latch:
%i_next = add nsw i32 %i, 1
br label %L2_header

L1_latch:
; CHECK: L1_latch:
; CHECK: %i_lcssa = phi i32 [ %[[TRUNC]], %L2_exiting_1 ], [ %[[TRUNC]], %L2_exiting_2 ]

%i_lcssa = phi i32 [ %i, %L2_exiting_1 ], [ %i, %L2_exiting_2 ]
br i1 undef, label %exit, label %L1_header

exit:
ret void
}

0 comments on commit 683bf07

Please sign in to comment.