@@ -2643,46 +2643,33 @@ static Value *foldSelectWithFrozenICmp(SelectInst &Sel, InstCombiner::BuilderTy
26432643 return nullptr ;
26442644}
26452645
2646+ // / Given that \p CondVal is known to be \p CondIsTrue, try to simplify \p SI.
2647+ static Value *simplifyNestedSelectsUsingImpliedCond (SelectInst &SI,
2648+ Value *CondVal,
2649+ bool CondIsTrue,
2650+ const DataLayout &DL) {
2651+ Value *InnerCondVal = SI.getCondition ();
2652+ Value *InnerTrueVal = SI.getTrueValue ();
2653+ Value *InnerFalseVal = SI.getFalseValue ();
2654+ assert (CondVal->getType () == InnerCondVal->getType () &&
2655+ " The type of inner condition must match with the outer." );
2656+ if (auto Implied = isImpliedCondition (CondVal, InnerCondVal, DL, CondIsTrue))
2657+ return *Implied ? InnerTrueVal : InnerFalseVal;
2658+ return nullptr ;
2659+ }
2660+
26462661Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond (Value *Op,
26472662 SelectInst &SI,
26482663 bool IsAnd) {
2649- Value *CondVal = SI.getCondition ();
2650- Value *A = SI.getTrueValue ();
2651- Value *B = SI.getFalseValue ();
2652-
26532664 assert (Op->getType ()->isIntOrIntVectorTy (1 ) &&
26542665 " Op must be either i1 or vector of i1." );
2655-
2656- std::optional<bool > Res = isImpliedCondition (Op, CondVal, DL, IsAnd);
2657- if (!Res)
2666+ if (SI.getCondition ()->getType () != Op->getType ())
26582667 return nullptr ;
2659-
2660- Value *Zero = Constant::getNullValue (A->getType ());
2661- Value *One = Constant::getAllOnesValue (A->getType ());
2662-
2663- if (*Res == true ) {
2664- if (IsAnd)
2665- // select op, (select cond, A, B), false => select op, A, false
2666- // and op, (select cond, A, B) => select op, A, false
2667- // if op = true implies condval = true.
2668- return SelectInst::Create (Op, A, Zero);
2669- else
2670- // select op, true, (select cond, A, B) => select op, true, A
2671- // or op, (select cond, A, B) => select op, true, A
2672- // if op = false implies condval = true.
2673- return SelectInst::Create (Op, One, A);
2674- } else {
2675- if (IsAnd)
2676- // select op, (select cond, A, B), false => select op, B, false
2677- // and op, (select cond, A, B) => select op, B, false
2678- // if op = true implies condval = false.
2679- return SelectInst::Create (Op, B, Zero);
2680- else
2681- // select op, true, (select cond, A, B) => select op, true, B
2682- // or op, (select cond, A, B) => select op, true, B
2683- // if op = false implies condval = false.
2684- return SelectInst::Create (Op, One, B);
2685- }
2668+ if (Value *V = simplifyNestedSelectsUsingImpliedCond (SI, Op, IsAnd, DL))
2669+ return SelectInst::Create (Op,
2670+ IsAnd ? V : ConstantInt::getTrue (Op->getType ()),
2671+ IsAnd ? ConstantInt::getFalse (Op->getType ()) : V);
2672+ return nullptr ;
26862673}
26872674
26882675// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
@@ -3138,11 +3125,6 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
31383125 return replaceInstUsesWith (SI, Op1);
31393126 }
31403127
3141- if (auto *Op1SI = dyn_cast<SelectInst>(Op1))
3142- if (auto *I = foldAndOrOfSelectUsingImpliedCond (CondVal, *Op1SI,
3143- /* IsAnd */ IsAnd))
3144- return I;
3145-
31463128 if (auto *ICmp0 = dyn_cast<ICmpInst>(CondVal))
31473129 if (auto *ICmp1 = dyn_cast<ICmpInst>(Op1))
31483130 if (auto *V = foldAndOrOfICmps (ICmp0, ICmp1, SI, IsAnd,
@@ -3643,12 +3625,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
36433625
36443626 if (SelectInst *TrueSI = dyn_cast<SelectInst>(TrueVal)) {
36453627 if (TrueSI->getCondition ()->getType () == CondVal->getType ()) {
3646- // select(C, select(C, a, b), c) -> select(C, a, c)
3647- if (TrueSI-> getCondition () == CondVal) {
3648- if (SI. getTrueValue () == TrueSI-> getTrueValue ())
3649- return nullptr ;
3650- return replaceOperand (SI, 1 , TrueSI-> getTrueValue () );
3651- }
3628+ // Fold nested selects if the inner condition can be implied by the outer
3629+ // condition.
3630+ if (Value *V = simplifyNestedSelectsUsingImpliedCond (
3631+ *TrueSI, CondVal, /* CondIsTrue= */ true , DL))
3632+ return replaceOperand (SI, 1 , V );
3633+
36523634 // select(C0, select(C1, a, b), b) -> select(C0&C1, a, b)
36533635 // We choose this as normal form to enable folding on the And and
36543636 // shortening paths for the values (this helps getUnderlyingObjects() for
@@ -3663,12 +3645,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
36633645 }
36643646 if (SelectInst *FalseSI = dyn_cast<SelectInst>(FalseVal)) {
36653647 if (FalseSI->getCondition ()->getType () == CondVal->getType ()) {
3666- // select(C, a, select(C, b, c)) -> select(C, a, c)
3667- if (FalseSI-> getCondition () == CondVal) {
3668- if (SI. getFalseValue () == FalseSI-> getFalseValue ())
3669- return nullptr ;
3670- return replaceOperand (SI, 2 , FalseSI-> getFalseValue () );
3671- }
3648+ // Fold nested selects if the inner condition can be implied by the outer
3649+ // condition.
3650+ if (Value *V = simplifyNestedSelectsUsingImpliedCond (
3651+ *FalseSI, CondVal, /* CondIsTrue= */ false , DL))
3652+ return replaceOperand (SI, 2 , V );
3653+
36723654 // select(C0, a, select(C1, a, b)) -> select(C0|C1, a, b)
36733655 if (FalseSI->getTrueValue () == TrueVal && FalseSI->hasOneUse ()) {
36743656 Value *Or = Builder.CreateLogicalOr (CondVal, FalseSI->getCondition ());
0 commit comments