diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 3f780285efe42..caea62ef2cc9c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1366,9 +1366,8 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel, // with different operands, which should not cause side-effects or trigger // undefined behavior). Only do this if CmpRHS is a constant, as // profitability is not clear for other cases. - // FIXME: Support vectors. if (OldOp == CmpLHS && match(NewOp, m_ImmConstant()) && - !match(OldOp, m_Constant()) && !Cmp.getType()->isVectorTy() && + !match(OldOp, m_Constant()) && isGuaranteedNotToBeUndef(NewOp, SQ.AC, &Sel, &DT)) if (replaceInInstruction(TrueVal, OldOp, NewOp)) return &Sel; diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index ad28ad980de5b..eb4723c86542d 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -983,7 +983,7 @@ define <2 x i1> @substitute_constant_or_ne_slt_swap_vec_poison(<2 x i8> %x, <2 x define <2 x i1> @substitute_constant_or_ne_slt_swap_vec_logical(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @substitute_constant_or_ne_slt_swap_vec_logical( ; CHECK-NEXT: [[C1:%.*]] = icmp ne <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[C2:%.*]] = icmp slt <2 x i8> [[Y:%.*]], [[X]] +; CHECK-NEXT: [[C2:%.*]] = icmp slt <2 x i8> [[Y:%.*]], ; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C1]], <2 x i1> , <2 x i1> [[C2]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; diff --git a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll index 647287ef5ebad..4e4ade4a37989 100644 --- a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll @@ -557,7 +557,7 @@ define i32 @select_xor_icmp_bad_6(i32 %x, i32 %y, i32 %z) { define <2 x i8> @select_xor_icmp_vec_bad(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { ; CHECK-LABEL: @select_xor_icmp_vec_bad( ; CHECK-NEXT: [[A:%.*]] = icmp eq <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[B:%.*]] = xor <2 x i8> [[X]], [[Z:%.*]] +; CHECK-NEXT: [[B:%.*]] = xor <2 x i8> [[Z:%.*]], ; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[A]], <2 x i8> [[B]], <2 x i8> [[Y:%.*]] ; CHECK-NEXT: ret <2 x i8> [[C]] ; @@ -571,10 +571,7 @@ define <2 x i8> @select_xor_icmp_vec_bad(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) define <2 x i32> @vec_select_no_equivalence(<2 x i32> %x) { ; CHECK-LABEL: @vec_select_no_equivalence( -; CHECK-NEXT: [[X10:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> poison, <2 x i32> -; CHECK-NEXT: [[COND:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer -; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[X10]], <2 x i32> [[X]] -; CHECK-NEXT: ret <2 x i32> [[S]] +; CHECK-NEXT: ret <2 x i32> [[S:%.*]] ; %x10 = shufflevector <2 x i32> %x, <2 x i32> undef, <2 x i32> %cond = icmp eq <2 x i32> %x, zeroinitializer diff --git a/llvm/test/Transforms/InstCombine/select-value-equivalence.ll b/llvm/test/Transforms/InstCombine/select-value-equivalence.ll new file mode 100644 index 0000000000000..a274683836bf3 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/select-value-equivalence.ll @@ -0,0 +1,182 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -passes=instcombine -S %s | FileCheck %s + +define <2 x i8> @select_icmp_insertelement_eq(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i8> @select_icmp_insertelement_eq( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[Y]], +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> , <2 x i8> [[X]] +; CHECK-NEXT: ret <2 x i8> [[RETVAL]] +; + %cmp = icmp eq <2 x i8> %y, + %insert = insertelement <2 x i8> %y, i8 0, i8 1 + %retval = select <2 x i1> %cmp, <2 x i8> %insert, <2 x i8> %x + ret <2 x i8> %retval +} + +define <2 x i8> @select_icmp_insertelement_ne(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i8> @select_icmp_insertelement_ne( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i8> [[Y]], +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> , <2 x i8> [[X]] +; CHECK-NEXT: ret <2 x i8> [[RETVAL]] +; + %cmp = icmp ne <2 x i8> %y, + %insert = insertelement <2 x i8> %y, i8 0, i8 1 + %retval = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %insert + ret <2 x i8> %retval +} + +define <2 x i8> @select_icmp_shufflevector(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i8> @select_icmp_shufflevector( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[Y]], +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> , <2 x i8> [[X]] +; CHECK-NEXT: ret <2 x i8> [[RETVAL]] +; + %cmp = icmp eq <2 x i8> %y, + %shuffle = shufflevector <2 x i8> %y, <2 x i8> poison, <2 x i32> + %retval = select <2 x i1> %cmp, <2 x i8> %shuffle, <2 x i8> %x + ret <2 x i8> %retval +} + +define <2 x i8> @select_icmp_udiv_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i8> @select_icmp_udiv_vec( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[Y]], +; CHECK-NEXT: [[UDIV:%.*]] = udiv <2 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[UDIV]], <2 x i8> [[X]] +; CHECK-NEXT: ret <2 x i8> [[RETVAL]] +; + %cmp = icmp eq <2 x i8> %y, + %udiv = udiv <2 x i8> %x, %y + %retval = select <2 x i1> %cmp, <2 x i8> %udiv, <2 x i8> %x + ret <2 x i8> %retval +} + +define <2 x i8> @select_icmp_urem_vec(<2 x i8> %x, <2 x i8> %y) { +; CHECK-LABEL: define <2 x i8> @select_icmp_urem_vec( +; CHECK-SAME: <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]]) { +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[Y]], +; CHECK-NEXT: [[UREM:%.*]] = urem <2 x i8> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[UREM]], <2 x i8> [[X]] +; CHECK-NEXT: ret <2 x i8> [[RETVAL]] +; + %cmp = icmp eq <2 x i8> %y, + %urem = urem <2 x i8> %x, %y + %retval = select <2 x i1> %cmp, <2 x i8> %urem, <2 x i8> %x + ret <2 x i8> %retval +} + +define <2 x double> @select_fcmp_fdiv_oeq_not_zero_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_oeq_not_zero_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <2 x double> [[Y]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[DIV]], <2 x double> [[X]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp oeq <2 x double> %y, + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %div, <2 x double> %x + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_une_not_zero_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_une_not_zero_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp une <2 x double> [[Y]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[X]], <2 x double> [[DIV]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp une <2 x double> %y, + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %x, <2 x double> %div + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_ueq_nnan_not_zero_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_ueq_nnan_not_zero_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan ueq <2 x double> [[Y]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[DIV]], <2 x double> [[X]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp nnan ueq <2 x double> %y, + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %div, <2 x double> %x + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_one_nnan_not_zero_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_one_nnan_not_zero_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp nnan one <2 x double> [[Y]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[X]], <2 x double> [[DIV]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp nnan one <2 x double> %y, + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %x, <2 x double> %div + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_ueq_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_ueq_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp ueq <2 x double> [[Y]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[DIV]], <2 x double> [[X]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp ueq <2 x double> %y, + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %div, <2 x double> %x + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_one_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_one_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp one <2 x double> [[Y]], +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[X]], <2 x double> [[DIV]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp one <2 x double> %y, + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %x, <2 x double> %div + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_oeq_zero_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_oeq_zero_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp oeq <2 x double> [[Y]], zeroinitializer +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[DIV]], <2 x double> [[X]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp oeq <2 x double> %y, zeroinitializer + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %div, <2 x double> %x + ret <2 x double> %retval +} + +define <2 x double> @select_fcmp_fdiv_une_zero_vec(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: define <2 x double> @select_fcmp_fdiv_une_zero_vec( +; CHECK-SAME: <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) { +; CHECK-NEXT: [[FCMP:%.*]] = fcmp une <2 x double> [[Y]], zeroinitializer +; CHECK-NEXT: [[DIV:%.*]] = fdiv <2 x double> [[X]], [[Y]] +; CHECK-NEXT: [[RETVAL:%.*]] = select <2 x i1> [[FCMP]], <2 x double> [[X]], <2 x double> [[DIV]] +; CHECK-NEXT: ret <2 x double> [[RETVAL]] +; + %fcmp = fcmp une <2 x double> %y, zeroinitializer + %div = fdiv <2 x double> %x, %y + %retval = select <2 x i1> %fcmp, <2 x double> %x, <2 x double> %div + ret <2 x double> %retval +} +