diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 71 | 
1 files changed, 60 insertions, 11 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 20bf00344b14..ab55f235920a 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1171,14 +1171,15 @@ static Value *foldSelectCttzCtlz(ICmpInst *ICI, Value *TrueVal, Value *FalseVal,    return nullptr;  } -static Instruction *canonicalizeSPF(SelectInst &Sel, ICmpInst &Cmp, -                                    InstCombinerImpl &IC) { +static Value *canonicalizeSPF(ICmpInst &Cmp, Value *TrueVal, Value *FalseVal, +                              InstCombinerImpl &IC) {    Value *LHS, *RHS;    // TODO: What to do with pointer min/max patterns? -  if (!Sel.getType()->isIntOrIntVectorTy()) +  if (!TrueVal->getType()->isIntOrIntVectorTy())      return nullptr; -  SelectPatternFlavor SPF = matchSelectPattern(&Sel, LHS, RHS).Flavor; +  SelectPatternFlavor SPF = +      matchDecomposedSelectPattern(&Cmp, TrueVal, FalseVal, LHS, RHS).Flavor;    if (SPF == SelectPatternFlavor::SPF_ABS ||        SPF == SelectPatternFlavor::SPF_NABS) {      if (!Cmp.hasOneUse() && !RHS->hasOneUse()) @@ -1188,13 +1189,13 @@ static Instruction *canonicalizeSPF(SelectInst &Sel, ICmpInst &Cmp,      bool IntMinIsPoison = SPF == SelectPatternFlavor::SPF_ABS &&                            match(RHS, m_NSWNeg(m_Specific(LHS)));      Constant *IntMinIsPoisonC = -        ConstantInt::get(Type::getInt1Ty(Sel.getContext()), IntMinIsPoison); +        ConstantInt::get(Type::getInt1Ty(Cmp.getContext()), IntMinIsPoison);      Instruction *Abs =          IC.Builder.CreateBinaryIntrinsic(Intrinsic::abs, LHS, IntMinIsPoisonC);      if (SPF == SelectPatternFlavor::SPF_NABS) -      return BinaryOperator::CreateNeg(Abs); // Always without NSW flag! -    return IC.replaceInstUsesWith(Sel, Abs); +      return IC.Builder.CreateNeg(Abs); // Always without NSW flag! +    return Abs;    }    if (SelectPatternResult::isMinOrMax(SPF)) { @@ -1215,8 +1216,7 @@ static Instruction *canonicalizeSPF(SelectInst &Sel, ICmpInst &Cmp,      default:        llvm_unreachable("Unexpected SPF");      } -    return IC.replaceInstUsesWith( -        Sel, IC.Builder.CreateBinaryIntrinsic(IntrinsicID, LHS, RHS)); +    return IC.Builder.CreateBinaryIntrinsic(IntrinsicID, LHS, RHS);    }    return nullptr; @@ -1677,8 +1677,9 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,    if (Instruction *NewSel = foldSelectValueEquivalence(SI, *ICI))      return NewSel; -  if (Instruction *NewSPF = canonicalizeSPF(SI, *ICI, *this)) -    return NewSPF; +  if (Value *V = +          canonicalizeSPF(*ICI, SI.getTrueValue(), SI.getFalseValue(), *this)) +    return replaceInstUsesWith(SI, V);    if (Value *V = foldSelectInstWithICmpConst(SI, ICI, Builder))      return replaceInstUsesWith(SI, V); @@ -2363,6 +2364,9 @@ static Instruction *foldSelectToCopysign(SelectInst &Sel,    Value *FVal = Sel.getFalseValue();    Type *SelType = Sel.getType(); +  if (ICmpInst::makeCmpResultType(TVal->getType()) != Cond->getType()) +    return nullptr; +    // Match select ?, TC, FC where the constants are equal but negated.    // TODO: Generalize to handle a negated variable operand?    const APFloat *TC, *FC; @@ -3790,5 +3794,50 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {    if (Instruction *I = foldBitCeil(SI, Builder))      return I; +  // Fold: +  // (select A && B, T, F) -> (select A, (select B, T, F), F) +  // (select A || B, T, F) -> (select A, T, (select B, T, F)) +  // if (select B, T, F) is foldable. +  // TODO: preserve FMF flags +  auto FoldSelectWithAndOrCond = [&](bool IsAnd, Value *A, +                                     Value *B) -> Instruction * { +    if (Value *V = simplifySelectInst(B, TrueVal, FalseVal, +                                      SQ.getWithInstruction(&SI))) +      return SelectInst::Create(A, IsAnd ? V : TrueVal, IsAnd ? FalseVal : V); + +    // Is (select B, T, F) a SPF? +    if (CondVal->hasOneUse() && SelType->isIntOrIntVectorTy()) { +      if (ICmpInst *Cmp = dyn_cast<ICmpInst>(B)) +        if (Value *V = canonicalizeSPF(*Cmp, TrueVal, FalseVal, *this)) +          return SelectInst::Create(A, IsAnd ? V : TrueVal, +                                    IsAnd ? FalseVal : V); +    } + +    return nullptr; +  }; + +  Value *LHS, *RHS; +  if (match(CondVal, m_And(m_Value(LHS), m_Value(RHS)))) { +    if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ true, LHS, RHS)) +      return I; +    if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ true, RHS, LHS)) +      return I; +  } else if (match(CondVal, m_Or(m_Value(LHS), m_Value(RHS)))) { +    if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ false, LHS, RHS)) +      return I; +    if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ false, RHS, LHS)) +      return I; +  } else { +    // We cannot swap the operands of logical and/or. +    // TODO: Can we swap the operands by inserting a freeze? +    if (match(CondVal, m_LogicalAnd(m_Value(LHS), m_Value(RHS)))) { +      if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ true, LHS, RHS)) +        return I; +    } else if (match(CondVal, m_LogicalOr(m_Value(LHS), m_Value(RHS)))) { +      if (Instruction *I = FoldSelectWithAndOrCond(/*IsAnd*/ false, LHS, RHS)) +        return I; +    } +  } +    return nullptr;  }  | 
