Index: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2811,6 +2811,32 @@ // (A ? B : 0) ? 1 : (C ? B : 0) --> (A ? 1 : C) ? B : 0 if (B == D) return SelectInst::Create(Builder.CreateSelect(A, One, C), B, Zero); + } else if (FalseLogicAnd) { + // (C & B) ? 1 : (C ? D : 0) --> C ? (B ? 1 : D) : 0 + if (C == A) + return SelectInst::Create(C, Builder.CreateSelect(B, One, D), Zero); + // (A & C) ? 1 : (C ? D : 0) --> C ? (A ? 1 : D) : 0 + if (C == B) + return SelectInst::Create(C, Builder.CreateSelect(A, One, D), Zero); + // (D & B) ? 1 : (C ? D : 0) --> D ? (B ? 1 : C) : 0 + if (D == A) + return SelectInst::Create(D, Builder.CreateSelect(B, One, C), Zero); + // (A & D) ? 1 : (C ? D : 0) --> D ? (A ? 1 : C) : 0 + if (D == B) + return SelectInst::Create(D, Builder.CreateSelect(A, One, C), Zero); + } else if (!CondLogicAnd) { + // (A & B) ? 1 : (A & D) --> (B ? 1 : D) & A + if (A == C) + return BinaryOperator::CreateAnd(Builder.CreateSelect(B, One, D), A); + // (A & B) ? 1 : (C & A) --> (B ? 1 : C) & A + if (A == D) + return BinaryOperator::CreateAnd(Builder.CreateSelect(B, One, C), A); + // (A & B) ? 1 : (B & D) --> (A ? 1 : D) & B + if (B == C) + return BinaryOperator::CreateAnd(Builder.CreateSelect(A, One, D), B); + // (A & B) ? 1 : (C & B) --> (A ? 1 : C) & B + if (B == D) + return BinaryOperator::CreateAnd(Builder.CreateSelect(A, One, C), B); } } } @@ -2846,6 +2872,32 @@ // (A ? 1 : B) ? (C ? 1 : B) : 0 --> (A ? C : 0) ? 1 : B if (B == D) return SelectInst::Create(Builder.CreateSelect(A, C, Zero), One, B); + } else if (TrueLogicOr) { + // (C | B) ? (C ? 1 : D) : 0 --> C ? 1 : (B ? D : 0) + if (C == A) + return SelectInst::Create(C, One, Builder.CreateSelect(B, D, Zero)); + // (A | C) ? (C ? 1 : D) : 0 --> C ? 1 : (A ? D : 0) + if (C == B) + return SelectInst::Create(C, One, Builder.CreateSelect(A, D, Zero)); + // (D | B) ? (C ? 1 : D) : 0 --> D ? 1 : (B ? C : 0) + if (D == A) + return SelectInst::Create(D, One, Builder.CreateSelect(B, C, Zero)); + // (A | D) ? (C ? 1 : D) : 0 --> D ? 1 : (A ? C : 0) + if (D == B) + return SelectInst::Create(D, One, Builder.CreateSelect(A, C, Zero)); + } else if (!CondLogicOr) { + // (A | B) ? (A | D) : 0 --> (B ? D : 0) | A + if (A == C) + return BinaryOperator::CreateOr(Builder.CreateSelect(B, D, Zero), A); + // (A | B) ? (C | A) : 0 --> (B ? C : 0) | A + if (A == D) + return BinaryOperator::CreateOr(Builder.CreateSelect(B, C, Zero), A); + // (A | B) ? (B | D) : 0 --> (A ? D : 0) | B + if (B == C) + return BinaryOperator::CreateOr(Builder.CreateSelect(A, D, Zero), B); + // (A | B) ? (C | B) : 0 --> (A ? C : 0) | B + if (B == D) + return BinaryOperator::CreateOr(Builder.CreateSelect(A, C, Zero), B); } } } Index: llvm/test/Transforms/InstCombine/select-factorize.ll =================================================================== --- llvm/test/Transforms/InstCombine/select-factorize.ll +++ llvm/test/Transforms/InstCombine/select-factorize.ll @@ -169,8 +169,8 @@ define i1 @and_logic_and_logic_or_1(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_logic_and_logic_or_1( -; CHECK-NEXT: [[BC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[BC]], i1 false +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 false ; CHECK-NEXT: ret i1 [[OR]] ; %ac = and i1 %c, %a @@ -181,9 +181,8 @@ define i1 @and_logic_and_logic_or_2(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_logic_and_logic_or_2( -; CHECK-NEXT: [[AC:%.*]] = and i1 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = select i1 [[B:%.*]], i1 [[C]], i1 false -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AC]], i1 true, i1 [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 false ; CHECK-NEXT: ret i1 [[OR]] ; %ac = and i1 %c, %a @@ -194,8 +193,8 @@ define i1 @and_logic_and_logic_or_3(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_logic_and_logic_or_3( -; CHECK-NEXT: [[BC:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[BC]], i1 false +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 false ; CHECK-NEXT: ret i1 [[OR]] ; %ac = and i1 %a, %c @@ -204,6 +203,8 @@ ret i1 %or } +; negative test: and is not last select condition + define i1 @and_logic_and_logic_or_4(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_logic_and_logic_or_4( ; CHECK-NEXT: [[AC:%.*]] = and i1 [[A:%.*]], [[C:%.*]] @@ -219,8 +220,8 @@ define <3 x i1> @and_logic_and_logic_or_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @and_logic_and_logic_or_vector( -; CHECK-NEXT: [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> , <3 x i1> [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> , <3 x i1> [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[TMP1]], <3 x i1> zeroinitializer ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = and <3 x i1> %c, %a @@ -243,8 +244,8 @@ define <3 x i1> @and_logic_and_logic_or_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @and_logic_and_logic_or_vector_poison2( -; CHECK-NEXT: [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> , <3 x i1> [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[BC]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> , <3 x i1> [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> [[TMP1]], <3 x i1> zeroinitializer ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = and <3 x i1> %c, %a @@ -253,6 +254,8 @@ ret <3 x i1> %or } +; negative test: not one use for both op + define i1 @and_logic_and_logic_or_not_one_use(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_logic_and_logic_or_not_one_use( ; CHECK-NEXT: [[AC:%.*]] = and i1 [[A:%.*]], [[C:%.*]] @@ -272,9 +275,8 @@ define i1 @and_and_logic_or_1(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_and_logic_or_1( -; CHECK-NEXT: [[AC:%.*]] = and i1 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = and i1 [[C]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AC]], i1 true, i1 [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = and i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %ac = and i1 %c, %a @@ -285,9 +287,8 @@ define i1 @and_and_logic_or_2(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_and_logic_or_2( -; CHECK-NEXT: [[AC:%.*]] = and i1 [[A:%.*]], [[C:%.*]] -; CHECK-NEXT: [[BC:%.*]] = and i1 [[C]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[BC]], i1 true, i1 [[AC]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[A:%.*]] +; CHECK-NEXT: [[OR:%.*]] = and i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %ac = and i1 %a, %c @@ -298,9 +299,8 @@ define <3 x i1> @and_and_logic_or_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @and_and_logic_or_vector( -; CHECK-NEXT: [[AC:%.*]] = and <3 x i1> [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = and <3 x i1> [[C]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> , <3 x i1> [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> , <3 x i1> [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = and <3 x i1> [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = and <3 x i1> %c, %a @@ -311,9 +311,8 @@ define <3 x i1> @and_and_logic_or_vector_poison(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @and_and_logic_or_vector_poison( -; CHECK-NEXT: [[AC:%.*]] = and <3 x i1> [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = and <3 x i1> [[C]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> , <3 x i1> [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> , <3 x i1> [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = and <3 x i1> [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = and <3 x i1> %c, %a @@ -322,6 +321,8 @@ ret <3 x i1> %or } +; negative test : extra use for both cond/falseval + define i1 @and_and_logic_or_not_one_use(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @and_and_logic_or_not_one_use( ; CHECK-NEXT: [[AC:%.*]] = and i1 [[A:%.*]], [[C:%.*]] @@ -505,8 +506,8 @@ define i1 @or_logic_or_logic_and_1(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_logic_or_logic_and_1( -; CHECK-NEXT: [[BC:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false -; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[TMP1]] ; CHECK-NEXT: ret i1 [[OR]] ; %ac = or i1 %c, %a @@ -517,9 +518,8 @@ define i1 @or_logic_or_logic_and_2(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_logic_or_logic_and_2( -; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[C]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AC]], i1 [[BC]], i1 false +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 true, i1 [[TMP1]] ; CHECK-NEXT: ret i1 [[OR]] ; %ac = or i1 %c, %a @@ -528,6 +528,8 @@ ret i1 %or } +; negative test: or is not last select condition + define i1 @or_logic_or_logic_and_3(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_logic_or_logic_and_3( ; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]] @@ -541,6 +543,8 @@ ret i1 %or } +; negative test: or is not last select condition + define i1 @or_logic_or_logic_and_4(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_logic_or_logic_and_4( ; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]] @@ -556,8 +560,8 @@ define <3 x i1> @or_logic_or_logic_and_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @or_logic_or_logic_and_vector( -; CHECK-NEXT: [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> , <3 x i1> [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> , <3 x i1> [[TMP1]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = or <3 x i1> %c, %a @@ -580,8 +584,8 @@ define <3 x i1> @or_logic_or_logic_and_vector_poison2(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @or_logic_or_logic_and_vector_poison2( -; CHECK-NEXT: [[BC:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> , <3 x i1> [[BC]] +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[C:%.*]], <3 x i1> , <3 x i1> [[TMP1]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = or <3 x i1> %c, %a @@ -590,6 +594,8 @@ ret <3 x i1> %or } +; negative test: not one use for both op + define i1 @or_logic_or_logic_and_not_one_use(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_logic_or_logic_and_not_one_use( ; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]] @@ -609,9 +615,8 @@ define i1 @or_or_logic_and_1(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_or_logic_and_1( -; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = or i1 [[B:%.*]], [[C]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AC]], i1 [[BC]], i1 false +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[OR:%.*]] = or i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %ac = or i1 %c, %a @@ -622,9 +627,8 @@ define i1 @or_or_logic_and_2(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_or_logic_and_2( -; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = or i1 [[B:%.*]], [[C]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[BC]], i1 [[AC]], i1 false +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[B:%.*]], i1 [[A:%.*]], i1 false +; CHECK-NEXT: [[OR:%.*]] = or i1 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %ac = or i1 %c, %a @@ -635,9 +639,8 @@ define <3 x i1> @or_or_logic_and_vector(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @or_or_logic_and_vector( -; CHECK-NEXT: [[AC:%.*]] = or <3 x i1> [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = or <3 x i1> [[B:%.*]], [[C]] -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <3 x i1> [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = or <3 x i1> %c, %a @@ -648,9 +651,8 @@ define <3 x i1> @or_or_logic_and_vector_poison(<3 x i1> %c, <3 x i1> %a, <3 x i1> %b) { ; CHECK-LABEL: @or_or_logic_and_vector_poison( -; CHECK-NEXT: [[AC:%.*]] = or <3 x i1> [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[BC:%.*]] = or <3 x i1> [[B:%.*]], [[C]] -; CHECK-NEXT: [[OR:%.*]] = select <3 x i1> [[AC]], <3 x i1> [[BC]], <3 x i1> +; CHECK-NEXT: [[TMP1:%.*]] = select <3 x i1> [[A:%.*]], <3 x i1> [[B:%.*]], <3 x i1> zeroinitializer +; CHECK-NEXT: [[OR:%.*]] = or <3 x i1> [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret <3 x i1> [[OR]] ; %ac = or <3 x i1> %c, %a @@ -659,6 +661,8 @@ ret <3 x i1> %or } +; negative test : extra use for both cond/trueval + define i1 @or_or_logic_and_not_one_use(i1 %c, i1 %a, i1 %b) { ; CHECK-LABEL: @or_or_logic_and_not_one_use( ; CHECK-NEXT: [[AC:%.*]] = or i1 [[C:%.*]], [[A:%.*]]