Skip to content

Commit d5c56c5

Browse files
committed
[SCEVExpander] Remember phi nodes inserted by LCSSA construction
SCEVExpander keeps track of all instructions it inserted. However, it currently misses some phi nodes created during LCSSA construction. Fix this by collecting these into another argument. This also removes the IRBuilder argument, which was added for essentially the same purpose, but only handles the root LCSSA nodes, not those inserted by SSAUpdater. This was reported as a regression on D149344, but the reduced test case also reproduces without it. Differential Revision: https://reviews.llvm.org/D150681
1 parent cfd9093 commit d5c56c5

File tree

6 files changed

+100
-21
lines changed

6 files changed

+100
-21
lines changed

llvm/include/llvm/Transforms/Utils/LoopUtils.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,13 @@ bool formDedicatedExitBlocks(Loop *L, DominatorTree *DT, LoopInfo *LI,
7676
/// This function may introduce unused PHI nodes. If \p PHIsToRemove is not
7777
/// nullptr, those are added to it (before removing, the caller has to check if
7878
/// they still do not have any uses). Otherwise the PHIs are directly removed.
79+
///
80+
/// If \p InsertedPHIs is not nullptr, inserted phis will be added to this
81+
/// vector.
7982
bool formLCSSAForInstructions(
8083
SmallVectorImpl<Instruction *> &Worklist, const DominatorTree &DT,
81-
const LoopInfo &LI, IRBuilderBase &Builder,
82-
SmallVectorImpl<PHINode *> *PHIsToRemove = nullptr);
84+
const LoopInfo &LI, SmallVectorImpl<PHINode *> *PHIsToRemove = nullptr,
85+
SmallVectorImpl<PHINode *> *InsertedPHIs = nullptr);
8386

8487
/// Put loop into LCSSA form.
8588
///

llvm/lib/Transforms/Scalar/LoopInterchange.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "llvm/IR/DiagnosticInfo.h"
3131
#include "llvm/IR/Dominators.h"
3232
#include "llvm/IR/Function.h"
33-
#include "llvm/IR/IRBuilder.h"
3433
#include "llvm/IR/InstrTypes.h"
3534
#include "llvm/IR/Instruction.h"
3635
#include "llvm/IR/Instructions.h"
@@ -1686,12 +1685,11 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
16861685
// latch. In that case, we need to create LCSSA phis for them, because after
16871686
// interchanging they will be defined in the new inner loop and used in the
16881687
// new outer loop.
1689-
IRBuilder<> Builder(OuterLoopHeader->getContext());
16901688
SmallVector<Instruction *, 4> MayNeedLCSSAPhis;
16911689
for (Instruction &I :
16921690
make_range(OuterLoopHeader->begin(), std::prev(OuterLoopHeader->end())))
16931691
MayNeedLCSSAPhis.push_back(&I);
1694-
formLCSSAForInstructions(MayNeedLCSSAPhis, *DT, *LI, Builder);
1692+
formLCSSAForInstructions(MayNeedLCSSAPhis, *DT, *LI);
16951693

16961694
return true;
16971695
}

llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5659,8 +5659,7 @@ void LSRInstance::RewriteForPHI(
56595659
}
56605660
}
56615661

5662-
IRBuilder<> Builder(L->getHeader()->getContext());
5663-
formLCSSAForInstructions(InsertedNonLCSSAInsts, DT, LI, Builder);
5662+
formLCSSAForInstructions(InsertedNonLCSSAInsts, DT, LI);
56645663
}
56655664

56665665
/// Emit instructions for the leading candidate expression for this LSRUse (this

