diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -734,6 +734,11 @@ if (Constant *C = foldOrCommuteConstant(Instruction::Sub, Op0, Op1, Q)) return C; + // X - poison -> poison + // poison - X -> poison + if (isa(Op0) || isa(Op1)) + return PoisonValue::get(Op0->getType()); + // X - undef -> undef // undef - X -> undef if (Q.isUndefValue(Op0) || Q.isUndefValue(Op1)) @@ -869,6 +874,10 @@ if (Constant *C = foldOrCommuteConstant(Instruction::Mul, Op0, Op1, Q)) return C; + // X * poison -> poison + if (isa(Op1)) + return Op1; + // X * undef -> 0 // X * 0 -> 0 if (Q.isUndefValue(Op1) || match(Op1, m_Zero())) @@ -955,6 +964,11 @@ } } + // poison / X -> poison + // poison % X -> poison + if (isa(Op0)) + return Op0; + // undef / X -> 0 // undef % X -> 0 if (Q.isUndefValue(Op0)) @@ -1241,6 +1255,10 @@ if (Constant *C = foldOrCommuteConstant(Opcode, Op0, Op1, Q)) return C; + // poison shift by X -> poison + if (isa(Op0)) + return Op0; + // 0 shift by X -> 0 if (match(Op0, m_Zero())) return Constant::getNullValue(Op0->getType()); @@ -1984,6 +2002,10 @@ if (Constant *C = foldOrCommuteConstant(Instruction::And, Op0, Op1, Q)) return C; + // X & poison -> poison + if (isa(Op1)) + return Op1; + // X & undef -> 0 if (Q.isUndefValue(Op1)) return Constant::getNullValue(Op0->getType()); @@ -2152,6 +2174,10 @@ if (Constant *C = foldOrCommuteConstant(Instruction::Or, Op0, Op1, Q)) return C; + // X | poison -> poison + if (isa(Op1)) + return Op1; + // X | undef -> -1 // X | -1 = -1 // Do not return Op1 because it may contain undef elements if it's a vector. @@ -3689,6 +3715,11 @@ if (match(RHS, m_NaN())) return ConstantInt::get(RetTy, CmpInst::isUnordered(Pred)); + // fcmp pred x, poison and fcmp pred poison, x + // fold to poison + if (isa(LHS) || isa(RHS)) + return PoisonValue::get(RetTy); + // fcmp pred x, undef and fcmp pred undef, x // fold to true if unordered, false if ordered if (Q.isUndefValue(LHS) || Q.isUndefValue(RHS)) { @@ -4156,6 +4187,10 @@ if (auto *FalseC = dyn_cast(FalseVal)) return ConstantFoldSelectInstruction(CondC, TrueC, FalseC); + // select poison, X, Y -> poison + if (isa(CondC)) + return PoisonValue::get(TrueVal->getType()); + // select undef, X, Y -> X or Y if (Q.isUndefValue(CondC)) return isa(FalseVal) ? FalseVal : TrueVal; @@ -4183,15 +4218,20 @@ if (TrueVal == FalseVal) return TrueVal; + // If the true or false value is poison, we can fold to the other value. // If the true or false value is undef, we can fold to the other value as // long as the other value isn't poison. - // select ?, undef, X -> X - if (Q.isUndefValue(TrueVal) && - isGuaranteedNotToBeUndefOrPoison(FalseVal, Q.AC, Q.CxtI, Q.DT)) + // select ?, poison, X -> X + // select ?, undef, X -> X + if (isa(TrueVal) || + (Q.isUndefValue(TrueVal) && + isGuaranteedNotToBePoison(FalseVal, Q.AC, Q.CxtI, Q.DT))) return FalseVal; - // select ?, X, undef -> X - if (Q.isUndefValue(FalseVal) && - isGuaranteedNotToBeUndefOrPoison(TrueVal, Q.AC, Q.CxtI, Q.DT)) + // select ?, X, poison -> X + // select ?, X, undef -> X + if (isa(FalseVal) || + (Q.isUndefValue(FalseVal) && + isGuaranteedNotToBePoison(TrueVal, Q.AC, Q.CxtI, Q.DT))) return TrueVal; // Deal with partial undef vector constants: select ?, VecC, VecC' --> VecC'' @@ -4213,11 +4253,11 @@ // one element is undef, choose the defined element as the safe result. if (TEltC == FEltC) NewC.push_back(TEltC); - else if (Q.isUndefValue(TEltC) && - isGuaranteedNotToBeUndefOrPoison(FEltC)) + else if (isa(TEltC) || + (Q.isUndefValue(TEltC) && isGuaranteedNotToBePoison(FEltC))) NewC.push_back(FEltC); - else if (Q.isUndefValue(FEltC) && - isGuaranteedNotToBeUndefOrPoison(TEltC)) + else if (isa(FEltC) || + (Q.isUndefValue(FEltC) && isGuaranteedNotToBePoison(TEltC))) NewC.push_back(TEltC); else break; diff --git a/llvm/test/Transforms/InstCombine/and-narrow.ll b/llvm/test/Transforms/InstCombine/and-narrow.ll --- a/llvm/test/Transforms/InstCombine/and-narrow.ll +++ b/llvm/test/Transforms/InstCombine/and-narrow.ll @@ -177,7 +177,7 @@ define <2 x i16> @zext_lshr_vec_undef(<2 x i8> %x) { ; CHECK-LABEL: @zext_lshr_vec_undef( -; CHECK-NEXT: ret <2 x i16> zeroinitializer +; CHECK-NEXT: ret <2 x i16> poison ; %z = zext <2 x i8> %x to <2 x i16> %b = lshr <2 x i16> %z, undef @@ -202,7 +202,7 @@ define <2 x i16> @zext_shl_vec_undef(<2 x i8> %x) { ; CHECK-LABEL: @zext_shl_vec_undef( -; CHECK-NEXT: ret <2 x i16> zeroinitializer +; CHECK-NEXT: ret <2 x i16> poison ; %z = zext <2 x i8> %x to <2 x i16> %b = shl <2 x i16> %z, undef diff --git a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll --- a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll @@ -31,7 +31,7 @@ define i32 @select_xor_icmp_meta(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_xor_icmp_meta( ; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], 0 -; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[Z:%.*]], i32 [[Y:%.*]], !prof !0 +; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[Z:%.*]], i32 [[Y:%.*]], !prof [[PROF0:![0-9]+]] ; CHECK-NEXT: ret i32 [[C]] ; %A = icmp eq i32 %x, 0 @@ -1270,9 +1270,7 @@ ; replacing the udiv result by poisong is fine. define i32 @select_replace_udiv_non_speculatable(i32 %x, i32 %y) { ; CHECK-LABEL: @select_replace_udiv_non_speculatable( -; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[X:%.*]], 0 -; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 poison, i32 [[Y:%.*]] -; CHECK-NEXT: ret i32 [[S]] +; CHECK-NEXT: ret i32 [[Y:%.*]] ; %c = icmp eq i32 %x, 0 %div = udiv i32 %y, %x diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll b/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll --- a/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/poison.ll @@ -115,10 +115,9 @@ ret void } -; TODO: these must be folded into poison; D92270 define void @logicalops_i1(i1 %x) { ; CHECK-LABEL: @logicalops_i1( -; CHECK-NEXT: call void (...) @use(i1 true, i1 false) +; CHECK-NEXT: call void (...) @use(i1 poison, i1 poison) ; CHECK-NEXT: ret void ; %i1 = or i1 %x, poison diff --git a/llvm/test/Transforms/InstSimplify/and.ll b/llvm/test/Transforms/InstSimplify/and.ll --- a/llvm/test/Transforms/InstSimplify/and.ll +++ b/llvm/test/Transforms/InstSimplify/and.ll @@ -1,11 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s -; TODO: this should be poison - define i32 @poison(i32 %x) { ; CHECK-LABEL: @poison( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: ret i32 poison ; %v = and i32 %x, poison ret i32 %v diff --git a/llvm/test/Transforms/InstSimplify/fcmp.ll b/llvm/test/Transforms/InstSimplify/fcmp.ll --- a/llvm/test/Transforms/InstSimplify/fcmp.ll +++ b/llvm/test/Transforms/InstSimplify/fcmp.ll @@ -1,10 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instsimplify -S | FileCheck %s -; TODO: these should be poison define i1 @poison(float %x) { ; CHECK-LABEL: @poison( -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: ret i1 poison ; %v = fcmp oeq float %x, poison ret i1 %v @@ -12,7 +11,7 @@ define i1 @poison2(float %x) { ; CHECK-LABEL: @poison2( -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 poison ; %v = fcmp ueq float %x, poison ret i1 %v diff --git a/llvm/test/Transforms/InstSimplify/mul.ll b/llvm/test/Transforms/InstSimplify/mul.ll --- a/llvm/test/Transforms/InstSimplify/mul.ll +++ b/llvm/test/Transforms/InstSimplify/mul.ll @@ -42,11 +42,9 @@ ret <2 x i8> %b } -; TODO: this should be poison - define i32 @poison(i32 %x) { ; CHECK-LABEL: @poison( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: ret i32 poison ; %v = mul i32 %x, poison ret i32 %v diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -292,11 +292,9 @@ ret <2 x i1> %r } -; TODO: this should be poison - define i32 @poison(i32 %x) { ; CHECK-LABEL: @poison( -; CHECK-NEXT: ret i32 -1 +; CHECK-NEXT: ret i32 poison ; %v = or i32 %x, poison ret i32 %v diff --git a/llvm/test/Transforms/InstSimplify/select-inseltpoison.ll b/llvm/test/Transforms/InstSimplify/select-inseltpoison.ll --- a/llvm/test/Transforms/InstSimplify/select-inseltpoison.ll +++ b/llvm/test/Transforms/InstSimplify/select-inseltpoison.ll @@ -965,8 +965,6 @@ ret %s } -; TODO: these can be optimized more - define i32 @poison(i32 %x, i32 %y) { ; CHECK-LABEL: @poison( ; CHECK-NEXT: ret i32 [[X:%.*]] @@ -977,8 +975,7 @@ define i32 @poison2(i1 %cond, i32 %x) { ; CHECK-LABEL: @poison2( -; CHECK-NEXT: [[V:%.*]] = select i1 [[COND:%.*]], i32 poison, i32 [[X:%.*]] -; CHECK-NEXT: ret i32 [[V]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %v = select i1 %cond, i32 poison, i32 %x ret i32 %v @@ -986,8 +983,7 @@ define i32 @poison3(i1 %cond, i32 %x) { ; CHECK-LABEL: @poison3( -; CHECK-NEXT: [[V:%.*]] = select i1 [[COND:%.*]], i32 [[X:%.*]], i32 poison -; CHECK-NEXT: ret i32 [[V]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %v = select i1 %cond, i32 %x, i32 poison ret i32 %v @@ -995,8 +991,7 @@ define <2 x i32> @poison4(<2 x i1> %cond, <2 x i32> %x) { ; CHECK-LABEL: @poison4( -; CHECK-NEXT: [[V:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> [[X:%.*]], <2 x i32> poison -; CHECK-NEXT: ret <2 x i32> [[V]] +; CHECK-NEXT: ret <2 x i32> [[X:%.*]] ; %v = select <2 x i1> %cond, <2 x i32> %x, <2 x i32> poison ret <2 x i32> %v diff --git a/llvm/test/Transforms/InstSimplify/select.ll b/llvm/test/Transforms/InstSimplify/select.ll --- a/llvm/test/Transforms/InstSimplify/select.ll +++ b/llvm/test/Transforms/InstSimplify/select.ll @@ -957,8 +957,7 @@ ; Partial undef scalable vectors should be ignored. define @ignore_scalable_undef( %cond) { ; CHECK-LABEL: @ignore_scalable_undef( -; CHECK-NEXT: [[S:%.*]] = select [[COND:%.*]], undef, insertelement ( undef, i1 true, i32 0) -; CHECK-NEXT: ret [[S]] +; CHECK-NEXT: ret insertelement ( undef, i1 true, i32 0) ; %vec = insertelement undef, i1 true, i32 0 %s = select %cond, undef, %vec @@ -1036,8 +1035,6 @@ ret <2 x i32> %s } -; TODO: these can be optimized more - define i32 @poison(i32 %x, i32 %y) { ; CHECK-LABEL: @poison( ; CHECK-NEXT: ret i32 [[X:%.*]] @@ -1048,8 +1045,7 @@ define i32 @poison2(i1 %cond, i32 %x) { ; CHECK-LABEL: @poison2( -; CHECK-NEXT: [[V:%.*]] = select i1 [[COND:%.*]], i32 poison, i32 [[X:%.*]] -; CHECK-NEXT: ret i32 [[V]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %v = select i1 %cond, i32 poison, i32 %x ret i32 %v @@ -1057,8 +1053,7 @@ define i32 @poison3(i1 %cond, i32 %x) { ; CHECK-LABEL: @poison3( -; CHECK-NEXT: [[V:%.*]] = select i1 [[COND:%.*]], i32 [[X:%.*]], i32 poison -; CHECK-NEXT: ret i32 [[V]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %v = select i1 %cond, i32 %x, i32 poison ret i32 %v @@ -1066,8 +1061,7 @@ define <2 x i32> @poison4(<2 x i1> %cond, <2 x i32> %x) { ; CHECK-LABEL: @poison4( -; CHECK-NEXT: [[V:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i32> [[X:%.*]], <2 x i32> poison -; CHECK-NEXT: ret <2 x i32> [[V]] +; CHECK-NEXT: ret <2 x i32> [[X:%.*]] ; %v = select <2 x i1> %cond, <2 x i32> %x, <2 x i32> poison ret <2 x i32> %v diff --git a/llvm/test/Transforms/InstSimplify/shift.ll b/llvm/test/Transforms/InstSimplify/shift.ll --- a/llvm/test/Transforms/InstSimplify/shift.ll +++ b/llvm/test/Transforms/InstSimplify/shift.ll @@ -262,11 +262,9 @@ ret i32 %v } -; TODO: these should be poison - define i32 @poison4(i32 %x) { ; CHECK-LABEL: @poison4( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: ret i32 poison ; %v = lshr i32 poison, %x ret i32 %v @@ -274,7 +272,7 @@ define i32 @poison5(i32 %x) { ; CHECK-LABEL: @poison5( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: ret i32 poison ; %v = ashr i32 poison, %x ret i32 %v @@ -282,7 +280,7 @@ define i32 @poison6(i32 %x) { ; CHECK-LABEL: @poison6( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: ret i32 poison ; %v = shl i32 poison, %x ret i32 %v diff --git a/llvm/test/Transforms/InstSimplify/sub.ll b/llvm/test/Transforms/InstSimplify/sub.ll --- a/llvm/test/Transforms/InstSimplify/sub.ll +++ b/llvm/test/Transforms/InstSimplify/sub.ll @@ -51,11 +51,9 @@ ret <2 x i32> %C } -; TODO: these should be poison - define i32 @poison1(i32 %x) { ; CHECK-LABEL: @poison1( -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: ret i32 poison ; %v = sub i32 %x, poison ret i32 %v @@ -63,7 +61,7 @@ define i32 @poison2(i32 %x) { ; CHECK-LABEL: @poison2( -; CHECK-NEXT: ret i32 undef +; CHECK-NEXT: ret i32 poison ; %v = sub i32 poison, %x ret i32 %v