[llvm] [InstSimplify] Fix Inconsistent PHI Simplification (PR #113037)
Marius Kamp via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 7 03:18:00 PST 2024
https://github.com/mskamp updated https://github.com/llvm/llvm-project/pull/113037
>From 786ff71cd1bf66350dcf57d1c0e1cb9bae0dab77 Mon Sep 17 00:00:00 2001
From: Marius Kamp <msk at posteo.org>
Date: Fri, 11 Oct 2024 10:47:57 +0200
Subject: [PATCH 1/3] [InstSimplify] Add Tests for PHI of Partially
Unknown/Poison Vector/Array/Struct; NFC
---
.../InstSimplify/phi-vec-unknown-poison.ll | 231 ++++++++++++++++++
1 file changed, 231 insertions(+)
create mode 100644 llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll
diff --git a/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll b/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll
new file mode 100644
index 00000000000000..a59c3d619143ff
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll
@@ -0,0 +1,231 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+define <2 x i1> @test_vec_undef_poison(i1 %c) {
+; CHECK-LABEL: define <2 x i1> @test_vec_undef_poison(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: ret <2 x i1> <i1 poison, i1 false>
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i1> [ <i1 undef, i1 poison>, %t ], [ <i1 poison, i1 false>, %f ]
+ ret <2 x i1> %res
+}
+
+define <2 x i1> @test_vec_poison_undef(i1 %c) {
+; CHECK-LABEL: define <2 x i1> @test_vec_poison_undef(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: ret <2 x i1> <i1 false, i1 poison>
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i1> [ <i1 false, i1 poison>, %t ], [ <i1 poison, i1 undef>, %f ]
+ ret <2 x i1> %res
+}
+
+define <2 x i1> @test_vec_poison_undef_defined(i1 %c1, i1 %c2) {
+; CHECK-LABEL: define <2 x i1> @test_vec_poison_undef_defined(
+; CHECK-SAME: i1 [[C1:%.*]], i1 [[C2:%.*]]) {
+; CHECK-NEXT: br i1 [[C1]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br i1 [[C2]], label %[[TT:.*]], label %[[TF:.*]]
+; CHECK: [[TT]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[TF]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: [[RES:%.*]] = phi <2 x i1> [ <i1 false, i1 poison>, %[[TT]] ], [ undef, %[[TF]] ], [ <i1 poison, i1 true>, %[[F]] ]
+; CHECK-NEXT: ret <2 x i1> [[RES]]
+;
+ br i1 %c1, label %t, label %f
+t:
+ br i1 %c2, label %tt, label %tf
+tt:
+ br label %m
+tf:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i1> [ <i1 false, i1 poison>, %tt ], [ <i1 undef, i1 undef>, %tf ], [ <i1 poison, i1 true>, %f ]
+ ret <2 x i1> %res
+}
+
+define <2 x i8> @test_vec_same_constants(i1 %c) {
+; CHECK-LABEL: define <2 x i8> @test_vec_same_constants(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: ret <2 x i8> <i8 4, i8 2>
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i8> [ <i8 4, i8 2>, %t ], [ <i8 4, i8 2>, %f ]
+ ret <2 x i8> %res
+}
+
+; Negative test
+define <2 x i8> @test_vec_different_constants(i1 %c) {
+; CHECK-LABEL: define <2 x i8> @test_vec_different_constants(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: [[RES:%.*]] = phi <2 x i8> [ <i8 4, i8 2>, %[[T]] ], [ <i8 2, i8 4>, %[[F]] ]
+; CHECK-NEXT: ret <2 x i8> [[RES]]
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i8> [ <i8 4, i8 2>, %t ], [ <i8 2, i8 4>, %f ]
+ ret <2 x i8> %res
+}
+
+ at glob = global i32 0
+
+define <2 x i8> @test_undef_poison_const_expr(i1 %c) {
+; CHECK-LABEL: define <2 x i8> @test_undef_poison_const_expr(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: ret <2 x i8> bitcast (i16 ptrtoint (ptr @glob to i16) to <2 x i8>)
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i8> [ <i8 undef, i8 poison>, %t ], [ bitcast (i16 ptrtoint (ptr @glob to i16) to <2 x i8>), %f ]
+ ret <2 x i8> %res
+}
+
+; Negative test
+define <2 x i8> @test_undef_0_const_expr(i1 %c) {
+; CHECK-LABEL: define <2 x i8> @test_undef_0_const_expr(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: [[RES:%.*]] = phi <2 x i8> [ <i8 undef, i8 0>, %[[T]] ], [ bitcast (i16 ptrtoint (ptr @glob to i16) to <2 x i8>), %[[F]] ]
+; CHECK-NEXT: ret <2 x i8> [[RES]]
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i8> [ <i8 undef, i8 0>, %t ], [ bitcast (i16 ptrtoint (ptr @glob to i16) to <2 x i8>), %f ]
+ ret <2 x i8> %res
+}
+
+; Negative test
+define <2 x i8> @test_const_expr_undef_0(i1 %c) {
+; CHECK-LABEL: define <2 x i8> @test_const_expr_undef_0(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: [[RES:%.*]] = phi <2 x i8> [ bitcast (i16 ptrtoint (ptr @glob to i16) to <2 x i8>), %[[T]] ], [ <i8 undef, i8 0>, %[[F]] ]
+; CHECK-NEXT: ret <2 x i8> [[RES]]
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi <2 x i8> [ bitcast (i16 ptrtoint (ptr @glob to i16) to <2 x i8>), %t ], [ <i8 undef, i8 0>, %f ]
+ ret <2 x i8> %res
+}
+
+define [2 x double] @test_array_undef_poison(i1 %c) {
+; CHECK-LABEL: define [2 x double] @test_array_undef_poison(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: ret [2 x double] [double poison, double 0.000000e+00]
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi [2 x double] [ [double undef, double poison], %t ], [ [double poison, double 0.0], %f ]
+ ret [2 x double] %res
+}
+
+%Struct = type { i8, i8 }
+
+define %Struct @test_struct_undef_poison(i1 %c) {
+; CHECK-LABEL: define %Struct @test_struct_undef_poison(
+; CHECK-SAME: i1 [[C:%.*]]) {
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: br label %[[M:.*]]
+; CHECK: [[F]]:
+; CHECK-NEXT: br label %[[M]]
+; CHECK: [[M]]:
+; CHECK-NEXT: ret [[STRUCT:%.*]] { i8 poison, i8 0 }
+;
+ br i1 %c, label %t, label %f
+t:
+ br label %m
+f:
+ br label %m
+m:
+ %res = phi %Struct [ {i8 undef, i8 poison}, %t ], [ {i8 poison, i8 0}, %f ]
+ ret %Struct %res
+}
>From 26ea4a622803ef35acf9d3e5c885a68207ac7a36 Mon Sep 17 00:00:00 2001
From: Marius Kamp <msk at posteo.org>
Date: Thu, 17 Oct 2024 19:59:48 +0200
Subject: [PATCH 2/3] [AMDGPU] Change Constant Vector in Test Case; NFC
This adaption is necessary to keep the loop structure even after
applying the next commit, which would otherwise simplify the control
flow too much.
---
llvm/test/CodeGen/AMDGPU/collapse-endcf.ll | 26 +++++++++++-----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/llvm/test/CodeGen/AMDGPU/collapse-endcf.ll b/llvm/test/CodeGen/AMDGPU/collapse-endcf.ll
index 75d0b83a024ff5..5bf050f60fc010 100644
--- a/llvm/test/CodeGen/AMDGPU/collapse-endcf.ll
+++ b/llvm/test/CodeGen/AMDGPU/collapse-endcf.ll
@@ -983,7 +983,8 @@ define void @scc_liveness(i32 %arg) local_unnamed_addr #0 {
; GCN-NEXT: v_cmp_gt_i32_e32 vcc, s4, v0
; GCN-NEXT: s_mov_b32 s8, 0
; GCN-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v0
-; GCN-NEXT: s_mov_b64 s[12:13], 0
+; GCN-NEXT: s_mov_b64 s[14:15], 0
+; GCN-NEXT: s_mov_b32 s13, 1.0
; GCN-NEXT: s_mov_b64 s[6:7], 0
; GCN-NEXT: s_branch .LBB5_3
; GCN-NEXT: .LBB5_1: ; %Flow
@@ -991,11 +992,11 @@ define void @scc_liveness(i32 %arg) local_unnamed_addr #0 {
; GCN-NEXT: s_or_b64 exec, exec, s[10:11]
; GCN-NEXT: .LBB5_2: ; %bb10
; GCN-NEXT: ; in Loop: Header=BB5_3 Depth=1
-; GCN-NEXT: s_or_b64 exec, exec, s[14:15]
+; GCN-NEXT: s_or_b64 exec, exec, s[16:17]
; GCN-NEXT: s_and_b64 s[6:7], exec, s[4:5]
-; GCN-NEXT: s_or_b64 s[12:13], s[6:7], s[12:13]
+; GCN-NEXT: s_or_b64 s[14:15], s[6:7], s[14:15]
; GCN-NEXT: s_mov_b64 s[6:7], 0
-; GCN-NEXT: s_andn2_b64 exec, exec, s[12:13]
+; GCN-NEXT: s_andn2_b64 exec, exec, s[14:15]
; GCN-NEXT: s_cbranch_execz .LBB5_7
; GCN-NEXT: .LBB5_3: ; %bb1
; GCN-NEXT: ; =>This Inner Loop Header: Depth=1
@@ -1013,7 +1014,7 @@ define void @scc_liveness(i32 %arg) local_unnamed_addr #0 {
; GCN-NEXT: v_mov_b32_e32 v1, s9
; GCN-NEXT: v_mov_b32_e32 v2, s10
; GCN-NEXT: v_mov_b32_e32 v3, s11
-; GCN-NEXT: s_and_saveexec_b64 s[14:15], s[4:5]
+; GCN-NEXT: s_and_saveexec_b64 s[16:17], s[4:5]
; GCN-NEXT: s_cbranch_execz .LBB5_2
; GCN-NEXT: ; %bb.5: ; %bb4
; GCN-NEXT: ; in Loop: Header=BB5_3 Depth=1
@@ -1028,14 +1029,13 @@ define void @scc_liveness(i32 %arg) local_unnamed_addr #0 {
; GCN-NEXT: s_cbranch_execz .LBB5_1
; GCN-NEXT: ; %bb.6: ; %bb8
; GCN-NEXT: ; in Loop: Header=BB5_3 Depth=1
-; GCN-NEXT: s_mov_b32 s9, s8
-; GCN-NEXT: v_mov_b32_e32 v0, s8
-; GCN-NEXT: v_mov_b32_e32 v1, s9
-; GCN-NEXT: v_mov_b32_e32 v2, s10
-; GCN-NEXT: v_mov_b32_e32 v3, s11
+; GCN-NEXT: v_mov_b32_e32 v0, s12
+; GCN-NEXT: v_mov_b32_e32 v1, s13
+; GCN-NEXT: v_mov_b32_e32 v2, s14
+; GCN-NEXT: v_mov_b32_e32 v3, s15
; GCN-NEXT: s_branch .LBB5_1
; GCN-NEXT: .LBB5_7: ; %bb12
-; GCN-NEXT: s_or_b64 exec, exec, s[12:13]
+; GCN-NEXT: s_or_b64 exec, exec, s[14:15]
; GCN-NEXT: buffer_store_dword v3, v0, s[0:3], 0 offen
; GCN-NEXT: s_waitcnt vmcnt(0)
; GCN-NEXT: buffer_store_dword v2, v0, s[0:3], 0 offen
@@ -1168,7 +1168,7 @@ define void @scc_liveness(i32 %arg) local_unnamed_addr #0 {
; GCN-O0-NEXT: s_cbranch_execz .LBB5_6
; GCN-O0-NEXT: ; %bb.4: ; %bb8
; GCN-O0-NEXT: ; in Loop: Header=BB5_1 Depth=1
-; GCN-O0-NEXT: s_mov_b32 s10, 0
+; GCN-O0-NEXT: s_mov_b32 s10, 1.0
; GCN-O0-NEXT: ; implicit-def: $sgpr4
; GCN-O0-NEXT: ; implicit-def: $sgpr5
; GCN-O0-NEXT: ; implicit-def: $sgpr9
@@ -1372,7 +1372,7 @@ bb4: ; preds = %bb2
br i1 %tmp7, label %bb8, label %Flow
bb8: ; preds = %bb4
- %tmp9 = insertelement <4 x float> undef, float 0.0, i32 1
+ %tmp9 = insertelement <4 x float> undef, float 1.0, i32 1
br label %Flow
Flow: ; preds = %bb8, %bb4
>From a3551b8349a3d0eb38fded9a27c7c9b27e7c1023 Mon Sep 17 00:00:00 2001
From: Marius Kamp <msk at posteo.org>
Date: Fri, 11 Oct 2024 11:25:17 +0200
Subject: [PATCH 3/3] [InstSimplify] Fix Inconsistent PHI Simplification
Before this commit, the simplification of PHI functions was inconsistent
with the simplification of `select` instructions. The simplification of
`select` instructions includes special handling of vector operands,
which the simplification of PHI functions lacked. This resulted in
different simplifications for partially `undef` vectors.
This commit extends the simplification of PHI functions by handling also
vector, array, and struct operands that are partially `undef` or
`poison`. As is done for `select` operations, combining `undef` and
`poison` elements now yields an `undef` element.
This is consistent with the reasoning in Alive:
https://alive2.llvm.org/ce/z/vbmYTa
Fixes #98441.
---
llvm/lib/Analysis/InstructionSimplify.cpp | 108 ++++++++++++------
.../InstSimplify/phi-vec-unknown-poison.ll | 11 +-
2 files changed, 81 insertions(+), 38 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index d08be1e55c853e..8f400131083c59 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4802,6 +4802,35 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
return nullptr;
}
+/// Try to fold the given arguments of a select or PHI function of array,
+/// struct, or vector types. Return true if this is possible and false
+/// otherwise.
+static bool getCommonValueForAggregateOrVector(
+ unsigned NumElts, Constant *PreviousCommonC, Constant *CurrentC,
+ SmallVector<Constant *, 16> &NewCommonC, const SimplifyQuery &Q) {
+ for (unsigned I = 0; I != NumElts; ++I) {
+ // Bail out on incomplete array/struct/vector constants.
+ Constant *PrevElt = PreviousCommonC->getAggregateElement(I);
+ Constant *CurrElt = CurrentC->getAggregateElement(I);
+ if (!PrevElt || !CurrElt)
+ return false;
+
+ // If the elements match (undef or not), that value is the result. If only
+ // one element is undef, choose the defined element as the safe result.
+ if (PrevElt == CurrElt)
+ NewCommonC.push_back(PrevElt);
+ else if (isa<PoisonValue>(PrevElt) ||
+ (Q.isUndefValue(PrevElt) && isGuaranteedNotToBePoison(CurrElt)))
+ NewCommonC.push_back(CurrElt);
+ else if (isa<PoisonValue>(CurrElt) ||
+ (Q.isUndefValue(CurrElt) && isGuaranteedNotToBePoison(PrevElt)))
+ NewCommonC.push_back(PrevElt);
+ else
+ return false;
+ }
+ return true;
+}
+
/// Given operands for a SelectInst, see if we can fold the result.
/// If not, this returns null.
static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
@@ -4940,27 +4969,7 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
unsigned NumElts =
cast<FixedVectorType>(TrueC->getType())->getNumElements();
SmallVector<Constant *, 16> NewC;
- for (unsigned i = 0; i != NumElts; ++i) {
- // Bail out on incomplete vector constants.
- Constant *TEltC = TrueC->getAggregateElement(i);
- Constant *FEltC = FalseC->getAggregateElement(i);
- if (!TEltC || !FEltC)
- break;
-
- // If the elements match (undef or not), that value is the result. If only
- // one element is undef, choose the defined element as the safe result.
- if (TEltC == FEltC)
- NewC.push_back(TEltC);
- else if (isa<PoisonValue>(TEltC) ||
- (Q.isUndefValue(TEltC) && isGuaranteedNotToBePoison(FEltC)))
- NewC.push_back(FEltC);
- else if (isa<PoisonValue>(FEltC) ||
- (Q.isUndefValue(FEltC) && isGuaranteedNotToBePoison(TEltC)))
- NewC.push_back(TEltC);
- else
- break;
- }
- if (NewC.size() == NumElts)
+ if (getCommonValueForAggregateOrVector(NumElts, TrueC, FalseC, NewC, Q))
return ConstantVector::get(NewC);
}
@@ -5288,6 +5297,45 @@ Value *llvm::simplifyExtractElementInst(Value *Vec, Value *Idx,
return ::simplifyExtractElementInst(Vec, Idx, Q, RecursionLimit);
}
+/// Try to fold the given arguments to a PHI function. If this is not
+/// possible, return nullptr.
+static Value *getCommonPHIValue(Value *PreviousCommon, Value *Current,
+ const SimplifyQuery &Q) {
+ if (!PreviousCommon || PreviousCommon == Current)
+ return Current;
+
+ Constant *PreviousCommonC, *CurrentC;
+ if (match(PreviousCommon, m_Constant(PreviousCommonC)) &&
+ match(Current, m_Constant(CurrentC))) {
+ auto *Ty = PreviousCommonC->getType();
+ SmallVector<Constant *, 16> NewCommonC;
+ if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) {
+ if (getCommonValueForAggregateOrVector(VecTy->getNumElements(),
+ PreviousCommonC, CurrentC,
+ NewCommonC, Q))
+ return ConstantVector::get(NewCommonC);
+ } else if (auto *ArrayTy = dyn_cast<ArrayType>(Ty)) {
+ if (getCommonValueForAggregateOrVector(ArrayTy->getNumElements(),
+ PreviousCommonC, CurrentC,
+ NewCommonC, Q))
+ return ConstantArray::get(ArrayTy, NewCommonC);
+ } else if (auto *StructTy = dyn_cast<StructType>(Ty)) {
+ if (getCommonValueForAggregateOrVector(StructTy->getNumElements(),
+ PreviousCommonC, CurrentC,
+ NewCommonC, Q))
+ return ConstantStruct::get(StructTy, NewCommonC);
+ }
+ }
+
+ if (Q.isUndefValue(PreviousCommon))
+ return Current;
+
+ if (Q.isUndefValue(Current))
+ return PreviousCommon;
+
+ return nullptr;
+}
+
/// See if we can fold the given phi. If not, returns null.
static Value *simplifyPHINode(PHINode *PN, ArrayRef<Value *> IncomingValues,
const SimplifyQuery &Q) {
@@ -5308,21 +5356,17 @@ static Value *simplifyPHINode(PHINode *PN, ArrayRef<Value *> IncomingValues,
HasPoisonInput = true;
continue;
}
- if (Q.isUndefValue(Incoming)) {
- // Remember that we saw an undef value, but otherwise ignore them.
- HasUndefInput = true;
- continue;
- }
- if (CommonValue && Incoming != CommonValue)
+ // Remember if we saw an undef value.
+ HasUndefInput |= Q.isUndefValue(Incoming);
+ CommonValue = getCommonPHIValue(CommonValue, Incoming, Q);
+ if (!CommonValue)
return nullptr; // Not the same, bail out.
- CommonValue = Incoming;
}
- // If CommonValue is null then all of the incoming values were either undef,
- // poison or equal to the phi node itself.
+ // If CommonValue is null then all of the incoming values were either poison
+ // or equal to the phi node itself.
if (!CommonValue)
- return HasUndefInput ? UndefValue::get(PN->getType())
- : PoisonValue::get(PN->getType());
+ return PoisonValue::get(PN->getType());
if (HasPoisonInput || HasUndefInput) {
// If we have a PHI node like phi(X, undef, X), where X is defined by some
diff --git a/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll b/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll
index a59c3d619143ff..0582e6ed877dea 100644
--- a/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll
+++ b/llvm/test/Transforms/InstSimplify/phi-vec-unknown-poison.ll
@@ -10,7 +10,7 @@ define <2 x i1> @test_vec_undef_poison(i1 %c) {
; CHECK: [[F]]:
; CHECK-NEXT: br label %[[M]]
; CHECK: [[M]]:
-; CHECK-NEXT: ret <2 x i1> <i1 poison, i1 false>
+; CHECK-NEXT: ret <2 x i1> <i1 undef, i1 false>
;
br i1 %c, label %t, label %f
t:
@@ -31,7 +31,7 @@ define <2 x i1> @test_vec_poison_undef(i1 %c) {
; CHECK: [[F]]:
; CHECK-NEXT: br label %[[M]]
; CHECK: [[M]]:
-; CHECK-NEXT: ret <2 x i1> <i1 false, i1 poison>
+; CHECK-NEXT: ret <2 x i1> <i1 false, i1 undef>
;
br i1 %c, label %t, label %f
t:
@@ -56,8 +56,7 @@ define <2 x i1> @test_vec_poison_undef_defined(i1 %c1, i1 %c2) {
; CHECK: [[F]]:
; CHECK-NEXT: br label %[[M]]
; CHECK: [[M]]:
-; CHECK-NEXT: [[RES:%.*]] = phi <2 x i1> [ <i1 false, i1 poison>, %[[TT]] ], [ undef, %[[TF]] ], [ <i1 poison, i1 true>, %[[F]] ]
-; CHECK-NEXT: ret <2 x i1> [[RES]]
+; CHECK-NEXT: ret <2 x i1> <i1 false, i1 true>
;
br i1 %c1, label %t, label %f
t:
@@ -195,7 +194,7 @@ define [2 x double] @test_array_undef_poison(i1 %c) {
; CHECK: [[F]]:
; CHECK-NEXT: br label %[[M]]
; CHECK: [[M]]:
-; CHECK-NEXT: ret [2 x double] [double poison, double 0.000000e+00]
+; CHECK-NEXT: ret [2 x double] [double undef, double 0.000000e+00]
;
br i1 %c, label %t, label %f
t:
@@ -218,7 +217,7 @@ define %Struct @test_struct_undef_poison(i1 %c) {
; CHECK: [[F]]:
; CHECK-NEXT: br label %[[M]]
; CHECK: [[M]]:
-; CHECK-NEXT: ret [[STRUCT:%.*]] { i8 poison, i8 0 }
+; CHECK-NEXT: ret [[STRUCT:%.*]] { i8 undef, i8 0 }
;
br i1 %c, label %t, label %f
t:
More information about the llvm-commits
mailing list