Skip to content

Commit f108e30

Browse files
committed
Add block identifier to cache key
1 parent b5657d6 commit f108e30

File tree

2 files changed

+116
-7
lines changed

2 files changed

+116
-7
lines changed

llvm/lib/Transforms/Scalar/NewGVN.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,11 @@ class NewGVN {
529529
// IR.
530530
SmallPtrSet<const Instruction *, 8> PHINodeUses;
531531

532-
DenseMap<const Value *, bool> OpSafeForPHIOfOps;
532+
// The cached results, in general, are only valid for the specific block where
533+
// they were computed. The unsigned part of the key is a unique block
534+
// identifier
535+
DenseMap<std::pair<const Value *, unsigned>, bool> OpSafeForPHIOfOps;
536+
unsigned CacheIdx;
533537

534538
// Map a temporary instruction we created to a parent block.
535539
DenseMap<const Value *, BasicBlock *> TempToBlock;
@@ -2600,19 +2604,19 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
26002604
if (!isa<Instruction>(I))
26012605
continue;
26022606

2603-
auto OISIt = OpSafeForPHIOfOps.find(I);
2607+
auto OISIt = OpSafeForPHIOfOps.find({I, CacheIdx});
26042608
if (OISIt != OpSafeForPHIOfOps.end())
26052609
return OISIt->second;
26062610

26072611
// Keep walking until we either dominate the phi block, or hit a phi, or run
26082612
// out of things to check.
26092613
if (DT->properlyDominates(getBlockForValue(I), PHIBlock)) {
2610-
OpSafeForPHIOfOps.insert({I, true});
2614+
OpSafeForPHIOfOps.insert({{I, CacheIdx}, true});
26112615
continue;
26122616
}
26132617
// PHI in the same block.
26142618
if (isa<PHINode>(I) && getBlockForValue(I) == PHIBlock) {
2615-
OpSafeForPHIOfOps.insert({I, false});
2619+
OpSafeForPHIOfOps.insert({{I, CacheIdx}, false});
26162620
return false;
26172621
}
26182622

@@ -2631,10 +2635,10 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
26312635
if (!isa<Instruction>(Op))
26322636
continue;
26332637
// Stop now if we find an unsafe operand.
2634-
auto OISIt = OpSafeForPHIOfOps.find(OrigI);
2638+
auto OISIt = OpSafeForPHIOfOps.find({OrigI, CacheIdx});
26352639
if (OISIt != OpSafeForPHIOfOps.end()) {
26362640
if (!OISIt->second) {
2637-
OpSafeForPHIOfOps.insert({I, false});
2641+
OpSafeForPHIOfOps.insert({{I, CacheIdx}, false});
26382642
return false;
26392643
}
26402644
continue;
@@ -2644,7 +2648,7 @@ bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
26442648
Worklist.push_back(cast<Instruction>(Op));
26452649
}
26462650
}
2647-
OpSafeForPHIOfOps.insert({V, true});
2651+
OpSafeForPHIOfOps.insert({{V, CacheIdx}, true});
26482652
return true;
26492653
}
26502654

