From d7fecf26f42b47f5c2e7e64a2975ec0dcccd7248 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 21 Oct 2022 11:15:11 -0400 Subject: [PATCH] [InstCombine] allow some commutative matches for logical-and to select fold This is obviously correct for real logic instructions, and it also works for the poison-safe variants that use selects: https://alive2.llvm.org/ce/z/wyHiwX This is motivated by the lack of 'xor' folding seen in issue #58313. This more general fold should help reduce some of those patterns, but I'm not sure if this specific case does anything for that particular example. --- .../Transforms/InstCombine/InstCombineSelect.cpp | 4 +-- .../InstCombine/select-safe-transforms.ll | 40 +++++----------------- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 0f56483..6bed09d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2852,12 +2852,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { // (C && A) || (!C && B) --> sel C, A, B if (match(FalseVal, m_LogicalAnd(m_Not(m_Value(C)), m_Value(B))) && - match(CondVal, m_LogicalAnd(m_Specific(C), m_Value(A)))) + match(CondVal, m_c_LogicalAnd(m_Specific(C), m_Value(A)))) return SelectInst::Create(C, A, B); // (!C && A) || (C && B) --> sel C, B, A if (match(CondVal, m_LogicalAnd(m_Not(m_Value(C)), m_Value(A))) && - match(FalseVal, m_LogicalAnd(m_Specific(C), m_Value(B)))) + match(FalseVal, m_c_LogicalAnd(m_Specific(C), m_Value(B)))) return SelectInst::Create(C, B, A); } } diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll index 59298e0..8526758 100644 --- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll +++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll @@ -271,10 +271,7 @@ define i1 @bools_logical_commute1_and1_and2(i1 %b, i1 %c) { define <2 x i1> @bools_logical_commute2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) { ; CHECK-LABEL: @bools_logical_commute2( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[C:%.*]], -; CHECK-NEXT: [[AND1:%.*]] = select <2 x i1> [[NOT]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer -; CHECK-NEXT: [[AND2:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[C]], <2 x i1> zeroinitializer -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[AND1]], <2 x i1> , <2 x i1> [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %not = xor <2 x i1> %c, @@ -286,10 +283,7 @@ define <2 x i1> @bools_logical_commute2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) { define <2 x i1> @bools_logical_commute2_and1(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) { ; CHECK-LABEL: @bools_logical_commute2_and1( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[C:%.*]], -; CHECK-NEXT: [[AND1:%.*]] = and <2 x i1> [[NOT]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> [[C]], <2 x i1> zeroinitializer -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[AND1]], <2 x i1> , <2 x i1> [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %not = xor <2 x i1> %c, @@ -301,10 +295,7 @@ define <2 x i1> @bools_logical_commute2_and1(<2 x i1> %a, <2 x i1> %b, <2 x i1> define <2 x i1> @bools_logical_commute2_and2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) { ; CHECK-LABEL: @bools_logical_commute2_and2( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[C:%.*]], -; CHECK-NEXT: [[AND1:%.*]] = select <2 x i1> [[NOT]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer -; CHECK-NEXT: [[AND2:%.*]] = and <2 x i1> [[B:%.*]], [[C]] -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[AND1]], <2 x i1> , <2 x i1> [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %not = xor <2 x i1> %c, @@ -316,10 +307,7 @@ define <2 x i1> @bools_logical_commute2_and2(<2 x i1> %a, <2 x i1> %b, <2 x i1> define <2 x i1> @bools_logical_commute2_and1_and2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) { ; CHECK-LABEL: @bools_logical_commute2_and1_and2( -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[C:%.*]], -; CHECK-NEXT: [[AND1:%.*]] = and <2 x i1> [[NOT]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and <2 x i1> [[B:%.*]], [[C]] -; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[AND1]], <2 x i1> , <2 x i1> [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]] ; CHECK-NEXT: ret <2 x i1> [[OR]] ; %not = xor <2 x i1> %c, @@ -443,10 +431,7 @@ define i1 @bools2_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) { define i1 @bools2_logical_commute1(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @bools2_logical_commute1( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 [[C]], i1 false -; CHECK-NEXT: [[AND2:%.*]] = select i1 [[NOT]], i1 [[B:%.*]], i1 false -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AND1]], i1 true, i1 [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %not = xor i1 %c, -1 @@ -458,10 +443,7 @@ define i1 @bools2_logical_commute1(i1 %a, i1 %b, i1 %c) { define i1 @bools2_logical_commute1_and1(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @bools2_logical_commute1_and1( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = select i1 [[NOT]], i1 [[B:%.*]], i1 false -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AND1]], i1 true, i1 [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %not = xor i1 %c, -1 @@ -473,10 +455,7 @@ define i1 @bools2_logical_commute1_and1(i1 %a, i1 %b, i1 %c) { define i1 @bools2_logical_commute1_and2(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @bools2_logical_commute1_and2( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 [[C]], i1 false -; CHECK-NEXT: [[AND2:%.*]] = and i1 [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AND1]], i1 true, i1 [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %not = xor i1 %c, -1 @@ -488,10 +467,7 @@ define i1 @bools2_logical_commute1_and2(i1 %a, i1 %b, i1 %c) { define i1 @bools2_logical_commute1_and1_and2(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @bools2_logical_commute1_and1_and2( -; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[AND1:%.*]] = and i1 [[A:%.*]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i1 [[NOT]], [[B:%.*]] -; CHECK-NEXT: [[OR:%.*]] = select i1 [[AND1]], i1 true, i1 [[AND2]] +; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[OR]] ; %not = xor i1 %c, -1 -- 2.7.4