Skip to content

Commit c9ad949

Browse files
committed
Relax conditions safety memory access
1 parent 69fecaa commit c9ad949

File tree

3 files changed

+57
-32
lines changed

3 files changed

+57
-32
lines changed

llvm/lib/Transforms/Scalar/NewGVN.cpp

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,34 +2597,63 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
25972597
Worklist.push_back(V);
25982598
while (!Worklist.empty()) {
25992599
auto *I = Worklist.pop_back_val();
2600-
if (!isa<Instruction>(I))
2600+
if (alwaysAvailable(I))
26012601
continue;
2602+
assert((isa<Instruction>(I) || isa<MemoryPhi>(I)) &&
2603+
"Should have been an Instruction or MemoryPhi");
26022604

26032605
auto OISIt = OpSafeForPHIOfOps.find({I, CacheIdx});
26042606
if (OISIt != OpSafeForPHIOfOps.end())
26052607
return OISIt->second;
26062608

2609+
auto *IBlock = getBlockForValue(I);
26072610
// Keep walking until we either dominate the phi block, or hit a phi, or run
26082611
// out of things to check.
2609-
if (DT->properlyDominates(getBlockForValue(I), PHIBlock)) {
2612+
if (DT->properlyDominates(IBlock, PHIBlock)) {
26102613
OpSafeForPHIOfOps.insert({{I, CacheIdx}, true});
26112614
continue;
26122615
}
26132616
// PHI in the same block.
2614-
if (isa<PHINode>(I) && getBlockForValue(I) == PHIBlock) {
2617+
if ((isa<PHINode>(I) || isa<MemoryPhi>(I)) && IBlock == PHIBlock) {
26152618
OpSafeForPHIOfOps.insert({{I, CacheIdx}, false});
26162619
return false;
26172620
}
26182621

2619-
auto *OrigI = cast<Instruction>(I);
2620-
// When we hit an instruction that reads memory (load, call, etc), we must
2621-
// consider any store that may happen in the loop. For now, we assume the
2622-
// worst: there is a store in the loop that alias with this read.
2623-
// The case where the load is outside the loop is already covered by the
2624-
// dominator check above.
2625-
// TODO: relax this condition
2626-
if (OrigI->mayReadFromMemory())
2627-
return false;
2622+
auto *OrigI = dyn_cast<Instruction>(I);
2623+
// When we encounter an instruction that reads memory (load, call, etc.) or
2624+
// a MemoryAccess, we must ensure that it does not depend on a memory Phi in
2625+
// PHIBlock. The base cases are already checked above; now we must check its
2626+
// operands.
2627+
MemoryAccess *MA = nullptr;
2628+
if (OrigI && OrigI->mayReadOrWriteMemory())
2629+
MA = getMemoryAccess(OrigI);
2630+
else if (isa<MemoryPhi>(I))
2631+
MA = cast<MemoryPhi>(I);
2632+
if (MA) {
2633+
for (auto *Op : MA->operand_values()) {
2634+
// Null => LiveOnEntryDef
2635+
if (!Op || MSSA->isLiveOnEntryDef(cast<MemoryAccess>(Op)))
2636+
continue;
2637+
// Add the instruction that the memory access represents.
2638+
if (auto *MUD = dyn_cast<MemoryUseOrDef>(Op))
2639+
Op = MUD->getMemoryInst();
2640+
// Stop now if we find an unsafe operand.
2641+
auto OISIt = OpSafeForPHIOfOps.find({Op, CacheIdx});
2642+
if (OISIt != OpSafeForPHIOfOps.end()) {
2643+
if (!OISIt->second) {
2644+
OpSafeForPHIOfOps.insert({{I, CacheIdx}, false});
2645+
return false;
2646+
}
2647+
continue;
2648+
}
2649+
if (!Visited.insert(Op).second)
2650+
continue;
2651+
Worklist.push_back(Op);
2652+
}
2653+
}
2654+
// If it's a MemoryPhi there is nothing more to do.
2655+
if (isa<MemoryPhi>(I))
2656+
continue;
26282657

26292658
// Check the operands of the current instruction.
26302659
for (auto *Op : OrigI->operand_values()) {
@@ -2641,7 +2670,7 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
26412670
}
26422671
if (!Visited.insert(Op).second)
26432672
continue;
2644-
Worklist.push_back(cast<Instruction>(Op));
2673+
Worklist.push_back(Op);
26452674
}
26462675
}
26472676
OpSafeForPHIOfOps.insert({{V, CacheIdx}, true});

llvm/test/Transforms/NewGVN/phi-of-ops-loads.ll

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,17 @@ bb237:
7777
ret void
7878
}
7979

