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 @@ -3083,6 +3083,18 @@ TrueVal = Builder.CreateFreeze(TrueVal); return BinaryOperator::CreateAnd(FalseVal, Builder.CreateOr(C, TrueVal)); } + // select (a | ~c), a, b -> select a, true, (select c, b, false) + if (match(CondVal, m_c_Or(m_Specific(TrueVal), m_Not(m_Value(C)))) && + CondVal->hasOneUse()) { + Value *AndV = Builder.CreateSelect(C, FalseVal, Zero); + return SelectInst::Create(TrueVal, One, AndV); + } + // select (c & ~b), a, b -> select b, true, (select c, a, false) + if (match(CondVal, m_c_And(m_Value(C), m_Not(m_Specific(FalseVal)))) && + CondVal->hasOneUse()) { + Value *AndV = Builder.CreateSelect(C, TrueVal, Zero); + return SelectInst::Create(FalseVal, One, AndV); + } if (match(FalseVal, m_Zero()) || match(TrueVal, m_One())) { Use *Y = nullptr; diff --git a/llvm/test/Transforms/InstCombine/select-and-or.ll b/llvm/test/Transforms/InstCombine/select-and-or.ll --- a/llvm/test/Transforms/InstCombine/select-and-or.ll +++ b/llvm/test/Transforms/InstCombine/select-and-or.ll @@ -604,9 +604,8 @@ define i1 @or_and1(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @or_and1( -; CHECK-NEXT: [[NOTB:%.*]] = xor i1 [[B:%.*]], true -; CHECK-NEXT: [[COND:%.*]] = and i1 [[NOTB]], [[C:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %notb = xor i1 %b, true @@ -617,9 +616,8 @@ define i1 @or_and2(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @or_and2( -; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[COND:%.*]] = or i1 [[NOTC]], [[A:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %notc = xor i1 %c, true @@ -630,9 +628,8 @@ define i1 @or_and1_commuted(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @or_and1_commuted( -; CHECK-NEXT: [[NOTB:%.*]] = xor i1 [[B:%.*]], true -; CHECK-NEXT: [[COND:%.*]] = and i1 [[NOTB]], [[C:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A:%.*]], i1 [[B]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i1 true, i1 [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %notb = xor i1 %b, true @@ -643,9 +640,8 @@ define i1 @or_and2_commuted(i1 %a, i1 %b, i1 %c) { ; CHECK-LABEL: @or_and2_commuted( -; CHECK-NEXT: [[NOTC:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[COND:%.*]] = or i1 [[NOTC]], [[A:%.*]] -; CHECK-NEXT: [[R:%.*]] = select i1 [[COND]], i1 [[A]], i1 [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP1]] ; CHECK-NEXT: ret i1 [[R]] ; %notc = xor i1 %c, true @@ -687,9 +683,8 @@ define <2 x i1> @or_and1_vec(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @or_and1_vec( ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() -; CHECK-NEXT: [[NOTB:%.*]] = xor <2 x i1> [[B:%.*]], -; CHECK-NEXT: [[COND:%.*]] = and <2 x i1> [[C]], [[NOTB]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[A:%.*]], <2 x i1> [[B]] +; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> , <2 x i1> [[TMP1]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %c = call <2 x i1> @gen_v2i1() @@ -702,9 +697,8 @@ define <2 x i1> @or_and2_vec(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @or_and2_vec( ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() -; CHECK-NEXT: [[NOTC:%.*]] = xor <2 x i1> [[C]], -; CHECK-NEXT: [[COND:%.*]] = or <2 x i1> [[NOTC]], [[A:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[A]], <2 x i1> [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> , <2 x i1> [[TMP1]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %c = call <2 x i1> @gen_v2i1() @@ -717,9 +711,8 @@ define <2 x i1> @or_and1_vec_commuted(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @or_and1_vec_commuted( ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() -; CHECK-NEXT: [[NOTB:%.*]] = xor <2 x i1> [[B:%.*]], -; CHECK-NEXT: [[COND:%.*]] = and <2 x i1> [[C]], [[NOTB]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[A:%.*]], <2 x i1> [[B]] +; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i1> , <2 x i1> [[TMP1]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %c = call <2 x i1> @gen_v2i1() @@ -732,9 +725,8 @@ define <2 x i1> @or_and2_vec_commuted(<2 x i1> %a, <2 x i1> %b) { ; CHECK-LABEL: @or_and2_vec_commuted( ; CHECK-NEXT: [[C:%.*]] = call <2 x i1> @gen_v2i1() -; CHECK-NEXT: [[NOTC:%.*]] = xor <2 x i1> [[C]], -; CHECK-NEXT: [[COND:%.*]] = or <2 x i1> [[NOTC]], [[A:%.*]] -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[A]], <2 x i1> [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> [[C]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> , <2 x i1> [[TMP1]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %c = call <2 x i1> @gen_v2i1() @@ -773,9 +765,7 @@ define i1 @pr64558(i1 noundef %a, i1 noundef %b) { ; CHECK-LABEL: @pr64558( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[LNOT:%.*]] = xor i1 [[B:%.*]], true -; CHECK-NEXT: [[AND11:%.*]] = and i1 [[LNOT]], [[A:%.*]] -; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[AND11]], i1 [[A]], i1 [[B]] +; CHECK-NEXT: [[COND_V:%.*]] = or i1 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: ret i1 [[COND_V]] ; entry: