@@ -2643,46 +2643,33 @@ static Value *foldSelectWithFrozenICmp(SelectInst &Sel, InstCombiner::BuilderTy
2643
2643
return nullptr ;
2644
2644
}
2645
2645
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
+
2646
2661
Instruction *InstCombinerImpl::foldAndOrOfSelectUsingImpliedCond (Value *Op,
2647
2662
SelectInst &SI,
2648
2663
bool IsAnd) {
2649
- Value *CondVal = SI.getCondition ();
2650
- Value *A = SI.getTrueValue ();
2651
- Value *B = SI.getFalseValue ();
2652
-
2653
2664
assert (Op->getType ()->isIntOrIntVectorTy (1 ) &&
2654
2665
" 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 ())
2658
2667
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 ;
2686
2673
}
2687
2674
2688
2675
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need
@@ -3138,11 +3125,6 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
3138
3125
return replaceInstUsesWith (SI, Op1);
3139
3126
}
3140
3127
3141
- if (auto *Op1SI = dyn_cast<SelectInst>(Op1))
3142
- if (auto *I = foldAndOrOfSelectUsingImpliedCond (CondVal, *Op1SI,
3143
- /* IsAnd */ IsAnd))
3144
- return I;
3145
-
3146
3128
if (auto *ICmp0 = dyn_cast<ICmpInst>(CondVal))
3147
3129
if (auto *ICmp1 = dyn_cast<ICmpInst>(Op1))
3148
3130
if (auto *V = foldAndOrOfICmps (ICmp0, ICmp1, SI, IsAnd,
@@ -3643,12 +3625,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
3643
3625
3644
3626
if (SelectInst *TrueSI = dyn_cast<SelectInst>(TrueVal)) {
3645
3627
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
+
3652
3634
// select(C0, select(C1, a, b), b) -> select(C0&C1, a, b)
3653
3635
// We choose this as normal form to enable folding on the And and
3654
3636
// shortening paths for the values (this helps getUnderlyingObjects() for
@@ -3663,12 +3645,12 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
3663
3645
}
3664
3646
if (SelectInst *FalseSI = dyn_cast<SelectInst>(FalseVal)) {
3665
3647
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
+
3672
3654
// select(C0, a, select(C1, a, b)) -> select(C0|C1, a, b)
3673
3655
if (FalseSI->getTrueValue () == TrueVal && FalseSI->hasOneUse ()) {
3674
3656
Value *Or = Builder.CreateLogicalOr (CondVal, FalseSI->getCondition ());
0 commit comments