80-
; TODO: we should support this case
8180
define void @no-alias-store-in-loop(ptr noalias %p, ptr noalias %q) {
8281
; CHECK-LABEL: @no-alias-store-in-loop(
8382
; CHECK-NEXT: bb56:
8483
; CHECK-NEXT: br label [[BB57:%.*]]
8584
; CHECK: bb57:
86-
; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ]
85+
; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ true, [[BB56:%.*]] ], [ [[N62:%.*]], [[BB229:%.*]] ]
86+
; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229]] ], [ true, [[BB56]] ]
8787
; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ]
8888
; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
89-
; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2
90-
; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]]
91-
; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]]
89+
; CHECK-NEXT: [[N62]] = icmp ne i8 [[N60]], 2
90+
; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[BB229]], label [[BB237:%.*]]
9291
; CHECK: bb229:
9392
; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1
9493
; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1
@@ -150,17 +149,16 @@ bb237:
150149
ret void
151150
}
152151

153-
; TODO: we should support this case
154152
define void @nowrite-function-in-loop(ptr %p) {
155153
; CHECK-LABEL: @nowrite-function-in-loop(
156154
; CHECK-NEXT: bb56:
157155
; CHECK-NEXT: br label [[BB57:%.*]]
158156
; CHECK: bb57:
159-
; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ]
157+
; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ true, [[BB56:%.*]] ], [ [[N62:%.*]], [[BB229:%.*]] ]
158+
; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229]] ], [ true, [[BB56]] ]
160159
; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1
161-
; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2
162-
; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]]
163-
; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]]
160+
; CHECK-NEXT: [[N62]] = icmp ne i8 [[N60]], 2
161+
; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[BB229]], label [[BB237:%.*]]
164162
; CHECK: bb229:
165163
; CHECK-NEXT: call void @f() #[[ATTR0:[0-9]+]]
166164
; CHECK-NEXT: br label [[BB57]]
@@ -199,9 +197,7 @@ define void @issfeoperand(ptr nocapture readonly %array, i1 %cond1, i1 %cond2, p
199197
; CHECK-NEXT: [[PHI1:%.*]] = phi i8 [ [[LD1]], [[COND_TRUE]] ], [ 0, [[FOR_BODY:%.*]] ]
200198
; CHECK-NEXT: [[ARRAYIDX42:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY]], i64 109, i64 0, i64 0, i64 undef
201199
; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX42]], align 1
202-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[LD2]], [[PHI1]]
203-
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP1]] to i32
204-
; CHECK-NEXT: store i32 [[ZEXT]], ptr [[P2:%.*]], align 4
200+
; CHECK-NEXT: store i32 0, ptr [[P2:%.*]], align 4
205201
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[COND_END:%.*]], label [[EXIT:%.*]]
206202
; CHECK: cond.end:
207203
; CHECK-NEXT: [[LD3:%.*]] = load i16, ptr [[P1:%.*]], align 2

llvm/test/Transforms/NewGVN/storeoverstore.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ define i32 @foo(ptr, i32) {
1515
; CHECK: 4:
1616
; CHECK-NEXT: br label [[TMP5]]
1717
; CHECK: 5:
18-
; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP2:%.*]] ]
19-
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP6:%.*]], label [[TMP8:%.*]]
18+
; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i32 [ 10, [[TMP2:%.*]] ], [ 15, [[TMP4]] ]
19+
; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 10, [[TMP4]] ], [ 5, [[TMP2]] ]
20+
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP6:%.*]], label [[TMP7:%.*]]
2021
; CHECK: 6:
21-
; CHECK-NEXT: [[TMP7:%.*]] = add nsw i32 [[DOT0]], 5
22-
; CHECK-NEXT: br label [[TMP8]]
23-
; CHECK: 8:
24-
; CHECK-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP7]], [[TMP6]] ], [ [[DOT0]], [[TMP5]] ]
22+
; CHECK-NEXT: br label [[TMP7]]
23+
; CHECK: 7:
24+
; CHECK-NEXT: [[DOT1:%.*]] = phi i32 [ [[PHIOFOPS]], [[TMP6]] ], [ [[DOT0]], [[TMP5]] ]
2525
; CHECK-NEXT: ret i32 [[DOT1]]
2626
;
2727
store i32 5, ptr %0, align 4

0 commit comments

Comments
 (0)