Skip to content

Commit fcfa7c5

Browse files
committed
[MemorySSA] Make insertDef insert corresponding phi nodes.
Summary: The original assumption for the insertDef method was that it would not materialize Defs out of no-where, hence it will not insert phis needed after inserting a Def. However, when cloning an instruction (use case used in LICM), we do materialize Defs "out of no-where". If the block receiving a Def has at least one other Def, then no processing is needed. If the block just received its first Def, we must check where Phi placement is needed. The only new usage of insertDef is in LICM, hence the trigger for the bug. But the original goal of the method also fails to apply for the move() method. If we move a Def from the entry point of a diamond to either the left or right blocks, then the merge block must add a phi. While this usecase does not currently occur, or may be viewed as an incorrect transformation, MSSA must behave corectly given the scenario. Resolves PR40749 and PR40754. Reviewers: george.burgess.iv Subscribers: sanjoy, jlebar, Prazek, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58652 llvm-svn: 355040
1 parent a0884da commit fcfa7c5

File tree

5 files changed

+177
-9
lines changed

5 files changed

+177
-9
lines changed

llvm/lib/Analysis/MemorySSAUpdater.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,18 @@ void MemorySSAUpdater::insertDef(MemoryDef *MD, bool RenameUses) {
269269
// Also make sure we skip ourselves to avoid self references.
270270
if (isa<MemoryUse>(U.getUser()) || U.getUser() == MD)
271271
continue;
272+
// Defs are automatically unoptimized when the user is set to MD below,
273+
// because the isOptimized() call will fail to find the same ID.
272274
U.set(MD);
273275
}
274276
}
275277

276278
// and that def is now our defining access.
277279
MD->setDefiningAccess(DefBefore);
278280

