diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index adbd9186c59c5..9588930d7658c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -750,7 +750,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final Value *A, Value *B, Instruction &Outer, SelectPatternFlavor SPF2, Value *C); Instruction *foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI); - Instruction *foldSelectValueEquivalence(SelectInst &SI, ICmpInst &ICI); + Instruction *foldSelectValueEquivalence(SelectInst &SI, CmpInst &CI); bool replaceInInstruction(Value *V, Value *Old, Value *New, unsigned Depth = 0); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 010b77548c152..28dbca0270373 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1327,16 +1327,16 @@ bool InstCombinerImpl::replaceInInstruction(Value *V, Value *Old, Value *New, /// We can't replace %sel with %add unless we strip away the flags. /// TODO: Wrapping flags could be preserved in some cases with better analysis. Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, - ICmpInst &Cmp) { - if (!Cmp.isEquality()) - return nullptr; - - // Canonicalize the pattern to ICMP_EQ by swapping the select operands. + CmpInst &Cmp) { + // Canonicalize the pattern to an equivalence on the predicate by swapping the + // select operands. Value *TrueVal = Sel.getTrueValue(), *FalseVal = Sel.getFalseValue(); bool Swapped = false; - if (Cmp.getPredicate() == ICmpInst::ICMP_NE) { + if (Cmp.isEquivalence(/*Invert=*/true)) { std::swap(TrueVal, FalseVal); Swapped = true; + } else if (!Cmp.isEquivalence()) { + return nullptr; } Value *CmpLHS = Cmp.getOperand(0), *CmpRHS = Cmp.getOperand(1); @@ -1347,7 +1347,7 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, // would lead to an infinite replacement cycle. // If we will be able to evaluate f(Y) to a constant, we can allow undef, // otherwise Y cannot be undef as we might pick different values for undef - // in the icmp and in f(Y). + // in the cmp and in f(Y). if (TrueVal == OldOp) return nullptr; @@ -1901,9 +1901,6 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI, /// Visit a SelectInst that has an ICmpInst as its first operand. Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI) { - if (Instruction *NewSel = foldSelectValueEquivalence(SI, *ICI)) - return NewSel; - if (Value *V = canonicalizeSPF(*ICI, SI.getTrueValue(), SI.getFalseValue(), *this)) return replaceInstUsesWith(SI, V); @@ -3848,6 +3845,10 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { return Fabs; // See if we are selecting two values based on a comparison of the two values. + if (CmpInst *CI = dyn_cast(CondVal)) + if (Instruction *NewSel = foldSelectValueEquivalence(SI, *CI)) + return NewSel; + if (ICmpInst *ICI = dyn_cast(CondVal)) if (Instruction *Result = foldSelectInstWithICmp(SI, ICI)) return Result; diff --git a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll index cd8c29ba4cd81..e563cafbc7e4f 100644 --- a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll @@ -706,11 +706,10 @@ define i32 @select_lshr_icmp_const_different_values(i32 %x, i32 %y) { ret i32 %C } -; Invalid identity constant for FP op -define float @select_fadd_fcmp_bad(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fadd_fcmp_bad( +define float @select_fadd_fcmp_equiv(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fadd_fcmp_equiv( ; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], -1.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[X]], [[Z:%.*]] +; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[Z:%.*]], -1.000000e+00 ; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]] ; CHECK-NEXT: ret float [[C]] ; @@ -720,6 +719,19 @@ define float @select_fadd_fcmp_bad(float %x, float %y, float %z) { ret float %C } +define float @select_fadd_fcmp_equiv2(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fadd_fcmp_equiv2( +; CHECK-NEXT: [[A:%.*]] = fcmp une float [[X:%.*]], -1.000000e+00 +; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[Z:%.*]], -1.000000e+00 +; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[B]] +; CHECK-NEXT: ret float [[C]] +; + %A = fcmp une float %x, -1.0 + %B = fadd nsz float %x, %z + %C = select i1 %A, float %y, float %B + ret float %C +} + ; Invalid comparison type define float @select_fadd_fcmp_bad_2(float %x, float %y, float %z) { ; CHECK-LABEL: @select_fadd_fcmp_bad_2( @@ -893,24 +905,10 @@ define float @select_fadd_fcmp_bad_13(float %x, float %y, float %z) { ret float %C } -; Invalid identity constant for FP op -define float @select_fadd_fcmp_bad_14(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fadd_fcmp_bad_14( -; CHECK-NEXT: [[A:%.*]] = fcmp une float [[X:%.*]], -1.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[X]], [[Z:%.*]] -; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[Y:%.*]], float [[B]] -; CHECK-NEXT: ret float [[C]] -; - %A = fcmp une float %x, -1.0 - %B = fadd nsz float %x, %z - %C = select i1 %A, float %y, float %B - ret float %C -} - -define float @select_fmul_fcmp_bad(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fmul_fcmp_bad( +define float @select_fmul_fcmp_equiv(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fmul_fcmp_equiv( ; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 3.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fmul nsz float [[X]], [[Z:%.*]] +; CHECK-NEXT: [[B:%.*]] = fmul nsz float [[Z:%.*]], 3.000000e+00 ; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]] ; CHECK-NEXT: ret float [[C]] ; @@ -920,11 +918,10 @@ define float @select_fmul_fcmp_bad(float %x, float %y, float %z) { ret float %C } -define float @select_fmul_fcmp_bad_2(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fmul_fcmp_bad_2( +define float @select_fmul_fcmp_equiv2(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fmul_fcmp_equiv2( ; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fmul float [[X]], [[Z:%.*]] -; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]] +; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B:%.*]], float [[Y:%.*]] ; CHECK-NEXT: ret float [[C]] ; %A = fcmp oeq float %x, 1.0 @@ -959,10 +956,10 @@ define float @select_fmul_icmp_bad_2(float %x, float %y, float %z, i32 %k) { ret float %C } -define float @select_fdiv_fcmp_bad(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fdiv_fcmp_bad( +define float @select_fdiv_fcmp_equiv(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fdiv_fcmp_equiv( ; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fdiv float [[X]], [[Z:%.*]] +; CHECK-NEXT: [[B:%.*]] = fdiv float 1.000000e+00, [[Z:%.*]] ; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]] ; CHECK-NEXT: ret float [[C]] ; @@ -972,10 +969,10 @@ define float @select_fdiv_fcmp_bad(float %x, float %y, float %z) { ret float %C } -define float @select_fdiv_fcmp_bad_2(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fdiv_fcmp_bad_2( +define float @select_fdiv_fcmp_equiv2(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fdiv_fcmp_equiv2( ; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 3.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fdiv nsz float [[X]], [[Z:%.*]] +; CHECK-NEXT: [[B:%.*]] = fdiv nsz float 3.000000e+00, [[Z:%.*]] ; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]] ; CHECK-NEXT: ret float [[C]] ; @@ -1001,10 +998,10 @@ define float @select_fsub_fcmp_bad(float %x, float %y, float %z) { ret float %C } -define float @select_fsub_fcmp_bad_2(float %x, float %y, float %z) { -; CHECK-LABEL: @select_fsub_fcmp_bad_2( +define float @select_fsub_fcmp_equiv(float %x, float %y, float %z) { +; CHECK-LABEL: @select_fsub_fcmp_equiv( ; CHECK-NEXT: [[A:%.*]] = fcmp oeq float [[X:%.*]], 1.000000e+00 -; CHECK-NEXT: [[B:%.*]] = fsub nsz float [[Z:%.*]], [[X]] +; CHECK-NEXT: [[B:%.*]] = fadd nsz float [[Z:%.*]], -1.000000e+00 ; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], float [[B]], float [[Y:%.*]] ; CHECK-NEXT: ret float [[C]] ; diff --git a/llvm/test/Transforms/InstCombine/select-value-equivalence.ll b/llvm/test/Transforms/InstCombine/select-value-equivalence.ll index 433fafc7e553b..da2e59d760f96 100644 --- a/llvm/test/Transforms/InstCombine/select-value-equivalence.ll +++ b/llvm/test/Transforms/InstCombine/select-value-equivalence.ll @@ -90,7 +90,7 @@ define float @select_fcmp_fadd_oeq_not_zero(float %x, float %y) { ; CHECK-LABEL: define float @select_fcmp_fadd_oeq_not_zero( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq float [[Y]], 2.000000e+00 -; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], 2.000000e+00 ; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[FCMP]], float [[FADD]], float [[X]] ; CHECK-NEXT: ret float [[RETVAL]] ; @@ -104,7 +104,7 @@ define float @select_fcmp_fadd_une_not_zero(float %x, float %y) { ; CHECK-LABEL: define float @select_fcmp_fadd_une_not_zero( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp une float [[Y]], 2.000000e+00 -; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], 2.000000e+00 ; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[FCMP]], float [[X]], float [[FADD]] ; CHECK-NEXT: ret float [[RETVAL]] ; @@ -118,7 +118,7 @@ define float @select_fcmp_fadd_ueq_nnan_not_zero(float %x, float %y) { ; CHECK-LABEL: define float @select_fcmp_fadd_ueq_nnan_not_zero( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan ueq float [[Y]], 2.000000e+00 -; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], 2.000000e+00 ; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[FCMP]], float [[FADD]], float [[X]] ; CHECK-NEXT: ret float [[RETVAL]] ; @@ -132,7 +132,7 @@ define float @select_fcmp_fadd_one_nnan_not_zero(float %x, float %y) { ; CHECK-LABEL: define float @select_fcmp_fadd_one_nnan_not_zero( ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan one float [[Y]], 2.000000e+00 -; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd float [[X]], 2.000000e+00 ; CHECK-NEXT: [[RETVAL:%.*]] = select i1 [[FCMP]], float [[X]], float [[FADD]] ; CHECK-NEXT: ret float [[RETVAL]] ; @@ -202,7 +202,7 @@ define <2 x float> @select_fcmp_fadd_oeq_not_zero_vec(<2 x float> %x, <2 x float ; CHECK-LABEL: define <2 x float> @select_fcmp_fadd_oeq_not_zero_vec( ; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <2 x float> [[Y]], splat (float 2.000000e+00) -; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], splat (float 2.000000e+00) ; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[FADD]], <2 x float> [[X]] ; CHECK-NEXT: ret <2 x float> [[RETVAL]] ; @@ -216,7 +216,7 @@ define <2 x float> @select_fcmp_fadd_une_not_zero_vec(<2 x float> %x, <2 x float ; CHECK-LABEL: define <2 x float> @select_fcmp_fadd_une_not_zero_vec( ; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp une <2 x float> [[Y]], splat (float 2.000000e+00) -; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], splat (float 2.000000e+00) ; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[X]], <2 x float> [[FADD]] ; CHECK-NEXT: ret <2 x float> [[RETVAL]] ; @@ -230,7 +230,7 @@ define <2 x float> @select_fcmp_fadd_ueq_nnan_not_zero_vec(<2 x float> %x, <2 x ; CHECK-LABEL: define <2 x float> @select_fcmp_fadd_ueq_nnan_not_zero_vec( ; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan ueq <2 x float> [[Y]], splat (float 2.000000e+00) -; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], splat (float 2.000000e+00) ; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[FADD]], <2 x float> [[X]] ; CHECK-NEXT: ret <2 x float> [[RETVAL]] ; @@ -244,7 +244,7 @@ define <2 x float> @select_fcmp_fadd_one_nnan_not_zero_vec(<2 x float> %x, <2 x ; CHECK-LABEL: define <2 x float> @select_fcmp_fadd_one_nnan_not_zero_vec( ; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) { ; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan one <2 x float> [[Y]], splat (float 2.000000e+00) -; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], [[Y]] +; CHECK-NEXT: [[FADD:%.*]] = fadd <2 x float> [[X]], splat (float 2.000000e+00) ; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x float> [[X]], <2 x float> [[FADD]] ; CHECK-NEXT: ret <2 x float> [[RETVAL]] ;