diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -6472,6 +6472,36 @@ if (Instruction *Res = foldReductionIdiom(I, Builder, DL)) return Res; + { + Value *A, *B, *C, *D; + + // Find hidden xor optimization (only works if `C` and `D` have no common + // bits) (icmp eq (and (select A, C, D), (select B, C, D)), 0) --> (xor A, + // B) + if (I.getPredicate() == ICmpInst::ICMP_EQ && + match(Op0, m_And(m_Select(m_Value(A), m_Value(C), m_Value(D)), + m_Select(m_Value(B), m_Specific(C), m_Specific(D)))) && + match(Op1, m_Zero()) && + isKnownNonZero(C, DL, /*Depth*/ 0, &AC, &I, &DT) && + isKnownNonZero(D, DL, /*Depth*/ 0, &AC, &I, &DT) && + haveNoCommonBitsSet(C, D, DL, &AC, &I, &DT)) { + return BinaryOperator::CreateXor(A, B); + } + // (icmp ne (and (select A, C, D), (select B, C, D)), 0) --> (not (xor A, + // B), true) + if (I.getPredicate() == ICmpInst::ICMP_NE && + match(Op0, m_OneUse(m_And( + m_Select(m_Value(A), m_Value(C), m_Value(D)), + m_Select(m_Value(B), m_Specific(C), m_Specific(D))))) && + match(Op1, m_Zero()) && + isKnownNonZero(C, DL, /*Depth*/ 0, &AC, &I, &DT) && + isKnownNonZero(D, DL, /*Depth*/ 0, &AC, &I, &DT) && + haveNoCommonBitsSet(C, D, DL, &AC, &I, &DT)) { + Value *Xor = Builder.CreateXor(A, B); + return BinaryOperator::CreateNeg(Xor); + } + } + return Changed ? &I : nullptr; } diff --git a/llvm/test/Transforms/InstCombine/select_and_icmpeq.ll b/llvm/test/Transforms/InstCombine/select_and_icmpeq.ll --- a/llvm/test/Transforms/InstCombine/select_and_icmpeq.ll +++ b/llvm/test/Transforms/InstCombine/select_and_icmpeq.ll @@ -1,14 +1,12 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s -declare void @use32(i32) -declare void @use16(i16) -declare void @use7(i7) -declare void @use3(i3) - -define i1 @select_and_icmpeq_i32_commuted1(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i32_commuted1( -; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]] +define i1 @select_and_icmpeq_i32(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpeq_i32( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i32 2, i32 1 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i32 2, i32 1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; %s1 = select i1 %x, i32 2, i32 1 @@ -18,49 +16,16 @@ ret i1 %icmp } -define i1 @select_and_icmpeq_i32_commuted2(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i32_commuted2( -; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: ret i1 [[ICMP]] -; - %s1 = select i1 %y, i32 4, i32 1 - %s2 = select i1 %x, i32 4, i32 1 - %and = and i32 %s2, %s1 - %icmp = icmp eq i32 %and, 0 - ret i1 %icmp -} - -define i1 @select_and_icmpeq_i32_commuted3(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i32_commuted3( -; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: ret i1 [[ICMP]] -; - %s1 = select i1 %y, i32 3, i32 12 - %s2 = select i1 %x, i32 3, i32 12 - %and = and i32 %s1, %s2 - %icmp = icmp eq i32 %and, 0 - ret i1 %icmp -} - -define i1 @select_and_icmpeq_i32_commuted4(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i32_commuted4( -; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: ret i1 [[ICMP]] -; - %s1 = select i1 %y, i32 3, i32 16 - %s2 = select i1 %x, i32 3, i32 16 - %and = and i32 %s2, %s1 - %icmp = icmp eq i32 %and, 0 - ret i1 %icmp -} - define i1 @select_and_icmpeq_i9(i1 %x, i1 %y) { ; CHECK-LABEL: @select_and_icmpeq_i9( -; CHECK-NEXT: [[ICMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i9 3, i9 16 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i9 3, i9 16 +; CHECK-NEXT: [[AND:%.*]] = and i9 [[S2]], [[S1]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i9 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i9 3, i9 16 - %s2 = select i1 %x, i9 3, i9 16 + %s1 = select i1 %x, i9 3, i9 16 + %s2 = select i1 %y, i9 3, i9 16 %and = and i9 %s2, %s1 %icmp = icmp eq i9 %and, 0 ret i1 %icmp @@ -68,87 +33,71 @@ define <5 x i1> @select_and_icmpeq_i1vec(<5 x i1> %x, <5 x i1> %y) { ; CHECK-LABEL: @select_and_icmpeq_i1vec( -; CHECK-NEXT: [[S1:%.*]] = select <5 x i1> [[Y:%.*]], <5 x i32> , <5 x i32> -; CHECK-NEXT: [[S2:%.*]] = select <5 x i1> [[X:%.*]], <5 x i32> , <5 x i32> +; CHECK-NEXT: [[S1:%.*]] = select <5 x i1> [[X:%.*]], <5 x i32> , <5 x i32> +; CHECK-NEXT: [[S2:%.*]] = select <5 x i1> [[Y:%.*]], <5 x i32> , <5 x i32> ; CHECK-NEXT: [[AND:%.*]] = and <5 x i32> [[S2]], [[S1]] ; CHECK-NEXT: [[ICMP:%.*]] = icmp eq <5 x i32> [[AND]], zeroinitializer ; CHECK-NEXT: ret <5 x i1> [[ICMP]] ; - %s1 = select <5 x i1> %y, <5 x i32> , <5 x i32> - %s2 = select <5 x i1> %x, <5 x i32> , <5 x i32> + %s1 = select <5 x i1> %x, <5 x i32> , <5 x i32> + %s2 = select <5 x i1> %y, <5 x i32> , <5 x i32> %and = and <5 x i32> %s2, %s1 %icmp = icmp eq <5 x i32> %and, ret <5 x i1> %icmp } -define i1 @select_and_icmpeq_i32_multiuse_select1(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i32_multiuse_select1( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 4, i32 1 -; CHECK-NEXT: call void @use32(i32 [[S1]]) -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 4, i32 1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[S2]], [[S1]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[ICMP]] +define i1 @select_and_icmpeq_i8_negative_other_pred(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpeq_i8_negative_other_pred( +; CHECK-NEXT: ret i1 false ; - %s1 = select i1 %y, i32 4, i32 1 - call void @use32(i32 %s1) ; extra use of first select - %s2 = select i1 %x, i32 4, i32 1 - %and = and i32 %s2, %s1 - %icmp = icmp eq i32 %and, 0 + %s1 = select i1 %x, i8 1, i8 8 + %s2 = select i1 %y, i8 1, i8 8 + %and = and i8 %s1, %s2 + %icmp = icmp ult i8 %and, 0 ret i1 %icmp } -define i1 @select_and_icmpeq_i16_multiuse_select2(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i16_multiuse_select2( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i16 4, i16 1 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i16 4, i16 1 -; CHECK-NEXT: call void @use16(i16 [[S2]]) -; CHECK-NEXT: [[AND:%.*]] = and i16 [[S2]], [[S1]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i16 [[AND]], 0 +define i1 @select_and_icmpeq_i4_negative_select_arm_zero(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpeq_i4_negative_select_arm_zero( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i4 2, i4 1 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i4 2, i4 1 +; CHECK-NEXT: [[AND:%.*]] = and i4 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i4 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i16 4, i16 1 - %s2 = select i1 %x, i16 4, i16 1 - call void @use16(i16 %s2) ; extra use of second select - %and = and i16 %s2, %s1 - %icmp = icmp eq i16 %and, 0 + %s1 = select i1 %x, i4 2, i4 1 + %s2 = select i1 %y, i4 2, i4 1 + %and = and i4 %s1, %s2 + %icmp = icmp eq i4 %and, 0 ret i1 %icmp } -define i1 @select_and_icmpeq_i3_multiuse_and(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i3_multiuse_and( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i3 1, i3 2 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i3 1, i3 2 -; CHECK-NEXT: [[AND:%.*]] = and i3 [[S2]], [[S1]] -; CHECK-NEXT: call void @use3(i3 [[AND]]) -; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i3 [[AND]], 0 +define i1 @select_and_icmpeq_i12_negative_one_select_pair_matching1(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpeq_i12_negative_one_select_pair_matching1( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i12 0, i12 4 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i12 2, i12 4 +; CHECK-NEXT: [[AND:%.*]] = and i12 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i12 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i3 1, i3 2 - %s2 = select i1 %x, i3 1, i3 2 - %and = and i3 %s2, %s1 - call void @use3(i3 %and) ; extra use of and - %icmp = icmp eq i3 %and, 0 + %s1 = select i1 %x, i12 1, i12 4 + %s2 = select i1 %y, i12 2, i12 4 + %and = and i12 %s1, %s2 + %icmp = icmp eq i12 %and, 0 ret i1 %icmp } -define i1 @select_and_icmpeq_i7_multiuse_all(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpeq_i7_multiuse_all( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i7 1, i7 2 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i7 1, i7 2 -; CHECK-NEXT: [[AND:%.*]] = and i7 [[S2]], [[S1]] -; CHECK-NEXT: call void @use7(i7 [[S1]]) -; CHECK-NEXT: call void @use7(i7 [[S2]]) -; CHECK-NEXT: call void @use7(i7 [[AND]]) -; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i7 [[AND]], 0 +define i1 @select_and_icmpeq_i13_negative_one_select_pair_matching2(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpeq_i13_negative_one_select_pair_matching2( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i13 2, i13 0 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i13 2, i13 4 +; CHECK-NEXT: [[AND:%.*]] = and i13 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i13 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i7 1, i7 2 - %s2 = select i1 %x, i7 1, i7 2 - %and = and i7 %s2, %s1 - call void @use7(i7 %s1) ; extra use of first select - call void @use7(i7 %s2) ; extra use of second select - call void @use7(i7 %and) ; extra use of and - %icmp = icmp eq i7 %and, 0 + %s1 = select i1 %x, i13 2, i13 8 + %s2 = select i1 %y, i13 2, i13 4 + %and = and i13 %s1, %s2 + %icmp = icmp eq i13 %and, 0 ret i1 %icmp } diff --git a/llvm/test/Transforms/InstCombine/select_and_icmpne.ll b/llvm/test/Transforms/InstCombine/select_and_icmpne.ll --- a/llvm/test/Transforms/InstCombine/select_and_icmpne.ll +++ b/llvm/test/Transforms/InstCombine/select_and_icmpne.ll @@ -1,13 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s -declare void @use32(i32) -declare void @use16(i16) -declare void @use7(i7) -declare void @use3(i3) - -define i1 @select_and_icmpne_i32_commuted1(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i32_commuted1( +define i1 @select_and_icmpne_i32(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpne_i32( ; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i32 2, i32 1 ; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i32 2, i32 1 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[S1]], [[S2]] @@ -21,61 +16,16 @@ ret i1 %icmp } -define i1 @select_and_icmpne_i32_commuted2(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i32_commuted2( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 4, i32 1 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 4, i32 1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[S2]], [[S1]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[ICMP]] -; - %s1 = select i1 %y, i32 4, i32 1 - %s2 = select i1 %x, i32 4, i32 1 - %and = and i32 %s2, %s1 - %icmp = icmp ne i32 %and, 0 - ret i1 %icmp -} - -define i1 @select_and_icmpne_i32_commuted3(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i32_commuted3( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 3, i32 12 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 3, i32 12 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[S1]], [[S2]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[ICMP]] -; - %s1 = select i1 %y, i32 3, i32 12 - %s2 = select i1 %x, i32 3, i32 12 - %and = and i32 %s1, %s2 - %icmp = icmp ne i32 %and, 0 - ret i1 %icmp -} - -define i1 @select_and_icmpne_i32_commuted4(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i32_commuted4( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 3, i32 16 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 3, i32 16 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[S2]], [[S1]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32 [[AND]], 0 -; CHECK-NEXT: ret i1 [[ICMP]] -; - %s1 = select i1 %y, i32 3, i32 16 - %s2 = select i1 %x, i32 3, i32 16 - %and = and i32 %s2, %s1 - %icmp = icmp ne i32 %and, 0 - ret i1 %icmp -} - define i1 @select_and_icmpne_i9(i1 %x, i1 %y) { ; CHECK-LABEL: @select_and_icmpne_i9( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i9 3, i9 16 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i9 3, i9 16 +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i9 3, i9 16 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i9 3, i9 16 ; CHECK-NEXT: [[AND:%.*]] = and i9 [[S2]], [[S1]] ; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i9 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i9 3, i9 16 - %s2 = select i1 %x, i9 3, i9 16 + %s1 = select i1 %x, i9 3, i9 16 + %s2 = select i1 %y, i9 3, i9 16 %and = and i9 %s2, %s1 %icmp = icmp ne i9 %and, 0 ret i1 %icmp @@ -83,87 +33,75 @@ define <5 x i1> @select_and_icmpne_i1vec(<5 x i1> %x, <5 x i1> %y) { ; CHECK-LABEL: @select_and_icmpne_i1vec( -; CHECK-NEXT: [[S1:%.*]] = select <5 x i1> [[Y:%.*]], <5 x i32> , <5 x i32> -; CHECK-NEXT: [[S2:%.*]] = select <5 x i1> [[X:%.*]], <5 x i32> , <5 x i32> +; CHECK-NEXT: [[S1:%.*]] = select <5 x i1> [[X:%.*]], <5 x i32> , <5 x i32> +; CHECK-NEXT: [[S2:%.*]] = select <5 x i1> [[Y:%.*]], <5 x i32> , <5 x i32> ; CHECK-NEXT: [[AND:%.*]] = and <5 x i32> [[S2]], [[S1]] ; CHECK-NEXT: [[ICMP:%.*]] = icmp ne <5 x i32> [[AND]], zeroinitializer ; CHECK-NEXT: ret <5 x i1> [[ICMP]] ; - %s1 = select <5 x i1> %y, <5 x i32> , <5 x i32> - %s2 = select <5 x i1> %x, <5 x i32> , <5 x i32> + %s1 = select <5 x i1> %x, <5 x i32> , <5 x i32> + %s2 = select <5 x i1> %y, <5 x i32> , <5 x i32> %and = and <5 x i32> %s2, %s1 %icmp = icmp ne <5 x i32> %and, ret <5 x i1> %icmp } -define i1 @select_and_icmpne_i32_multiuse_select1(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i32_multiuse_select1( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i32 4, i32 1 -; CHECK-NEXT: call void @use32(i32 [[S1]]) -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i32 4, i32 1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[S2]], [[S1]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32 [[AND]], 0 +define i1 @select_and_icmpne_i8_negative_other_pred(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpne_i8_negative_other_pred( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 1, i8 8 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 1, i8 8 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i8 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i32 4, i32 1 - call void @use32(i32 %s1) ; extra use of first select - %s2 = select i1 %x, i32 4, i32 1 - %and = and i32 %s2, %s1 - %icmp = icmp ne i32 %and, 0 + %s1 = select i1 %x, i8 1, i8 8 + %s2 = select i1 %y, i8 1, i8 8 + %and = and i8 %s1, %s2 + %icmp = icmp ugt i8 %and, 0 ret i1 %icmp } -define i1 @select_and_icmpne_i16_multiuse_select2(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i16_multiuse_select2( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i16 4, i16 1 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i16 4, i16 1 -; CHECK-NEXT: call void @use16(i16 [[S2]]) -; CHECK-NEXT: [[AND:%.*]] = and i16 [[S2]], [[S1]] -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i16 [[AND]], 0 +define i1 @select_and_icmpne_i4_negative_select_arm_zero(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpne_i4_negative_select_arm_zero( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i4 2, i4 1 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i4 2, i4 1 +; CHECK-NEXT: [[AND:%.*]] = and i4 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i4 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i16 4, i16 1 - %s2 = select i1 %x, i16 4, i16 1 - call void @use16(i16 %s2) ; extra use of second select - %and = and i16 %s2, %s1 - %icmp = icmp ne i16 %and, 0 + %s1 = select i1 %x, i4 2, i4 1 + %s2 = select i1 %y, i4 2, i4 1 + %and = and i4 %s1, %s2 + %icmp = icmp ne i4 %and, 0 ret i1 %icmp } -define i1 @select_and_icmpne_i3_multiuse_and(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i3_multiuse_and( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i3 1, i3 2 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i3 1, i3 2 -; CHECK-NEXT: [[AND:%.*]] = and i3 [[S2]], [[S1]] -; CHECK-NEXT: call void @use3(i3 [[AND]]) -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i3 [[AND]], 0 +define i1 @select_and_icmpne_i12_negative_one_select_pair_matching1(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpne_i12_negative_one_select_pair_matching1( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i12 0, i12 4 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i12 2, i12 4 +; CHECK-NEXT: [[AND:%.*]] = and i12 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i12 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i3 1, i3 2 - %s2 = select i1 %x, i3 1, i3 2 - %and = and i3 %s2, %s1 - call void @use3(i3 %and) ; extra use of and - %icmp = icmp ne i3 %and, 0 + %s1 = select i1 %x, i12 1, i12 4 + %s2 = select i1 %y, i12 2, i12 4 + %and = and i12 %s1, %s2 + %icmp = icmp ne i12 %and, 0 ret i1 %icmp } -define i1 @select_and_icmpne_i7_multiuse_all(i1 %x, i1 %y) { -; CHECK-LABEL: @select_and_icmpne_i7_multiuse_all( -; CHECK-NEXT: [[S1:%.*]] = select i1 [[Y:%.*]], i7 1, i7 2 -; CHECK-NEXT: [[S2:%.*]] = select i1 [[X:%.*]], i7 1, i7 2 -; CHECK-NEXT: [[AND:%.*]] = and i7 [[S2]], [[S1]] -; CHECK-NEXT: call void @use7(i7 [[S1]]) -; CHECK-NEXT: call void @use7(i7 [[S2]]) -; CHECK-NEXT: call void @use7(i7 [[AND]]) -; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i7 [[AND]], 0 +define i1 @select_and_icmpne_i13_negative_one_select_pair_matching2(i1 %x, i1 %y) { +; CHECK-LABEL: @select_and_icmpne_i13_negative_one_select_pair_matching2( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i13 2, i13 0 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i13 2, i13 4 +; CHECK-NEXT: [[AND:%.*]] = and i13 [[S1]], [[S2]] +; CHECK-NEXT: [[ICMP:%.*]] = icmp ne i13 [[AND]], 0 ; CHECK-NEXT: ret i1 [[ICMP]] ; - %s1 = select i1 %y, i7 1, i7 2 - %s2 = select i1 %x, i7 1, i7 2 - %and = and i7 %s2, %s1 - call void @use7(i7 %s1) ; extra use of first select - call void @use7(i7 %s2) ; extra use of second select - call void @use7(i7 %and) ; extra use of and - %icmp = icmp ne i7 %and, 0 + %s1 = select i1 %x, i13 2, i13 8 + %s2 = select i1 %y, i13 2, i13 4 + %and = and i13 %s1, %s2 + %icmp = icmp ne i13 %and, 0 ret i1 %icmp }