281+
// Remember the index where we may insert new phis below.
282+
unsigned NewPhiIndex = InsertedPHIs.size();
283+
279284
SmallVector<WeakVH, 8> FixupList(InsertedPHIs.begin(), InsertedPHIs.end());
280285
if (!DefBeforeSameBlock) {
281286
// If there was a local def before us, we must have the same effect it
@@ -289,16 +294,65 @@ void MemorySSAUpdater::insertDef(MemoryDef *MD, bool RenameUses) {
289294
// backwards to find the def. To make that work, we'd have to track whether
290295
// getDefRecursive only ever used the single predecessor case. These types
291296
// of paths also only exist in between CFG simplifications.
297+
298+
// If this is the first def in the block and this insert is in an arbitrary
299+
// place, compute IDF and place phis.
300+
auto Iter = MD->getDefsIterator();
301+
++Iter;
302+
auto IterEnd = MSSA->getBlockDefs(MD->getBlock())->end();
303+
if (Iter == IterEnd) {
304+
ForwardIDFCalculator IDFs(*MSSA->DT);
305+
SmallVector<BasicBlock *, 32> IDFBlocks;
306+
SmallPtrSet<BasicBlock *, 2> DefiningBlocks;
307+
DefiningBlocks.insert(MD->getBlock());
308+
IDFs.setDefiningBlocks(DefiningBlocks);
309+
IDFs.calculate(IDFBlocks);
310+
SmallVector<AssertingVH<MemoryPhi>, 4> NewInsertedPHIs;
311+
for (auto *BBIDF : IDFBlocks)
312+
if (!MSSA->getMemoryAccess(BBIDF))
313+
NewInsertedPHIs.push_back(MSSA->createMemoryPhi(BBIDF));
314+
315+
for (auto &MPhi : NewInsertedPHIs) {
316+
auto *BBIDF = MPhi->getBlock();
317+
for (auto *Pred : predecessors(BBIDF)) {
318+
DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> CachedPreviousDef;
319+
MPhi->addIncoming(getPreviousDefFromEnd(Pred, CachedPreviousDef),
320+
Pred);
321+
}
322+
}
323+
324+
// Re-take the index where we're adding the new phis, because the above
325+
// call to getPreviousDefFromEnd, may have inserted into InsertedPHIs.
326+
NewPhiIndex = InsertedPHIs.size();
327+
for (auto &MPhi : NewInsertedPHIs) {
328+
InsertedPHIs.push_back(&*MPhi);
329+
FixupList.push_back(&*MPhi);
330+
}
331+
}
332+
292333
FixupList.push_back(MD);
293334
}
294335

336+
// Remember the index where we stopped inserting new phis above, since the
337+
// fixupDefs call in the loop below may insert more, that are already minimal.
338+
unsigned NewPhiIndexEnd = InsertedPHIs.size();
339+
295340
while (!FixupList.empty()) {
296341
unsigned StartingPHISize = InsertedPHIs.size();
297342
fixupDefs(FixupList);
298343
FixupList.clear();
299344
// Put any new phis on the fixup list, and process them
300345
FixupList.append(InsertedPHIs.begin() + StartingPHISize, InsertedPHIs.end());
301346
}
347+
348+
// Optimize potentially non-minimal phis added in this method.
349+
for (unsigned Idx = NewPhiIndex; Idx < NewPhiIndexEnd; ++Idx) {
350+
if (auto *MPhi = cast_or_null<MemoryPhi>(InsertedPHIs[Idx])) {
351+
auto OperRange = MPhi->operands();
352+
tryRemoveTrivialPhi(MPhi, OperRange);
353+
}
354+
}
355+
302356
// Now that all fixups are done, rename all uses if we are asked.
303357
if (RenameUses) {
304358
SmallPtrSet<BasicBlock *, 16> Visited;

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,6 +2068,8 @@ bool llvm::promoteLoopAccessesToScalars(
20682068
// stores in the loop.
20692069
Promoter.run(LoopUses);
20702070

2071+
if (MSSAU && VerifyMemorySSA)
2072+
MSSAU->getMemorySSA()->verifyMemorySSA();
20712073
// If the SSAUpdater didn't use the load in the preheader, just zap it now.
20722074
if (PreheaderLoad->use_empty())
20732075
eraseInstruction(*PreheaderLoad, *SafetyInfo, CurAST, MSSAU);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; RUN: opt -licm -enable-mssa-loop-dependency -verify-memoryssa -S < %s | FileCheck %s
2+
; REQUIRES: asserts
3+
4+
target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
5+
target triple = "systemz-unknown"
6+
7+
@g_3 = external dso_local local_unnamed_addr global i32, align 4
8+
@g_57 = external dso_local local_unnamed_addr global i8, align 2
9+
@g_82 = external dso_local global [8 x i16], align 2
10+
@g_107 = external dso_local local_unnamed_addr global i32, align 4
11+
12+
define internal fastcc void @foo1() unnamed_addr{
13+
; CHECK-LABEL: @foo1()
14+
entry:
15+
%.pre.pre = load i32, i32* @g_3, align 4
16+
br label %loop1
17+
18+
loop1:
19+
%tmp0 = phi i32 [ undef, %entry ], [ %var18.lcssa, %loopexit ]
20+
br label %preheader
21+
22+
preheader:
23+
%indvars.iv = phi i64 [ 0, %loop1 ], [ %indvars.iv.next, %loop6 ]
24+
%phi18 = phi i32 [ %tmp0, %loop1 ], [ 0, %loop6 ]
25+
%phi87 = phi i32 [ 0, %loop1 ], [ %tmp7, %loop6 ]
26+
%tmp1 = getelementptr inbounds [8 x i16], [8 x i16]* @g_82, i64 0, i64 %indvars.iv
27+
%tmp2 = load i16, i16* %tmp1, align 2
28+
%tmp3 = trunc i16 %tmp2 to i8
29+
store i8 %tmp3, i8* @g_57, align 2
30+
store i32 8, i32* @g_107, align 4
31+
%tmp4 = icmp eq i32 %.pre.pre, 0
32+
%spec.select = select i1 %tmp4, i32 %phi18, i32 14
33+
%tmp5 = trunc i64 %indvars.iv to i32
34+
switch i32 %spec.select, label %loopexit [
35+
i32 0, label %loop6
36+
i32 14, label %loop9
37+
]
38+
39+
loop6:
40+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
41+
%tmp7 = add nuw nsw i32 %phi87, 1
42+
%tmp8 = icmp ult i64 %indvars.iv.next, 6
43+
br i1 %tmp8, label %preheader, label %loop9
44+
45+
loop9:
46+
%phi8.lcssa = phi i32 [ %tmp5, %preheader ], [ %tmp7, %loop6 ]
47+
%tmp10 = trunc i32 %phi8.lcssa to i8
48+
%tmp11 = tail call i16* @func_101(i16* getelementptr inbounds ([8 x i16], [8 x i16]* @g_82, i64 0, i64 6), i16* undef, i8 zeroext %tmp10)
49+
unreachable
50+
51+
loopexit:
52+
%var18.lcssa = phi i32 [ %phi18, %preheader ]
53+
br label %loop1
54+
55+
}
56+
57+
declare dso_local i16* @func_101(i16*, i16*, i8) local_unnamed_addr
58+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
; RUN: opt -licm -enable-mssa-loop-dependency -verify-memoryssa -S < %s | FileCheck %s
2+
; REQUIRES: asserts
3+
4+
target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
5+
target triple = "systemz-unknown"
6+
7+
@g_120 = external dso_local local_unnamed_addr global [8 x [4 x [6 x i32]]], align 4
8+
@g_185 = external dso_local local_unnamed_addr global i32, align 4
9+
@g_329 = external dso_local local_unnamed_addr global i16, align 2
10+
11+
; Function Attrs: norecurse noreturn nounwind
12+
define dso_local void @func_65() local_unnamed_addr {
13+
; CHECK-LABEL: @func_65()
14+
br label %1
15+
16+
; <label>:1: ; preds = %.thread, %0
17+
br label %2
18+
19+
; <label>:2: ; preds = %.critedge, %1
20+
br label %3
21+
22+
; <label>:3: ; preds = %5, %2
23+
%storemerge = phi i32 [ 0, %2 ], [ %6, %5 ]
24+
store i32 %storemerge, i32* @g_185, align 4
25+
%4 = icmp ult i32 %storemerge, 2
26+
br i1 %4, label %5, label %.thread.loopexit
27+
28+
; <label>:5: ; preds = %3
29+
%6 = add i32 %storemerge, 1
30+
%7 = zext i32 %6 to i64
31+
%8 = getelementptr [8 x [4 x [6 x i32]]], [8 x [4 x [6 x i32]]]* @g_120, i64 0, i64 undef, i64 %7, i64 undef
32+
%9 = load i32, i32* %8, align 4
33+
%10 = icmp eq i32 %9, 0
34+
br i1 %10, label %3, label %11
35+
36+
; <label>:11: ; preds = %5
37+
%storemerge.lcssa4 = phi i32 [ %storemerge, %5 ]
38+
%12 = icmp eq i32 %storemerge.lcssa4, 0
39+
br i1 %12, label %.critedge, label %.thread.loopexit3
40+
41+
.critedge: ; preds = %11
42+
store i16 0, i16* @g_329, align 2
43+
br label %2
44+
45+
.thread.loopexit: ; preds = %3
46+
br label %.thread
47+
48+
.thread.loopexit3: ; preds = %11
49+
br label %.thread
50+
51+
.thread: ; preds = %.thread.loopexit3, %.thread.loopexit
52+
br label %1
53+
}
54+

llvm/unittests/Analysis/MemorySSATest.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,15 @@ TEST_F(MemorySSATest, CreateLoadsAndStoreUpdater) {
159159
MemoryAccess *LeftStoreAccess = Updater.createMemoryAccessInBB(
160160
LeftStore, nullptr, Left, MemorySSA::Beginning);
161161
Updater.insertDef(cast<MemoryDef>(LeftStoreAccess), false);
162-
// We don't touch existing loads, so we need to create a new one to get a phi
162+
163+
// MemoryPHI should exist after adding LeftStore.
164+
MP = MSSA.getMemoryAccess(Merge);
165+
EXPECT_NE(MP, nullptr);
166+
163167
// Add the second load
164168
B.SetInsertPoint(Merge, Merge->begin());
165169
LoadInst *SecondLoad = B.CreateLoad(B.getInt8Ty(), PointerArg);
166170

167-
// MemoryPHI should not already exist.
168-
MP = MSSA.getMemoryAccess(Merge);
169-
EXPECT_EQ(MP, nullptr);
170-
171171
// Create the load memory access
172172
MemoryUse *SecondLoadAccess = cast<MemoryUse>(Updater.createMemoryAccessInBB(
173173
SecondLoad, nullptr, Merge, MemorySSA::Beginning));
@@ -226,14 +226,14 @@ TEST_F(MemorySSATest, CreateALoadUpdater) {
226226
Updater.createMemoryAccessInBB(SI, nullptr, Left, MemorySSA::Beginning);
227227
Updater.insertDef(cast<MemoryDef>(StoreAccess));
228228

229+
// MemoryPHI should be created when inserting the def
230+
MemoryPhi *MP = MSSA.getMemoryAccess(Merge);
231+
EXPECT_NE(MP, nullptr);
232+
229233
// Add the load
230234
B.SetInsertPoint(Merge, Merge->begin());
231235
LoadInst *LoadInst = B.CreateLoad(B.getInt8Ty(), PointerArg);
232236

233-
// MemoryPHI should not already exist.
234-
MemoryPhi *MP = MSSA.getMemoryAccess(Merge);
235-
EXPECT_EQ(MP, nullptr);
236-
237237
// Create the load memory acccess
238238
MemoryUse *LoadAccess = cast<MemoryUse>(Updater.createMemoryAccessInBB(
239239
LoadInst, nullptr, Merge, MemorySSA::Beginning));

0 commit comments

Comments
 (0)