diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -260,6 +260,8 @@ CmpComponents(CmpType *Cmp) : Pred_(Cmp->getPredicate()), Op0_(Cmp->getOperand(0)), Op1_(Cmp->getOperand(1)), OrigCmp_(Cmp) {} + CmpComponents(PredType Pred, Value *Op0, Value *Op1, CmpType *Cmp) + : Pred_(Pred), Op0_(Op0), Op1_(Op1), OrigCmp_(Cmp) {} }; using FCmpComponents = CmpComponents; 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 @@ -2937,6 +2937,24 @@ !IsAndVariant ? SelInner : InnerSel.FalseVal); } +static bool canFreelyInvert(InstCombiner &IC, Value *Op, + Instruction *IgnoredUser = nullptr) { + auto *I = dyn_cast(Op); + return I && IC.isFreeToInvert(I, /*WillInvertAllUses=*/true) && + InstCombiner::canFreelyInvertAllUsersOf(I, IgnoredUser); +} + +static Value *freelyInvert(InstCombinerImpl &IC, Value *Op, + Instruction *IgnoredUser) { + auto *I = cast(Op); + IC.Builder.SetInsertPoint(&*I->getInsertionPointAfterDef()); + Value *NotOp = IC.Builder.CreateNot(Op, Op->getName() + ".not"); + Op->replaceUsesWithIf(NotOp, + [NotOp](Use &U) { return U.getUser() != NotOp; }); + IC.freelyInvertAllUsersOf(NotOp, IgnoredUser); + return NotOp; +} + Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) { Value *CondVal = SI.getCondition(); Value *TrueVal = SI.getTrueValue(); @@ -2954,6 +2972,41 @@ auto *Zero = ConstantInt::getFalse(SelType); Value *A, *B, *C, *D; + // Some very basic simplifcations to get out of the way first. + if (match(TrueVal, m_Zero()) && match(FalseVal, m_One())) + return BinaryOperator::CreateNot(CondVal); + + if (TrueVal == CondVal) + return SelectInst::Create(CondVal, One, FalseVal); + + if (match(TrueVal, m_Not(m_Specific(CondVal)))) + return SelectInst::Create(CondVal, Zero, FalseVal); + + if (FalseVal == CondVal) + return SelectInst::Create(CondVal, TrueVal, Zero); + + if (match(FalseVal, m_Not(m_Specific(CondVal)))) + return SelectInst::Create(CondVal, TrueVal, One); + + // Try our best to canonicalize to `select c, true, false` starting from + // `select c, A, true` or `select c, false, B`. + // First try to just invert the condition and swap trueval/falseval. + // If we can't invert the condition try to invert the select as a whole. + if (match(TrueVal, m_Specific(Zero)) || match(FalseVal, m_Specific(One))) { + if (canFreelyInvert(*this, CondVal, &SI)) { + Value *NotCond = freelyInvert(*this, CondVal, &SI); + return SelectInst::Create(NotCond, FalseVal, TrueVal); + } + if (canFreelyInvert(*this, &SI)) { + Value *NotSelect = Builder.CreateSelect( + CondVal, Builder.CreateNot(TrueVal), Builder.CreateNot(FalseVal)); + Instruction *R = replaceInstUsesWith(SI, NotSelect); + freelyInvertAllUsersOf(NotSelect); + return R; + } + } + + // Folding select to and/or i1 isn't poison safe in general. impliesPoison // checks whether folding it does not convert a well-defined value into // poison. @@ -2998,6 +3051,28 @@ } } + if (match(TrueVal, m_Zero())) { + if (auto *LHS = dyn_cast(CondVal)) { + if (auto *RHS = dyn_cast(FalseVal)) { + InstCombinerImpl::FCmpComponents LHSComponents{ + LHS->getInversePredicate(), LHS->getOperand(0), LHS->getOperand(1), + LHS}; + if (Value *V = foldLogicOfFCmps(LHSComponents, RHS, /*IsAnd*/ true, + /*IsSelectLogical*/ true)) + return replaceInstUsesWith(SI, V); + } + } + + // !(A || B) && (C || B) --> !(A || B) && C + if (match(CondVal, m_LogicalOr(m_Value(A), m_Value(B))) && + match(FalseVal, m_LogicalOr(m_Value(C), m_Value(D)))) { + if (A == C || B == C) + return SelectInst::Create(CondVal, Zero, D); + if (A == D || B == D) + return SelectInst::Create(CondVal, Zero, C); + } + } + if (match(FalseVal, m_Zero())) { if (impliesPoison(TrueVal, CondVal)) { // Change: A = select B, C, false --> A = and B, C @@ -3039,17 +3114,25 @@ } } - // We match the "full" 0 or 1 constant here to avoid a potential infinite - // loop with vectors that may have undefined/poison elements. - // select a, false, b -> select !a, b, false - if (match(TrueVal, m_Specific(Zero))) { - Value *NotCond = Builder.CreateNot(CondVal, "not." + CondVal->getName()); - return SelectInst::Create(NotCond, FalseVal, Zero); - } - // select a, b, true -> select !a, true, b - if (match(FalseVal, m_Specific(One))) { - Value *NotCond = Builder.CreateNot(CondVal, "not." + CondVal->getName()); - return SelectInst::Create(NotCond, One, TrueVal); + if (match(FalseVal, m_One())) { + if (auto *LHS = dyn_cast(CondVal)) { + if (auto *RHS = dyn_cast(TrueVal)) { + InstCombinerImpl::FCmpComponents LHSComponents{ + LHS->getInversePredicate(), LHS->getOperand(0), LHS->getOperand(1), + LHS}; + if (Value *V = foldLogicOfFCmps(LHSComponents, RHS, /*IsAnd*/ false, + /*IsSelectLogical*/ true)) + return replaceInstUsesWith(SI, V); + } + } + // !(A && B) || (C && B) --> !(A && B) || C + if (match(CondVal, m_LogicalAnd(m_Value(A), m_Value(B))) && + match(TrueVal, m_LogicalAnd(m_Value(C), m_Value(D)))) { + if (A == C || B == C) + return SelectInst::Create(CondVal, D, One); + if (A == D || B == D) + return SelectInst::Create(CondVal, C, One); + } } // DeMorgan in select form: !a && !b --> !(a || b) @@ -3070,10 +3153,22 @@ if (match(CondVal, m_Select(m_Value(A), m_One(), m_Value(B))) && match(TrueVal, m_One()) && match(FalseVal, m_Specific(B))) return replaceOperand(SI, 0, A); + + // select (select a, b, true), b, true -> select a, true, b + if (match(CondVal, m_Select(m_Value(A), m_Value(B), m_One())) && + match(FalseVal, m_One()) && match(TrueVal, m_Specific(B))) + return SelectInst::Create(A, One, B); + // select (select a, b, false), b, false -> select a, b, false 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 (select a, false, b), false, b -> select a, b, false + if (match(CondVal, m_Select(m_Value(A), m_Zero(), m_Value(B))) && + match(TrueVal, m_Zero()) && match(FalseVal, m_Specific(B))) + return SelectInst::Create(A, B, Zero); + // 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())) @@ -3114,6 +3209,7 @@ return SelectInst::Create(FalseVal, One, AndV); } + if (match(FalseVal, m_Zero()) || match(TrueVal, m_One())) { Use *Y = nullptr; bool IsAnd = match(FalseVal, m_Zero()) ? true : false; @@ -3137,6 +3233,27 @@ return replaceInstUsesWith(SI, V); } + if (match(FalseVal, m_One()) || match(TrueVal, m_Zero())) { + bool IsAnd = match(TrueVal, m_Zero()); + Value *Op1 = IsAnd ? FalseVal : TrueVal; + if (auto *Op1SI = dyn_cast(Op1)) + if (auto *I = foldAndOrOfSelectUsingImpliedCond(CondVal, *Op1SI, + /* IsAnd */ IsAnd, + /*NotSICond*/ true)) + return I; + + if (auto *ICmp0 = dyn_cast(CondVal)) { + if (auto *ICmp1 = dyn_cast(Op1)) { + InstCombinerImpl::ICmpComponents ICmp0Components{ + ICmp0->getInversePredicate(), ICmp0->getOperand(0), + ICmp0->getOperand(1), ICmp0}; + if (auto *V = foldAndOrOfICmps(ICmp0Components, ICmp1, SI, IsAnd, + /* IsLogical */ true)) + return replaceInstUsesWith(SI, V); + } + } + } + // select (a || b), c, false -> select a, c, false // select c, (a || b), false -> select c, a, false // if c implies that b is false. diff --git a/llvm/test/Transforms/InstCombine/branch.ll b/llvm/test/Transforms/InstCombine/branch.ll --- a/llvm/test/Transforms/InstCombine/branch.ll +++ b/llvm/test/Transforms/InstCombine/branch.ll @@ -145,8 +145,7 @@ define i32 @logical_and_or(i1 %x, i1 %y) { ; CHECK-LABEL: @logical_and_or( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: [[AND:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 true ; CHECK-NEXT: br i1 [[AND]], label [[F:%.*]], label [[T:%.*]] ; CHECK: t: ; CHECK-NEXT: ret i32 42 diff --git a/llvm/test/Transforms/InstCombine/icmp-select.ll b/llvm/test/Transforms/InstCombine/icmp-select.ll --- a/llvm/test/Transforms/InstCombine/icmp-select.ll +++ b/llvm/test/Transforms/InstCombine/icmp-select.ll @@ -50,9 +50,8 @@ ; CHECK-LABEL: @icmp_select_var_select( ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 ; CHECK-NEXT: [[CMP212:%.*]] = icmp eq i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[CMP1]], i1 true, i1 [[NOT_C]] -; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[CMP212]] +; CHECK-NEXT: [[CMP21:%.*]] = select i1 [[C:%.*]], i1 [[CMP212]], i1 true +; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] ; CHECK-NEXT: ret i1 [[CMP2]] ; %z = select i1 %c, i8 %x, i8 %y @@ -207,8 +206,7 @@ ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 ; CHECK-NEXT: call void @use.i1(i1 [[CMP1]]) ; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]] -; CHECK-NEXT: [[NOT_CMP1:%.*]] = xor i1 [[CMP1]], true -; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[NOT_CMP1]], i1 true, i1 [[CMP21]] +; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 true ; CHECK-NEXT: ret i1 [[CMP2]] ; %cmp1 = icmp ne i8 %x, 0 @@ -377,8 +375,8 @@ define i1 @select_constants_and_icmp_eq0_zero_fval(i1 %x, i1 %y) { ; CHECK-LABEL: @select_constants_and_icmp_eq0_zero_fval( ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false -; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[TMP1]], true -; CHECK-NEXT: ret i1 [[NOT_]] +; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[TMP1]], true +; CHECK-NEXT: ret i1 [[CMP]] ; %s1 = select i1 %x, i8 12, i8 0 %s2 = select i1 %y, i8 12, i8 0 @@ -547,8 +545,8 @@ define i1 @select_constants_and_icmp_ne0_zero_tval(i1 %x, i1 %y) { ; CHECK-LABEL: @select_constants_and_icmp_ne0_zero_tval( ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] -; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[TMP1]], true -; CHECK-NEXT: ret i1 [[NOT_]] +; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[TMP1]], true +; CHECK-NEXT: ret i1 [[CMP]] ; %s1 = select i1 %x, i8 0, i8 12 %s2 = select i1 %y, i8 0, i8 12 diff --git a/llvm/test/Transforms/InstCombine/icmp-with-selects.ll b/llvm/test/Transforms/InstCombine/icmp-with-selects.ll --- a/llvm/test/Transforms/InstCombine/icmp-with-selects.ll +++ b/llvm/test/Transforms/InstCombine/icmp-with-selects.ll @@ -20,8 +20,8 @@ ; CHECK-LABEL: define i1 @both_sides_fold_eq ; CHECK-SAME: (i32 [[PARAM:%.*]], i1 [[COND:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND]], true -; CHECK-NEXT: ret i1 [[NOT_COND]] +; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[COND]], true +; CHECK-NEXT: ret i1 [[CMP]] ; entry: %cond1 = select i1 %cond, i32 1, i32 %param @@ -50,8 +50,7 @@ ; CHECK-SAME: (i32 [[VAL1:%.*]], i32 [[VAL2:%.*]], i32 [[PARAM:%.*]], i1 [[COND:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[VAL2]], [[VAL1]] -; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND]], true -; CHECK-NEXT: [[CMP:%.*]] = select i1 [[NOT_COND]], i1 [[TMP0]], i1 false +; CHECK-NEXT: [[CMP:%.*]] = select i1 [[COND]], i1 false, i1 [[TMP0]] ; CHECK-NEXT: ret i1 [[CMP]] ; entry: @@ -66,8 +65,7 @@ ; CHECK-SAME: (i32 [[VAL1:%.*]], i32 [[VAL2:%.*]], i32 [[PARAM:%.*]], i1 [[COND:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[VAL2]], [[VAL1]] -; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND]], true -; CHECK-NEXT: [[CMP:%.*]] = select i1 [[NOT_COND]], i1 true, i1 [[TMP0]] +; CHECK-NEXT: [[CMP:%.*]] = select i1 [[COND]], i1 [[TMP0]], i1 true ; CHECK-NEXT: ret i1 [[CMP]] ; entry: diff --git a/llvm/test/Transforms/InstCombine/nested-select.ll b/llvm/test/Transforms/InstCombine/nested-select.ll --- a/llvm/test/Transforms/InstCombine/nested-select.ll +++ b/llvm/test/Transforms/InstCombine/nested-select.ll @@ -263,8 +263,7 @@ ; In %outer.sel, %outer.cond is inverted define i1 @andcond.001.inv.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.trueval) { ; CHECK-LABEL: @andcond.001.inv.outer.cond( -; CHECK-NEXT: [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true -; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 false, i1 [[INNER_SEL_TRUEVAL:%.*]] ; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL]], i1 [[INNER_SEL_FALSEVAL:%.*]] ; CHECK-NEXT: ret i1 [[OUTER_SEL]] ; @@ -276,8 +275,7 @@ } define i1 @orcond.001.inv.outer.cond(i1 %inner.cond, i1 %alt.cond, i1 %inner.sel.trueval, i1 %inner.sel.falseval, i1 %outer.sel.falseval) { ; CHECK-LABEL: @orcond.001.inv.outer.cond( -; CHECK-NEXT: [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true -; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]] +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 true ; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[INNER_COND:%.*]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 [[INNER_SEL]] ; CHECK-NEXT: ret i1 [[OUTER_SEL]] ; @@ -347,10 +345,8 @@ ; CHECK-NEXT: [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[NOT_INNER_COND]], i1 true, i1 [[INNER_SEL_FALSEVAL:%.*]] ; CHECK-NEXT: call void @use.i1(i1 [[TMP1]]) -; CHECK-NEXT: [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true -; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 [[INNER_SEL_FALSEVAL]], i1 false -; CHECK-NEXT: [[NOT_INNER_COND1:%.*]] = xor i1 [[INNER_COND]], true -; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND1]], i1 true, i1 [[INNER_SEL]] +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 false, i1 [[INNER_SEL_FALSEVAL]] +; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i1 [[INNER_SEL]], i1 true ; CHECK-NEXT: ret i1 [[OUTER_SEL]] ; %outer.cond = select i1 %inner.cond, i1 %alt.cond, i1 false ; and %inner.cond, %alt.cond @@ -366,10 +362,8 @@ ; CHECK-NEXT: [[NOT_INNER_COND:%.*]] = xor i1 [[INNER_COND:%.*]], true ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[NOT_INNER_COND]], i1 [[INNER_SEL_TRUEVAL:%.*]], i1 false ; CHECK-NEXT: call void @use.i1(i1 [[TMP1]]) -; CHECK-NEXT: [[NOT_ALT_COND:%.*]] = xor i1 [[ALT_COND:%.*]], true -; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[NOT_ALT_COND]], i1 true, i1 [[INNER_SEL_TRUEVAL]] -; CHECK-NEXT: [[NOT_INNER_COND1:%.*]] = xor i1 [[INNER_COND]], true -; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND1]], i1 [[INNER_SEL]], i1 false +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[ALT_COND:%.*]], i1 [[INNER_SEL_TRUEVAL]], i1 true +; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[INNER_COND]], i1 false, i1 [[INNER_SEL]] ; CHECK-NEXT: ret i1 [[OUTER_SEL]] ; %outer.cond = select i1 %inner.cond, i1 true, i1 %alt.cond ; or %inner.cond, %alt.cond @@ -460,9 +454,8 @@ ; CHECK-NEXT: [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND]], true ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 [[INNER_SEL_FALSEVAL:%.*]], i1 false ; CHECK-NEXT: call void @use.i1(i1 [[TMP1]]) -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[INNER_COND]], i1 true, i1 [[ALT_COND]] -; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true -; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[TMP3]], i1 [[INNER_SEL_FALSEVAL]], i1 false +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[ALT_COND]], i1 false, i1 [[INNER_SEL_FALSEVAL]] +; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 [[INNER_SEL]], i1 false ; CHECK-NEXT: ret i1 [[OUTER_SEL]] ; %not.inner.cond.0 = xor i1 %inner.cond, -1 @@ -483,9 +476,8 @@ ; CHECK-NEXT: [[NOT_INNER_COND_1:%.*]] = xor i1 [[INNER_COND]], true ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[NOT_INNER_COND_1]], i1 true, i1 [[INNER_SEL_TRUEVAL:%.*]] ; CHECK-NEXT: call void @use.i1(i1 [[TMP1]]) -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[INNER_COND]], i1 [[ALT_COND]], i1 false -; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true -; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[TMP3]], i1 true, i1 [[INNER_SEL_TRUEVAL]] +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[ALT_COND]], i1 [[INNER_SEL_TRUEVAL]], i1 true +; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[NOT_INNER_COND_0]], i1 true, i1 [[INNER_SEL]] ; CHECK-NEXT: ret i1 [[OUTER_SEL]] ; %not.inner.cond.0 = xor i1 %inner.cond, -1 diff --git a/llvm/test/Transforms/InstCombine/not.ll b/llvm/test/Transforms/InstCombine/not.ll --- a/llvm/test/Transforms/InstCombine/not.ll +++ b/llvm/test/Transforms/InstCombine/not.ll @@ -481,8 +481,8 @@ define i1 @not_select_bool_const1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_select_bool_const1( -; CHECK-NEXT: [[Y_NOT:%.*]] = xor i1 [[Y:%.*]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[Y_NOT]], i1 false +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 true +; CHECK-NEXT: [[R:%.*]] = xor i1 [[SEL]], true ; CHECK-NEXT: ret i1 [[R]] ; %sel = select i1 %x, i1 %y, i1 true @@ -514,8 +514,8 @@ define i1 @not_select_bool_const4(i1 %x, i1 %y) { ; CHECK-LABEL: @not_select_bool_const4( -; CHECK-NEXT: [[Y_NOT:%.*]] = xor i1 [[Y:%.*]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y_NOT]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[X:%.*]], i1 false, i1 [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = xor i1 [[SEL]], true ; CHECK-NEXT: ret i1 [[R]] ; %sel = select i1 %x, i1 false, i1 %y @@ -537,8 +537,7 @@ define i1 @not_logicalAnd_not_op1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_logicalAnd_not_op1( -; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: [[NOTAND:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]] +; CHECK-NEXT: [[NOTAND:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 true ; CHECK-NEXT: ret i1 [[NOTAND]] ; %noty = xor i1 %y, true @@ -593,8 +592,7 @@ define i1 @not_logicalOr_not_op1(i1 %x, i1 %y) { ; CHECK-LABEL: @not_logicalOr_not_op1( -; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: [[NOTOR:%.*]] = select i1 [[NOT_X]], i1 [[Y:%.*]], i1 false +; CHECK-NEXT: [[NOTOR:%.*]] = select i1 [[X:%.*]], i1 false, i1 [[Y:%.*]] ; CHECK-NEXT: ret i1 [[NOTOR]] ; %noty = xor i1 %y, true 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 @@ -27,8 +27,7 @@ ; Canonicalize to logical and form, even if that requires adding a "not". define i1 @logical_and_not(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_and_not( -; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 false, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 false, i1 %b @@ -38,8 +37,7 @@ ; Canonicalize to logical or form, even if that requires adding a "not". define i1 @logical_or_not(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_or_not( -; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 true ; CHECK-NEXT: ret i1 [[RES]] ; %res = select i1 %a, i1 %b, i1 true @@ -70,8 +68,7 @@ define i1 @logical_and_not_cond_reuse(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_and_not_cond_reuse( -; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 true ; CHECK-NEXT: ret i1 [[RES]] ; %a.not = xor i1 %a, true @@ -81,8 +78,7 @@ define i1 @logical_or_not_cond_reuse(i1 %a, i1 %b) { ; CHECK-LABEL: @logical_or_not_cond_reuse( -; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 false, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[RES]] ; %a.not = xor i1 %a, true diff --git a/llvm/test/Transforms/InstCombine/select-bitext.ll b/llvm/test/Transforms/InstCombine/select-bitext.ll --- a/llvm/test/Transforms/InstCombine/select-bitext.ll +++ b/llvm/test/Transforms/InstCombine/select-bitext.ll @@ -341,8 +341,7 @@ define i32 @test_sext3(i1 %cca, i1 %ccb) { ; CHECK-LABEL: @test_sext3( -; CHECK-NEXT: [[NOT_CCB:%.*]] = xor i1 [[CCB:%.*]], true -; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[NOT_CCB]], i1 [[CCA:%.*]], i1 false +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[CCB:%.*]], i1 false, i1 [[CCA:%.*]] ; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; @@ -353,8 +352,7 @@ define i32 @test_sext4(i1 %cca, i1 %ccb) { ; CHECK-LABEL: @test_sext4( -; CHECK-NEXT: [[NOT_CCB:%.*]] = xor i1 [[CCB:%.*]], true -; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[NOT_CCB]], i1 true, i1 [[CCA:%.*]] +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[CCB:%.*]], i1 [[CCA:%.*]], i1 true ; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; @@ -387,8 +385,7 @@ define i32 @test_zext3(i1 %cca, i1 %ccb) { ; CHECK-LABEL: @test_zext3( -; CHECK-NEXT: [[NOT_CCB:%.*]] = xor i1 [[CCB:%.*]], true -; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[NOT_CCB]], i1 [[CCA:%.*]], i1 false +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[CCB:%.*]], i1 false, i1 [[CCA:%.*]] ; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; @@ -399,8 +396,7 @@ define i32 @test_zext4(i1 %cca, i1 %ccb) { ; CHECK-LABEL: @test_zext4( -; CHECK-NEXT: [[NOT_CCB:%.*]] = xor i1 [[CCB:%.*]], true -; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[NOT_CCB]], i1 true, i1 [[CCA:%.*]] +; CHECK-NEXT: [[NARROW:%.*]] = select i1 [[CCB:%.*]], i1 [[CCA:%.*]], i1 true ; CHECK-NEXT: [[R:%.*]] = zext i1 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll --- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll +++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll @@ -58,8 +58,7 @@ define i1 @xor_and(i1 %c, i32 %X, i32 %Y) { ; CHECK-LABEL: @xor_and( ; CHECK-NEXT: [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[COMP]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i1 [[COMP]], i1 true ; CHECK-NEXT: ret i1 [[SEL]] ; %comp = icmp ult i32 %X, %Y @@ -97,8 +96,7 @@ define i1 @xor_or(i1 %c, i32 %X, i32 %Y) { ; CHECK-LABEL: @xor_or( ; CHECK-NEXT: [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[NOT_C]], i1 [[COMP]], i1 false +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i1 false, i1 [[COMP]] ; CHECK-NEXT: ret i1 [[SEL]] ; %comp = icmp ult i32 %X, %Y diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -7,8 +7,8 @@ define i1 @test5(i1 %C) { ; CHECK-LABEL: @test5( -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: ret i1 [[NOT_C]] +; CHECK-NEXT: [[V:%.*]] = xor i1 [[C:%.*]], true +; CHECK-NEXT: ret i1 [[V]] ; %V = select i1 %C, i1 false, i1 true ret i1 %V @@ -79,8 +79,7 @@ define i1 @test9(i1 %C, i1 %X) { ; CHECK-LABEL: @test9( -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_C]], i1 [[X:%.*]], i1 false +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 false, i1 [[X:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %R = select i1 %C, i1 false, i1 %X @@ -89,8 +88,7 @@ define <2 x i1> @test9vec(<2 x i1> %C, <2 x i1> %X) { ; CHECK-LABEL: @test9vec( -; CHECK-NEXT: [[NOT_C:%.*]] = xor <2 x i1> [[C:%.*]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT_C]], <2 x i1> [[X:%.*]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> zeroinitializer, <2 x i1> [[X:%.*]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %R = select <2 x i1> %C, <2 x i1> , <2 x i1> %X @@ -99,8 +97,7 @@ define @test9vvec( %C, %X) { ; CHECK-LABEL: @test9vvec( -; CHECK-NEXT: [[NOT_C:%.*]] = xor [[C:%.*]], shufflevector ( insertelement ( poison, i1 true, i64 0), poison, zeroinitializer) -; CHECK-NEXT: [[R:%.*]] = select [[NOT_C]], [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = select [[C:%.*]], zeroinitializer, [[X:%.*]] ; CHECK-NEXT: ret [[R]] ; %R = select %C, zeroinitializer, %X @@ -109,8 +106,7 @@ define i1 @test10(i1 %C, i1 %X) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[X:%.*]], i1 true ; CHECK-NEXT: ret i1 [[R]] ; %R = select i1 %C, i1 %X, i1 true @@ -119,8 +115,7 @@ define <2 x i1> @test10vec(<2 x i1> %C, <2 x i1> %X) { ; CHECK-LABEL: @test10vec( -; CHECK-NEXT: [[NOT_C:%.*]] = xor <2 x i1> [[C:%.*]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT_C]], <2 x i1> , <2 x i1> [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[X:%.*]], <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[R]] ; %R = select <2 x i1> %C, <2 x i1> %X, <2 x i1> @@ -165,8 +160,7 @@ define i1 @test62(i1 %A, i1 %B) { ; CHECK-LABEL: @test62( -; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[C:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false +; CHECK-NEXT: [[C:%.*]] = select i1 [[A:%.*]], i1 false, i1 [[B:%.*]] ; CHECK-NEXT: ret i1 [[C]] ; %not = xor i1 %A, true @@ -176,8 +170,7 @@ define <2 x i1> @test62vec(<2 x i1> %A, <2 x i1> %B) { ; CHECK-LABEL: @test62vec( -; CHECK-NEXT: [[NOT_A:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[NOT_A]], <2 x i1> [[B:%.*]], <2 x i1> zeroinitializer +; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> zeroinitializer, <2 x i1> [[B:%.*]] ; CHECK-NEXT: ret <2 x i1> [[C]] ; %not = xor <2 x i1> %A, @@ -187,8 +180,7 @@ define i1 @test63(i1 %A, i1 %B) { ; CHECK-LABEL: @test63( -; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true -; CHECK-NEXT: [[C:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]] +; CHECK-NEXT: [[C:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 true ; CHECK-NEXT: ret i1 [[C]] ; %not = xor i1 %A, true @@ -198,8 +190,7 @@ define <2 x i1> @test63vec(<2 x i1> %A, <2 x i1> %B) { ; CHECK-LABEL: @test63vec( -; CHECK-NEXT: [[NOT_A:%.*]] = xor <2 x i1> [[A:%.*]], -; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[NOT_A]], <2 x i1> , <2 x i1> [[B:%.*]] +; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[A:%.*]], <2 x i1> [[B:%.*]], <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[C]] ; %not = xor <2 x i1> %A, @@ -316,8 +307,7 @@ define i1 @test14a(i1 %C, i32 %X) { ; CHECK-LABEL: @test14a( ; CHECK-NEXT: [[R1:%.*]] = icmp slt i32 [[X:%.*]], 1 -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[R1]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[R1]], i1 true ; CHECK-NEXT: ret i1 [[R]] ; %V = select i1 %C, i32 %X, i32 0 @@ -399,8 +389,7 @@ define i1 @test17(ptr %X, i1 %C) { ; CHECK-LABEL: @test17( ; CHECK-NEXT: [[RV1:%.*]] = icmp eq ptr [[X:%.*]], null -; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: [[RV:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[RV1]] +; CHECK-NEXT: [[RV:%.*]] = select i1 [[C:%.*]], i1 [[RV1]], i1 true ; CHECK-NEXT: ret i1 [[RV]] ; %R = select i1 %C, ptr %X, ptr null diff --git a/llvm/test/Transforms/InstCombine/sink-not-into-logical-and.ll b/llvm/test/Transforms/InstCombine/sink-not-into-logical-and.ll --- a/llvm/test/Transforms/InstCombine/sink-not-into-logical-and.ll +++ b/llvm/test/Transforms/InstCombine/sink-not-into-logical-and.ll @@ -40,8 +40,7 @@ define i1 @n2(i32 %v0, i32 %v1, i1 %i2) { ; CHECK-LABEL: @n2( ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] -; CHECK-NEXT: [[NOT_I2:%.*]] = xor i1 [[I2:%.*]], true -; CHECK-NEXT: [[I3:%.*]] = select i1 [[NOT_I2]], i1 true, i1 [[I1]] +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2:%.*]], i1 [[I1]], i1 true ; CHECK-NEXT: ret i1 [[I3]] ; %i1 = icmp eq i32 %v0, %v1 @@ -82,8 +81,7 @@ ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] ; CHECK-NEXT: call void @use1(i1 [[I2]]) -; CHECK-NEXT: [[NOT_I2:%.*]] = xor i1 [[I2]], true -; CHECK-NEXT: [[I3:%.*]] = select i1 [[NOT_I2]], i1 true, i1 [[I1]] +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 [[I1]], i1 true ; CHECK-NEXT: ret i1 [[I3]] ; %i1 = icmp eq i32 %v0, %v1 @@ -211,10 +209,10 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] ; CHECK: if: -; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i64 [[ARG:%.*]], 0 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[ARG:%.*]], 0 ; CHECK-NEXT: br label [[JOIN]] ; CHECK: join: -; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[CMP_NOT]], [[IF]] ] +; CHECK-NEXT: [[PHI:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ [[CMP]], [[IF]] ] ; CHECK-NEXT: ret i1 [[PHI]] ; entry: diff --git a/llvm/test/Transforms/InstCombine/sink-not-into-logical-or.ll b/llvm/test/Transforms/InstCombine/sink-not-into-logical-or.ll --- a/llvm/test/Transforms/InstCombine/sink-not-into-logical-or.ll +++ b/llvm/test/Transforms/InstCombine/sink-not-into-logical-or.ll @@ -40,8 +40,7 @@ define i1 @n2(i32 %v0, i32 %v1, i1 %i2) { ; CHECK-LABEL: @n2( ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] -; CHECK-NEXT: [[NOT_I2:%.*]] = xor i1 [[I2:%.*]], true -; CHECK-NEXT: [[I3:%.*]] = select i1 [[NOT_I2]], i1 [[I1]], i1 false +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2:%.*]], i1 false, i1 [[I1]] ; CHECK-NEXT: ret i1 [[I3]] ; %i1 = icmp eq i32 %v0, %v1 @@ -82,8 +81,7 @@ ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] ; CHECK-NEXT: call void @use1(i1 [[I2]]) -; CHECK-NEXT: [[NOT_I2:%.*]] = xor i1 [[I2]], true -; CHECK-NEXT: [[I3:%.*]] = select i1 [[NOT_I2]], i1 [[I1]], i1 false +; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 false, i1 [[I1]] ; CHECK-NEXT: ret i1 [[I3]] ; %i1 = icmp eq i32 %v0, %v1