llvm/lib/Transforms/Utils/LCSSA.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
4141
#include "llvm/IR/DebugInfo.h"
4242
#include "llvm/IR/Dominators.h"
43-
#include "llvm/IR/IRBuilder.h"
4443
#include "llvm/IR/Instructions.h"
4544
#include "llvm/IR/IntrinsicInst.h"
4645
#include "llvm/IR/PredIteratorCache.h"
@@ -77,15 +76,13 @@ static bool isExitBlock(BasicBlock *BB,
7776
/// rewrite the uses.
7877
bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
7978
const DominatorTree &DT, const LoopInfo &LI,
80-
IRBuilderBase &Builder,
81-
SmallVectorImpl<PHINode *> *PHIsToRemove) {
79+
SmallVectorImpl<PHINode *> *PHIsToRemove,
80+
SmallVectorImpl<PHINode *> *InsertedPHIs) {
8281
SmallVector<Use *, 16> UsesToRewrite;
8382
SmallSetVector<PHINode *, 16> LocalPHIsToRemove;
8483
PredIteratorCache PredCache;
8584
bool Changed = false;
8685

87-
IRBuilderBase::InsertPointGuard InsertPtGuard(Builder);
88-
8986
// Cache the Loop ExitBlocks across this loop. We expect to get a lot of
9087
// instructions within the same loops, computing the exit blocks is
9188
// expensive, and we're not mutating the loop structure.
@@ -146,8 +143,8 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
146143
SmallVector<PHINode *, 16> AddedPHIs;
147144
SmallVector<PHINode *, 8> PostProcessPHIs;
148145

149-
SmallVector<PHINode *, 4> InsertedPHIs;
150-
SSAUpdater SSAUpdate(&InsertedPHIs);
146+
SmallVector<PHINode *, 4> LocalInsertedPHIs;
147+
SSAUpdater SSAUpdate(&LocalInsertedPHIs);
151148
SSAUpdate.Initialize(I->getType(), I->getName());
152149

153150
// Insert the LCSSA phi's into all of the exit blocks dominated by the
@@ -159,9 +156,10 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
159156
// If we already inserted something for this BB, don't reprocess it.
160157
if (SSAUpdate.HasValueForBlock(ExitBB))
161158
continue;
162-
Builder.SetInsertPoint(&ExitBB->front());
163-
PHINode *PN = Builder.CreatePHI(I->getType(), PredCache.size(ExitBB),
164-
I->getName() + ".lcssa");
159+
PHINode *PN = PHINode::Create(I->getType(), PredCache.size(ExitBB),
160+
I->getName() + ".lcssa", &ExitBB->front());
161+
if (InsertedPHIs)
162+
InsertedPHIs->push_back(PN);
165163
// Get the debug location from the original instruction.
166164
PN->setDebugLoc(I->getDebugLoc());
167165

@@ -251,10 +249,12 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
251249

252250
// SSAUpdater might have inserted phi-nodes inside other loops. We'll need
253251
// to post-process them to keep LCSSA form.
254-
for (PHINode *InsertedPN : InsertedPHIs) {
252+
for (PHINode *InsertedPN : LocalInsertedPHIs) {
255253
if (auto *OtherLoop = LI.getLoopFor(InsertedPN->getParent()))
256254
if (!L->contains(OtherLoop))
257255
PostProcessPHIs.push_back(InsertedPN);
256+
if (InsertedPHIs)
257+
InsertedPHIs->push_back(InsertedPN);
258258
}
259259

260260
// Post process PHI instructions that were inserted into another disjoint
@@ -386,8 +386,7 @@ bool llvm::formLCSSA(Loop &L, const DominatorTree &DT, const LoopInfo *LI) {
386386
}
387387
}
388388

389-
IRBuilder<> Builder(L.getHeader()->getContext());
390-
Changed = formLCSSAForInstructions(Worklist, DT, *LI, Builder);
389+
Changed = formLCSSAForInstructions(Worklist, DT, *LI);
391390

392391
assert(L.isLCSSAForm(DT));
393392

llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2561,7 +2561,11 @@ Value *SCEVExpander::fixupLCSSAFormFor(Value *V) {
25612561
SmallVector<Instruction *, 1> ToUpdate;
25622562
ToUpdate.push_back(DefI);
25632563
SmallVector<PHINode *, 16> PHIsToRemove;
2564-
formLCSSAForInstructions(ToUpdate, SE.DT, SE.LI, Builder, &PHIsToRemove);
2564+
SmallVector<PHINode *, 16> InsertedPHIs;
2565+
formLCSSAForInstructions(ToUpdate, SE.DT, SE.LI, &PHIsToRemove,
2566+
&InsertedPHIs);
2567+
for (PHINode *PN : InsertedPHIs)
2568+
rememberInstruction(PN);
25652569
for (PHINode *PN : PHIsToRemove) {
25662570
if (!PN->use_empty())
25672571
continue;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt -S -passes=loop-idiom < %s | FileCheck %s
3+
4+
; Make sure that any inserted LCSSA phi nodes are removed if the transform
5+
; is aborted.
6+
7+
define void @test() {
8+
; CHECK-LABEL: define void @test() {
9+
; CHECK-NEXT: entry:
10+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [64 x i8], align 16
11+
; CHECK-NEXT: br label [[LOOP:%.*]]
12+
; CHECK: loop:
13+
; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ 1, [[LOOP_LATCH:%.*]] ]
14+
; CHECK-NEXT: br i1 false, label [[LOOP_EXIT2:%.*]], label [[LOOP_LATCH]]
15+
; CHECK: loop.latch:
16+
; CHECK-NEXT: [[OR:%.*]] = or i64 [[PHI]], 4
17+
; CHECK-NEXT: br i1 false, label [[LOOP_EXIT:%.*]], label [[LOOP]]
18+
; CHECK: loop.exit:
19+
; CHECK-NEXT: [[OR_LCSSA:%.*]] = phi i64 [ [[OR]], [[LOOP_LATCH]] ]
20+
; CHECK-NEXT: br label [[LOOP2_PREHEADER:%.*]]
21+
; CHECK: loop.exit2:
22+
; CHECK-NEXT: br label [[LOOP2_PREHEADER]]
23+
; CHECK: loop2.preheader:
24+
; CHECK-NEXT: [[PHI5_PH:%.*]] = phi ptr [ null, [[LOOP_EXIT2]] ], [ [[ALLOCA]], [[LOOP_EXIT]] ]
25+
; CHECK-NEXT: [[PHI6_PH:%.*]] = phi i64 [ 0, [[LOOP_EXIT2]] ], [ [[OR_LCSSA]], [[LOOP_EXIT]] ]
26+
; CHECK-NEXT: br label [[LOOP2:%.*]]
27+
; CHECK: loop2:
28+
; CHECK-NEXT: [[PHI5:%.*]] = phi ptr [ [[GETELEMENTPTR7:%.*]], [[LOOP2]] ], [ [[PHI5_PH]], [[LOOP2_PREHEADER]] ]
29+
; CHECK-NEXT: [[PHI6:%.*]] = phi i64 [ [[ADD:%.*]], [[LOOP2]] ], [ [[PHI6_PH]], [[LOOP2_PREHEADER]] ]
30+
; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i8, ptr [[ALLOCA]], i64 [[PHI6]]
31+
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[GETELEMENTPTR]], align 1
32+
; CHECK-NEXT: store i8 [[LOAD]], ptr [[PHI5]], align 1
33+
; CHECK-NEXT: [[GETELEMENTPTR7]] = getelementptr i8, ptr [[PHI5]], i64 1
34+
; CHECK-NEXT: [[ADD]] = add i64 [[PHI6]], 1
35+
; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[PHI6]], 0
36+
; CHECK-NEXT: br i1 [[ICMP]], label [[LOOP2_EXIT:%.*]], label [[LOOP2]]
37+
; CHECK: loop2.exit:
38+
; CHECK-NEXT: ret void
39+
;
40+
entry:
41+
%alloca = alloca [64 x i8], align 16
42+
br label %loop
43+
44+
loop:
45+
%phi = phi i64 [ 0, %entry ], [ 1, %loop.latch ]
46+
br i1 false, label %loop.exit2, label %loop.latch
47+
48+
loop.latch:
49+
%or = or i64 %phi, 4
50+
br i1 false, label %loop.exit, label %loop
51+
52+
loop.exit:
53+
br label %loop2.preheader
54+
55+
loop.exit2:
56+
br label %loop2.preheader
57+
58+
loop2.preheader:
59+
%phi5.ph = phi ptr [ null, %loop.exit2 ], [ %alloca, %loop.exit ]
60+
%phi6.ph = phi i64 [ 0, %loop.exit2 ], [ %or, %loop.exit ]
61+
br label %loop2
62+
63+
loop2:
64+
%phi5 = phi ptr [ %getelementptr7, %loop2 ], [ %phi5.ph, %loop2.preheader ]
65+
%phi6 = phi i64 [ %add, %loop2 ], [ %phi6.ph, %loop2.preheader ]
66+
%getelementptr = getelementptr i8, ptr %alloca, i64 %phi6
67+
%load = load i8, ptr %getelementptr, align 1
68+
store i8 %load, ptr %phi5, align 1
69+
%getelementptr7 = getelementptr i8, ptr %phi5, i64 1
70+
%add = add i64 %phi6, 1
71+
%icmp = icmp eq i64 %phi6, 0
72+
br i1 %icmp, label %loop2.exit, label %loop2
73+
74+
loop2.exit:
75+
ret void
76+
}

0 commit comments

Comments
 (0)