diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 76 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineInternal.h | 5 | 
2 files changed, 70 insertions, 11 deletions
| diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index c3a7b62568c..81a89e67ea0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2610,8 +2610,9 @@ Instruction *InstCombiner::foldICmpInstWithConstant(ICmpInst &Cmp) {        return I;    } -  if (Instruction *I = foldICmpIntrinsicWithConstant(Cmp, *C)) -    return I; +  if (auto *II = dyn_cast<IntrinsicInst>(Cmp.getOperand(0))) +    if (Instruction *I = foldICmpIntrinsicWithConstant(Cmp, II, *C)) +      return I;    return nullptr;  } @@ -2755,14 +2756,10 @@ Instruction *InstCombiner::foldICmpBinOpEqualityWithConstant(ICmpInst &Cmp,    return nullptr;  } -/// Fold an icmp with LLVM intrinsic and constant operand: icmp Pred II, C. -Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &Cmp, -                                                         const APInt &C) { -  IntrinsicInst *II = dyn_cast<IntrinsicInst>(Cmp.getOperand(0)); -  if (!II || !Cmp.isEquality()) -    return nullptr; - -  // Handle icmp {eq|ne} <intrinsic>, Constant. +/// Fold an equality icmp with LLVM intrinsic and constant operand. +Instruction *InstCombiner::foldICmpEqIntrinsicWithConstant(ICmpInst &Cmp, +                                                           IntrinsicInst *II, +                                                           const APInt &C) {    Type *Ty = II->getType();    unsigned BitWidth = C.getBitWidth();    switch (II->getIntrinsicID()) { @@ -2822,6 +2819,65 @@ Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &Cmp,    return nullptr;  } +/// Fold an icmp with LLVM intrinsic and constant operand: icmp Pred II, C. +Instruction *InstCombiner::foldICmpIntrinsicWithConstant(ICmpInst &Cmp, +                                                         IntrinsicInst *II, +                                                         const APInt &C) { +  if (Cmp.isEquality()) +    return foldICmpEqIntrinsicWithConstant(Cmp, II, C); + +  Type *Ty = II->getType(); +  unsigned BitWidth = C.getBitWidth(); +  switch (II->getIntrinsicID()) { +  case Intrinsic::ctlz: { +    // ctlz(0bXXXXXXXX) > 3 -> 0bXXXXXXXX < 0b00010000 +    if (Cmp.getPredicate() == ICmpInst::ICMP_UGT && C.ult(BitWidth)) { +      unsigned Num = C.getLimitedValue(); +      APInt Limit = APInt::getOneBitSet(BitWidth, BitWidth - Num - 1); +      return CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_ULT, +                             II->getArgOperand(0), ConstantInt::get(Ty, Limit)); +    } + +    // ctlz(0bXXXXXXXX) < 3 -> 0bXXXXXXXX > 0b00011111 +    if (Cmp.getPredicate() == ICmpInst::ICMP_ULT && +        C.uge(1) && C.ule(BitWidth)) { +      unsigned Num = C.getLimitedValue(); +      APInt Limit = APInt::getLowBitsSet(BitWidth, BitWidth - Num); +      return CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_UGT, +                             II->getArgOperand(0), ConstantInt::get(Ty, Limit)); +    } +    break; +  } +  case Intrinsic::cttz: { +    // Limit to one use to ensure we don't increase instruction count. +    if (!II->hasOneUse()) +      return nullptr; + +    // cttz(0bXXXXXXXX) > 3 -> 0bXXXXXXXX & 0b00001111 == 0 +    if (Cmp.getPredicate() == ICmpInst::ICMP_UGT && C.ult(BitWidth)) { +      APInt Mask = APInt::getLowBitsSet(BitWidth, C.getLimitedValue() + 1); +      return CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_EQ, +                             Builder.CreateAnd(II->getArgOperand(0), Mask), +                             ConstantInt::getNullValue(Ty)); +    } + +    // cttz(0bXXXXXXXX) < 3 -> 0bXXXXXXXX & 0b00000111 != 0 +    if (Cmp.getPredicate() == ICmpInst::ICMP_ULT && +        C.uge(1) && C.ule(BitWidth)) { +      APInt Mask = APInt::getLowBitsSet(BitWidth, C.getLimitedValue()); +      return CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_NE, +                             Builder.CreateAnd(II->getArgOperand(0), Mask), +                             ConstantInt::getNullValue(Ty)); +    } +    break; +  } +  default: +    break; +  } + +  return nullptr; +} +  /// Handle icmp with constant (but not simple integer constant) RHS.  Instruction *InstCombiner::foldICmpInstWithConstantNotInt(ICmpInst &I) {    Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index fe28ee78de1..51e182ef187 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -903,7 +903,10 @@ private:    Instruction *foldICmpBinOpEqualityWithConstant(ICmpInst &Cmp,                                                   BinaryOperator *BO,                                                   const APInt &C); -  Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI, const APInt &C); +  Instruction *foldICmpIntrinsicWithConstant(ICmpInst &ICI, IntrinsicInst *II, +                                             const APInt &C); +  Instruction *foldICmpEqIntrinsicWithConstant(ICmpInst &ICI, IntrinsicInst *II, +                                               const APInt &C);    // Helpers of visitSelectInst().    Instruction *foldSelectExtConst(SelectInst &Sel); | 

