diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1028,9 +1028,9 @@ return SelectInst::Create(X, TVal, FVal); } -static Constant *constantFoldOperationIntoSelectOperand(Instruction &I, - SelectInst *SI, - bool IsTrueArm) { +static Constant * +constantFoldOperationIntoSelectOperand(Instruction &I, SelectInst *SI, + bool IsTrueArm, const SimplifyQuery &Q) { SmallVector ConstOps; for (Value *Op : I.operands()) { CmpInst::Predicate Pred; @@ -1040,7 +1040,9 @@ : SI->getFalseValue()); } else if (match(SI->getCondition(), m_ICmp(Pred, m_Specific(Op), m_Constant(C))) && - Pred == (IsTrueArm ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE)) { + Pred == (IsTrueArm ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE) && + isGuaranteedNotToBeUndefOrPoison(C, Q.AC, Q.CxtI, Q.DT, + /* Depth */ 0)) { // Pass } else { C = dyn_cast(Op); @@ -1093,8 +1095,11 @@ } // Make sure that one of the select arms constant folds successfully. - Value *NewTV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true); - Value *NewFV = constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false); + SimplifyQuery Q = SQ.getWithInstruction(SI); + Value *NewTV = + constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ true, Q); + Value *NewFV = + constantFoldOperationIntoSelectOperand(Op, SI, /*IsTrueArm*/ false, Q); if (!NewTV && !NewFV) return nullptr; diff --git a/llvm/test/Transforms/InstCombine/binop-select.ll b/llvm/test/Transforms/InstCombine/binop-select.ll --- a/llvm/test/Transforms/InstCombine/binop-select.ll +++ b/llvm/test/Transforms/InstCombine/binop-select.ll @@ -6,6 +6,7 @@ declare void @use_v2f16(<2 x half>) declare void @use_v2i8(<2 x i8>) declare i32 @llvm.sadd.sat.i32(i32, i32) +declare <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8>, <2 x i8>) define i32 @test1(i1 %c, i32 %x, i32 %y) { ; CHECK-LABEL: @test1( @@ -109,6 +110,47 @@ ret i32 %sub } +define <2 x i8> @test_sub_dont_deduce_with_undef_cond_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @test_sub_dont_deduce_with_undef_cond_vec( +; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[C_NOT]], <2 x i8> , <2 x i8> [[Y:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[COND]]) +; CHECK-NEXT: ret <2 x i8> [[SUB]] +; + %c = icmp ne <2 x i8> %x, + %cond = select <2 x i1> %c, <2 x i8> %y, <2 x i8> + %sub = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %x, <2 x i8> %cond) + ret <2 x i8> %sub +} + +define <2 x i8> @test_sub_dont_deduce_with_poison_cond_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @test_sub_dont_deduce_with_poison_cond_vec( +; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[C_NOT]], <2 x i8> , <2 x i8> [[Y:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[COND]]) +; CHECK-NEXT: ret <2 x i8> [[SUB]] +; + %c = icmp ne <2 x i8> %x, + %cond = select <2 x i1> %c, <2 x i8> %y, <2 x i8> + %sub = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %x, <2 x i8> %cond) + ret <2 x i8> %sub +} + + +define <2 x i8> @test_sub_deduce_with_undef_val_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: @test_sub_deduce_with_undef_val_vec( +; CHECK-NEXT: [[C_NOT:%.*]] = icmp eq <2 x i8> [[X:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[X]], <2 x i8> [[Y:%.*]]) +; CHECK-NEXT: [[SUB:%.*]] = select <2 x i1> [[C_NOT]], <2 x i8> , <2 x i8> [[TMP1]] +; CHECK-NEXT: ret <2 x i8> [[SUB]] +; + %c = icmp ne <2 x i8> %x, + %cond = select <2 x i1> %c, <2 x i8> %y, <2 x i8> + %sub = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %x, <2 x i8> %cond) + ret <2 x i8> %sub +} + + define i32 @test6(i1 %c, i32 %x, i32 %y) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: [[COND:%.*]] = select i1 [[C:%.*]], i32 7, i32 [[X:%.*]]