Skip to content

Commit f1c18ac

Browse files
committedJan 29, 2022
[NewGVN] do phi(undef, x) -> x only if x is not poison
phi([undef, A], [x, B]) -> x is only correct x is guaranteed to be a non-poison value. Otherwise we would be changing an undef to poison in the branch A. Differential Revision: https://reviews.llvm.org/D117907
1 parent 7b2dfe1 commit f1c18ac

File tree

7 files changed

+48
-22
lines changed

7 files changed

+48
-22
lines changed
 

‎llvm/lib/Transforms/Scalar/NewGVN.cpp

+17-11
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "llvm/Analysis/MemoryBuiltins.h"
7878
#include "llvm/Analysis/MemorySSA.h"
7979
#include "llvm/Analysis/TargetLibraryInfo.h"
80+
#include "llvm/Analysis/ValueTracking.h"
8081
#include "llvm/IR/Argument.h"
8182
#include "llvm/IR/BasicBlock.h"
8283
#include "llvm/IR/Constant.h"
@@ -1736,18 +1737,18 @@ NewGVN::performSymbolicPHIEvaluation(ArrayRef<ValPair> PHIOps,
17361737
if (Filtered.empty()) {
17371738
// If it has undef or poison at this point, it means there are no-non-undef
17381739
// arguments, and thus, the value of the phi node must be undef.
1739-
if (HasPoison && !HasUndef) {
1740-
LLVM_DEBUG(
1741-
dbgs() << "PHI Node " << *I
1742-
<< " has no non-poison arguments, valuing it as poison\n");
1743-
return createConstantExpression(PoisonValue::get(I->getType()));
1744-
}
17451740
if (HasUndef) {
17461741
LLVM_DEBUG(
17471742
dbgs() << "PHI Node " << *I
17481743
<< " has no non-undef arguments, valuing it as undef\n");
17491744
return createConstantExpression(UndefValue::get(I->getType()));
17501745
}
1746+
if (HasPoison) {
1747+
LLVM_DEBUG(
1748+
dbgs() << "PHI Node " << *I
1749+
<< " has no non-poison arguments, valuing it as poison\n");
1750+
return createConstantExpression(PoisonValue::get(I->getType()));
1751+
}
17511752

17521753
LLVM_DEBUG(dbgs() << "No arguments of PHI node " << *I << " are live\n");
17531754
deleteExpression(E);
@@ -1757,15 +1758,20 @@ NewGVN::performSymbolicPHIEvaluation(ArrayRef<ValPair> PHIOps,
17571758
++Filtered.begin();
17581759
// Can't use std::equal here, sadly, because filter.begin moves.
17591760
if (llvm::all_of(Filtered, [&](Value *Arg) { return Arg == AllSameValue; })) {
1761+
// Can't fold phi(undef, X) -> X unless X can't be poison (thus X is undef
1762+
// in the worst case).
1763+
if (HasUndef && !isGuaranteedNotToBePoison(AllSameValue, AC, nullptr, DT))
1764+
return E;
1765+
17601766
// In LLVM's non-standard representation of phi nodes, it's possible to have
17611767
// phi nodes with cycles (IE dependent on other phis that are .... dependent
17621768
// on the original phi node), especially in weird CFG's where some arguments
17631769
// are unreachable, or uninitialized along certain paths. This can cause
17641770
// infinite loops during evaluation. We work around this by not trying to
17651771
// really evaluate them independently, but instead using a variable
17661772
// expression to say if one is equivalent to the other.
1767-
// We also special case undef, so that if we have an undef, we can't use the
1768-
// common value unless it dominates the phi block.
1773+
// We also special case undef/poison, so that if we have an undef, we can't
1774+
// use the common value unless it dominates the phi block.
17691775
if (HasPoison || HasUndef) {
17701776
// If we have undef and at least one other value, this is really a
17711777
// multivalued phi, and we need to know if it's cycle free in order to
@@ -2853,14 +2859,14 @@ NewGVN::makePossiblePHIOfOps(Instruction *I,
28532859
}
28542860

28552861
// The algorithm initially places the values of the routine in the TOP
2856-
// congruence class. The leader of TOP is the undetermined value `undef`.
2862+
// congruence class. The leader of TOP is the undetermined value `poison`.
28572863
// When the algorithm has finished, values still in TOP are unreachable.
28582864
void NewGVN::initializeCongruenceClasses(Function &F) {
28592865
NextCongruenceNum = 0;
28602866

28612867
// Note that even though we use the live on entry def as a representative
28622868
// MemoryAccess, it is *not* the same as the actual live on entry def. We
2863-
// have no real equivalemnt to undef for MemoryAccesses, and so we really
2869+
// have no real equivalent to poison for MemoryAccesses, and so we really
28642870
// should be checking whether the MemoryAccess is top if we want to know if it
28652871
// is equivalent to everything. Otherwise, what this really signifies is that
28662872
// the access "it reaches all the way back to the beginning of the function"
@@ -3031,7 +3037,7 @@ void NewGVN::valueNumberMemoryPhi(MemoryPhi *MP) {
30313037
!isMemoryAccessTOP(cast<MemoryAccess>(U)) &&
30323038
ReachableEdges.count({MP->getIncomingBlock(U), PHIBlock});
30333039
});
3034-
// If all that is left is nothing, our memoryphi is undef. We keep it as
3040+
// If all that is left is nothing, our memoryphi is poison. We keep it as
30353041
// InitialClass. Note: The only case this should happen is if we have at
30363042
// least one self-argument.
30373043
if (Filtered.begin() == Filtered.end()) {

‎llvm/test/Transforms/NewGVN/completeness.ll

+5-6
Original file line numberDiff line numberDiff line change
@@ -505,17 +505,16 @@ declare i32* @wombat()
505505
;; change in the verifier, as it goes from a constant value to a
506506
;; phi of [true, false]
507507

508-
define void @test12() {
508+
define void @test12(i32* %p) {
509509
; CHECK-LABEL: @test12(
510510
; CHECK-NEXT: bb:
511-
; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* null
511+
; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* %p
512512
; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP]], 0
513513
; CHECK-NEXT: br i1 [[TMP1]], label [[BB2:%.*]], label [[BB8:%.*]]
514514
; CHECK: bb2:
515515
; CHECK-NEXT: br label [[BB3:%.*]]
516516
; CHECK: bb3:
517-
; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ true, [[BB2]] ], [ false, [[BB7:%.*]] ]
518-
; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[BB6:%.*]], label [[BB7]]
517+
; CHECK-NEXT: br i1 true, label [[BB6:%.*]], label [[BB7]]
519518
; CHECK: bb6:
520519
; CHECK-NEXT: br label [[BB7]]
521520
; CHECK: bb7:
@@ -524,15 +523,15 @@ define void @test12() {
524523
; CHECK-NEXT: ret void
525524
;
526525
bb:
527-
%tmp = load i32, i32* null
526+
%tmp = load i32, i32* %p
528527
%tmp1 = icmp sgt i32 %tmp, 0
529528
br i1 %tmp1, label %bb2, label %bb8
530529

531530
bb2: ; preds = %bb
532531
br label %bb3
533532

534533
bb3: ; preds = %bb7, %bb2
535-
%tmp4 = phi i32 [ %tmp, %bb2 ], [ undef, %bb7 ]
534+
%tmp4 = phi i32 [ %tmp, %bb2 ], [ poison, %bb7 ]
536535
%tmp5 = icmp sgt i32 %tmp4, 0
537536
br i1 %tmp5, label %bb6, label %bb7
538537

‎llvm/test/Transforms/NewGVN/phi-edge-handling.ll

+21
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,27 @@ define i8 @value_undef(i1 %cond, i8 %v) {
119119
; CHECK: B:
120120
; CHECK-NEXT: br label [[EXIT]]
121121
; CHECK: EXIT:
122+
; CHECK-NEXT: [[R:%.*]] = phi i8 [ undef, [[A]] ], [ [[V:%.*]], [[B]] ]
123+
; CHECK-NEXT: ret i8 [[R]]
124+
;
125+
br i1 %cond, label %A, label %B
126+
A:
127+
br label %EXIT
128+
B:
129+
br label %EXIT
130+
EXIT:
131+
%r = phi i8 [undef, %A], [%v, %B]
132+
ret i8 %r
133+
}
134+
135+
define i8 @value_undef_noundef(i1 %cond, i8 noundef %v) {
136+
; CHECK-LABEL: @value_undef_noundef(
137+
; CHECK-NEXT: br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
138+
; CHECK: A:
139+
; CHECK-NEXT: br label [[EXIT:%.*]]
140+
; CHECK: B:
141+
; CHECK-NEXT: br label [[EXIT]]
142+
; CHECK: EXIT:
122143
; CHECK-NEXT: ret i8 [[V:%.*]]
123144
;
124145
br i1 %cond, label %A, label %B

‎llvm/test/Transforms/NewGVN/pr31682.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ bb:
2424
br label %bb2
2525

2626
bb2: ; preds = %bb2, %bb
27-
%tmp3 = phi %struct.foo* [ undef, %bb ], [ %tmp6, %bb2 ]
27+
%tmp3 = phi %struct.foo* [ poison, %bb ], [ %tmp6, %bb2 ]
2828
%tmp4 = getelementptr %struct.foo, %struct.foo* %tmp3, i64 0, i32 1
2929
%tmp5 = load i32, i32* %tmp4
3030
%tmp6 = load %struct.foo*, %struct.foo** @global

‎llvm/test/Transforms/NewGVN/pr32403.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ if.then17.i: ; preds = %for.body8.i
5050
br label %for.inc24.i
5151

5252
for.inc24.i: ; preds = %if.then17.i, %for.body8.i
53-
%nIdx.1.i = phi i32 [ undef, %if.then17.i ], [ %nIdx.052.i, %for.body8.i ]
53+
%nIdx.1.i = phi i32 [ poison, %if.then17.i ], [ %nIdx.052.i, %for.body8.i ]
5454
br label %for.body8.i
5555

5656
if.else58: ; preds = %for.body

‎llvm/test/Transforms/NewGVN/pr32838.ll

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
44
target triple = "x86_64-apple-macosx10.12.0"
55
;; Ensure we don't infinite loop when all phi arguments are really unreachable or self-defined
6-
define void @fn1(i64 %arg) {
6+
define void @fn1(i64 noundef %arg) {
77
; CHECK-LABEL: @fn1(
88
; CHECK-NEXT: entry:
99
; CHECK-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[COND_TRUE:%.*]]
@@ -47,7 +47,7 @@ cond.true:
4747
temp:
4848
ret void
4949
}
50-
define void @fn2(i64 %arg) {
50+
define void @fn2(i64 noundef %arg) {
5151
; CHECK-LABEL: @fn2(
5252
; CHECK-NEXT: entry:
5353
; CHECK-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[COND_TRUE:%.*]]

‎llvm/test/Transforms/NewGVN/pr34135.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
;; Make sure we don't incorrectly use predicateinfo to simplify phi of ops cases
44
source_filename = "pr34135.ll"
55

6-
define void @snork(i32 %arg) {
6+
define void @snork(i32 noundef %arg) {
77
; CHECK-LABEL: @snork(
88
; CHECK-NEXT: bb:
99
; CHECK-NEXT: [[TMP:%.*]] = sext i32 [[ARG:%.*]] to i64

0 commit comments

Comments
 (0)
Please sign in to comment.