diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2999,6 +2999,14 @@ if (match(CondVal, m_Select(m_Value(A), m_Value(B), m_Zero())) && match(TrueVal, m_Specific(B)) && match(FalseVal, m_Zero())) return replaceOperand(SI, 0, A); + // select a, (select ~a, true, b), false -> select a, b, false + if (match(TrueVal, m_c_LogicalOr(m_Not(m_Specific(CondVal)), m_Value(B))) && + match(FalseVal, m_Zero())) + return replaceOperand(SI, 1, B); + // select a, true, (select ~a, b, false) -> select a, true, b + if (match(FalseVal, m_c_LogicalAnd(m_Not(m_Specific(CondVal)), m_Value(B))) && + match(TrueVal, m_One())) + return replaceOperand(SI, 2, B); // ~(A & B) & (A | B) --> A ^ B if (match(&SI, m_c_LogicalAnd(m_Not(m_LogicalAnd(m_Value(A), m_Value(B))), diff --git a/llvm/test/Transforms/InstCombine/logical-select.ll b/llvm/test/Transforms/InstCombine/logical-select.ll --- a/llvm/test/Transforms/InstCombine/logical-select.ll +++ b/llvm/test/Transforms/InstCombine/logical-select.ll @@ -1143,9 +1143,7 @@ ; A & (~A | B) --> A & B define i1 @test1_variant1(i1 %a, i1 %b) { ; CHECK-LABEL: @test1_variant1( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[OR:%.*]] = or i1 [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[A]], i1 [[OR]], i1 false +; CHECK-NEXT: [[AND:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %not = xor i1 %a, true @@ -1158,9 +1156,7 @@ ; A & (~A | B) --> A & B define <2 x i1> @test1_variant2(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @test1_variant2( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[A]], <2 x i1> [[OR]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[AND]] ; %not = xor <2 x i1> %a, @@ -1173,9 +1169,7 @@ ; A & (~A | B) --> A & B define i1 @test1_variant3(i1 %a, i1 %b) { ; CHECK-LABEL: @test1_variant3( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[OR:%.*]] = select i1 [[NOT]], i1 true, i1 [[B:%.*]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[A]], i1 [[OR]], i1 false +; CHECK-NEXT: [[AND:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %not = xor i1 %a, true @@ -1190,7 +1184,7 @@ ; CHECK-LABEL: @test1_variant4( ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], ; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[NOT]], <2 x i1> , <2 x i1> [[B:%.*]] -; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[A]], <2 x i1> [[OR]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[A]], <2 x i1> [[B]], <2 x i1> zeroinitializer ; CHECK-NEXT: call void @use2(<2 x i1> [[A]]) ; CHECK-NEXT: call void @use2(<2 x i1> [[B]]) ; CHECK-NEXT: call void @use2(<2 x i1> [[OR]]) @@ -1210,9 +1204,7 @@ define i1 @test1_variant5(i1 %a) { ; CHECK-LABEL: @test1_variant5( ; CHECK-NEXT: [[B:%.*]] = call i1 @gen() -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[OR:%.*]] = or i1 [[B]], [[NOT]] -; CHECK-NEXT: [[AND:%.*]] = select i1 [[A]], i1 [[OR]], i1 false +; CHECK-NEXT: [[AND:%.*]] = select i1 [[A:%.*]], i1 [[B]], i1 false ; CHECK-NEXT: ret i1 [[AND]] ; %b = call i1 @gen() @@ -1240,9 +1232,7 @@ ; A | (~A & B) --> A | B define i1 @test2_variant1(i1 %a, i1 %b) { ; CHECK-LABEL: @test2_variant1( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[AND:%.*]] = and i1 [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[A]], i1 true, i1 [[AND]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %not = xor i1 %a, true @@ -1255,9 +1245,7 @@ ; A | (~A & B) --> A | B define <2 x i1> @test2_variant2(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @test2_variant2( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[A]], <2 x i1> , <2 x i1> [[AND]] +; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> , <2 x i1> [[B:%.*]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %not = xor <2 x i1> %a, @@ -1270,9 +1258,7 @@ ; A | (~A & B) --> A | B define i1 @test2_variant3(i1 %a, i1 %b) { ; CHECK-LABEL: @test2_variant3( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOT]], i1 [[B:%.*]], i1 false -; CHECK-NEXT: [[OR:%.*]] = select i1 [[A]], i1 true, i1 [[AND]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %not = xor i1 %a, true @@ -1287,7 +1273,7 @@ ; CHECK-LABEL: @test2_variant4( ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[A:%.*]], ; CHECK-NEXT: [[AND:%.*]] = select <2 x i1> [[NOT]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[A]], <2 x i1> , <2 x i1> [[AND]] +; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[A]], <2 x i1> , <2 x i1> [[B]] ; CHECK-NEXT: call void @use2(<2 x i1> [[A]]) ; CHECK-NEXT: call void @use2(<2 x i1> [[B]]) ; CHECK-NEXT: call void @use2(<2 x i1> [[AND]]) @@ -1307,9 +1293,7 @@ define i1 @test2_variant5(i1 %a) { ; CHECK-LABEL: @test2_variant5( ; CHECK-NEXT: [[B:%.*]] = call i1 @gen() -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[AND:%.*]] = and i1 [[B]], [[NOT]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[A]], i1 true, i1 [[AND]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B]] ; CHECK-NEXT: ret i1 [[OR]] ; %b = call i1 @gen()