@@ -3297,6 +3301,7 @@ void NewGVN::verifyIterationSettled(Function &F) {
32973301
TouchedInstructions.set();
32983302
TouchedInstructions.reset(0);
32993303
OpSafeForPHIOfOps.clear();
3304+
CacheIdx = 0;
33003305
iterateTouchedInstructions();
33013306
DenseSet<std::pair<const CongruenceClass *, const CongruenceClass *>>
33023307
EqualClasses;
@@ -3400,6 +3405,8 @@ void NewGVN::iterateTouchedInstructions() {
34003405
<< " because it is unreachable\n");
34013406
continue;
34023407
}
3408+
// Use the appropriate cache for "OpIsSafeForPHIOfOps".
3409+
CacheIdx = RPOOrdering.lookup(DT->getNode(CurrBlock)) - 1;
34033410
updateProcessedCount(CurrBlock);
34043411
}
34053412
// Reset after processing (because we may mark ourselves as touched when
@@ -3479,6 +3486,8 @@ bool NewGVN::runGVN() {
34793486
LLVM_DEBUG(dbgs() << "Block " << getBlockName(&F.getEntryBlock())
34803487
<< " marked reachable\n");
34813488
ReachableBlocks.insert(&F.getEntryBlock());
3489+
// Use index corresponding to entry block.
3490+
CacheIdx = 0;
34823491

34833492
iterateTouchedInstructions();
34843493
verifyMemoryCongruency();
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=newgvn < %s | FileCheck %s
3+
4+
define i32 @unsafe(i1 %arg, i32 %arg1) {
5+
; CHECK-LABEL: define i32 @unsafe(
6+
; CHECK-SAME: i1 [[ARG:%.*]], i32 [[ARG1:%.*]]) {
7+
; CHECK-NEXT: [[BB:.*:]]
8+
; CHECK-NEXT: br label %[[BB4:.*]]
9+
; CHECK: [[BB4]]:
10+
; CHECK-NEXT: br i1 [[ARG]], label %[[BB6:.*]], label %[[BB5:.*]]
11+
; CHECK: [[BB5]]:
12+
; CHECK-NEXT: br label %[[BB6]]
13+
; CHECK: [[BB6]]:
14+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ARG1]], %[[BB5]] ], [ 0, %[[BB4]] ]
15+
; CHECK-NEXT: [[SREM:%.*]] = srem i32 [[ARG1]], [[PHI]]
16+
; CHECK-NEXT: store i32 [[SREM]], ptr null, align 4
17+
; CHECK-NEXT: br i1 [[ARG]], label %[[BB8:.*]], label %[[BB7:.*]]
18+
; CHECK: [[BB7]]:
19+
; CHECK-NEXT: br i1 true, label %[[BB8]], label %[[BB5]]
20+
; CHECK: [[BB8]]:
21+
; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i32 [ [[ARG1]], %[[BB6]] ], [ 0, %[[BB7]] ]
22+
; CHECK-NEXT: [[PHI9:%.*]] = phi i32 [ 0, %[[BB7]] ], [ 1, %[[BB6]] ]
23+
; CHECK-NEXT: store i32 [[PHIOFOPS]], ptr null, align 4
24+
; CHECK-NEXT: br label %[[BB4]]
25+
;
26+
bb:
27+
br label %bb4
28+
29+
bb4: ; preds = %bb8, %bb
30+
br i1 %arg, label %bb6, label %bb5
31+
32+
bb5: ; preds = %bb7, %bb4
33+
br label %bb6
34+
35+
bb6: ; preds = %bb5, %bb4
36+
%phi = phi i32 [ %arg1, %bb5 ], [ 0, %bb4 ]
37+
%or = or i32 %phi, %arg1
38+
%srem = srem i32 %or, %phi
39+
store i32 %srem, ptr null, align 4
40+
br i1 %arg, label %bb8, label %bb7
41+
42+
bb7: ; preds = %bb6
43+
br i1 true, label %bb8, label %bb5
44+
45+
bb8: ; preds = %bb7, %bb6
46+
%phi9 = phi i32 [ 0, %bb7 ], [ 1, %bb6 ]
47+
%mul = mul i32 %phi9, %or
48+
store i32 %mul, ptr null, align 4
49+
br label %bb4
50+
}
51+
52+
define i32 @unsafe_load(i1 %arg) {
53+
; CHECK-LABEL: define i32 @unsafe_load(
54+
; CHECK-SAME: i1 [[ARG:%.*]]) {
55+
; CHECK-NEXT: [[BB:.*:]]
56+
; CHECK-NEXT: br label %[[BB1:.*]]
57+
; CHECK: [[BB1]]:
58+
; CHECK-NEXT: br i1 [[ARG]], label %[[BB3:.*]], label %[[BB2:.*]]
59+
; CHECK: [[BB2]]:
60+
; CHECK-NEXT: br label %[[BB3]]
61+
; CHECK: [[BB3]]:
62+
; CHECK-NEXT: [[PHI4:%.*]] = phi i32 [ 1, %[[BB2]] ], [ 0, %[[BB1]] ]
63+
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr null, align 4
64+
; CHECK-NEXT: [[SREM:%.*]] = srem i32 [[LOAD]], [[PHI4]]
65+
; CHECK-NEXT: store i32 [[SREM]], ptr null, align 4
66+
; CHECK-NEXT: br i1 [[ARG]], label %[[BB6:.*]], label %[[BB5:.*]]
67+
; CHECK: [[BB5]]:
68+
; CHECK-NEXT: br i1 true, label %[[BB6]], label %[[BB2]]
69+
; CHECK: [[BB6]]:
70+
; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i32 [ [[LOAD]], %[[BB3]] ], [ 0, %[[BB5]] ]
71+
; CHECK-NEXT: [[PHI7:%.*]] = phi i32 [ 0, %[[BB5]] ], [ 1, %[[BB3]] ]
72+
; CHECK-NEXT: store i32 [[PHIOFOPS]], ptr null, align 4
73+
; CHECK-NEXT: br label %[[BB1]]
74+
;
75+
bb:
76+
br label %bb1
77+
78+
bb1: ; preds = %bb6, %bb
79+
br i1 %arg, label %bb3, label %bb2
80+
81+
bb2: ; preds = %bb5, %bb1
82+
%phi = phi i32 [ 1, %bb1 ], [ 0, %bb5 ]
83+
br label %bb3
84+
85+
bb3: ; preds = %bb2, %bb1
86+
%phi4 = phi i32 [ %phi, %bb2 ], [ 0, %bb1 ]
87+
%load = load i32, ptr null, align 4
88+
%srem = srem i32 %load, %phi4
89+
store i32 %srem, ptr null, align 4
90+
br i1 %arg, label %bb6, label %bb5
91+
92+
bb5: ; preds = %bb3
93+
br i1 true, label %bb6, label %bb2
94+
95+
bb6: ; preds = %bb5, %bb3
96+
%phi7 = phi i32 [ 0, %bb5 ], [ 1, %bb3 ]
97+
%mul = mul i32 %phi7, %load
98+
store i32 %mul, ptr null, align 4
99+
br label %bb1
100+
}

0 commit comments

Comments
 (0)