Skip to content

Commit 5db2735

Browse files
committed
[gvn] Handle simply phi equivalence cases
GVN basically doesn't handle phi nodes at all. This is for a reason - we can't value number their inputs since the predecessor blocks have probably not been visited yet. However, it also creates a significant pass ordering problem. As it stands, instcombine and simplifycfg ends up implementing CSE of phi nodes. This means that for any series of CSE opportunities intermixed with phi nodes, we end up having to alternate instcombine/simplifycfg and gvn to make progress. This patch handles the simplest case by simply preprocessing the phi instructions in a block, and CSEing them if they are syntactically identical. This turns out to be powerful enough to handle many cases in a single invocation of GVN since blocks which use the cse'd phi results are visited after the block containing the phi. If there's a CSE opportunity in one the phi predecessors required to recognize the phi CSE opportunity, that will require a second iteration on the function. (Still within a single run of gvn though.) Compile time wise, this could go either way. On one hand, we're potentially causing GVN to iterate over the function more. On the other, we're cutting down on iterations between two passes and potentially shrinking the IR aggressively. So, a bit unclear what to expect. Note that this does still rely on instcombine to canonicalize block order of the phis, but that's a one time transformation independent of the values incoming to the phi. Differential Revision: https://reviews.llvm.org/D98080
1 parent 15fdd53 commit 5db2735

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

llvm/lib/Transforms/Scalar/GVN.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,12 @@ bool GVN::processBlock(BasicBlock *BB) {
23722372
ReplaceOperandsWithMap.clear();
23732373
bool ChangedFunction = false;
23742374

2375+
// Since we may not have visited the input blocks of the phis, we can't
2376+
// use our normal hash approach for phis. Instead, simply look for
2377+
// obvious duplicates. The first pass of GVN will tend to create
2378+
// identical phis, and the second or later passes can eliminate them.
2379+
ChangedFunction |= EliminateDuplicatePHINodes(BB);
2380+
23752381
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
23762382
BI != BE;) {
23772383
if (!ReplaceOperandsWithMap.empty())

llvm/test/Transforms/GVN/phi.ll

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ define i64 @test1(i1 %c, i64 %a, i64 %b) {
1111
; CHECK-NEXT: br label [[MERGE]]
1212
; CHECK: merge:
1313
; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[A:%.*]], [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ]
14-
; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ [[B]], [[UNTAKEN]] ]
15-
; CHECK-NEXT: [[RET:%.*]] = sub i64 [[PHI1]], [[PHI2]]
16-
; CHECK-NEXT: ret i64 [[RET]]
14+
; CHECK-NEXT: ret i64 0
1715
;
1816
br i1 %c, label %taken, label %untaken
1917
taken:
@@ -69,9 +67,7 @@ define i64 @test3(i1 %c, i64 %a, i64 %b) {
6967
; CHECK-NEXT: br label [[MERGE]]
7068
; CHECK: merge:
7169
; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[ADD1]], [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ]
72-
; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ [[ADD1]], [[TAKEN]] ], [ [[B]], [[UNTAKEN]] ]
73-
; CHECK-NEXT: [[RET:%.*]] = sub i64 [[PHI1]], [[PHI2]]
74-
; CHECK-NEXT: ret i64 [[RET]]
70+
; CHECK-NEXT: ret i64 0
7571
;
7672
br i1 %c, label %taken, label %untaken
7773
taken:
@@ -96,19 +92,15 @@ define i64 @test4(i1 %c, i64 %a, i64 %b) {
9692
; CHECK-NEXT: br label [[MERGE]]
9793
; CHECK: merge:
9894
; CHECK-NEXT: [[PHI1:%.*]] = phi i64 [ [[A:%.*]], [[TAKEN]] ], [ [[B:%.*]], [[UNTAKEN]] ]
99-
; CHECK-NEXT: [[PHI2:%.*]] = phi i64 [ [[A]], [[TAKEN]] ], [ [[B]], [[UNTAKEN]] ]
10095
; CHECK-NEXT: br i1 [[C]], label [[TAKEN2:%.*]], label [[UNTAKEN2:%.*]]
10196
; CHECK: taken2:
10297
; CHECK-NEXT: [[ADD1:%.*]] = add i64 [[PHI1]], 5
103-
; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[PHI2]], 5
10498
; CHECK-NEXT: br label [[MERGE2:%.*]]
10599
; CHECK: untaken2:
106100
; CHECK-NEXT: br label [[MERGE2]]
107101
; CHECK: merge2:
108-
; CHECK-NEXT: [[PHI3:%.*]] = phi i64 [ [[ADD1]], [[TAKEN2]] ], [ [[PHI2]], [[UNTAKEN2]] ]
109-
; CHECK-NEXT: [[PHI4:%.*]] = phi i64 [ [[ADD2]], [[TAKEN2]] ], [ [[PHI2]], [[UNTAKEN2]] ]
110-
; CHECK-NEXT: [[RET:%.*]] = sub i64 [[PHI4]], [[PHI3]]
111-
; CHECK-NEXT: ret i64 [[RET]]
102+
; CHECK-NEXT: [[PHI3:%.*]] = phi i64 [ [[ADD1]], [[TAKEN2]] ], [ [[PHI1]], [[UNTAKEN2]] ]
103+
; CHECK-NEXT: ret i64 0
112104
;
113105
br i1 %c, label %taken, label %untaken
114106
taken:

0 commit comments

Comments
 (0)