diff options
Diffstat (limited to 'llvm/lib/Analysis')
| -rwxr-xr-x | llvm/lib/Analysis/ConstantFolding.cpp | 44 | ||||
| -rw-r--r-- | llvm/lib/Analysis/DependenceAnalysis.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/Analysis/HashRecognize.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 50 | 
4 files changed, 76 insertions, 45 deletions
| diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index e9e2e7d..da32542 100755 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2163,18 +2163,42 @@ Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double),  }  Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) { -  FixedVectorType *VT = dyn_cast<FixedVectorType>(Op->getType()); -  if (!VT) -    return nullptr; - -  // This isn't strictly necessary, but handle the special/common case of zero: -  // all integer reductions of a zero input produce zero. -  if (isa<ConstantAggregateZero>(Op)) -    return ConstantInt::get(VT->getElementType(), 0); +  auto *OpVT = cast<VectorType>(Op->getType());    // This is the same as the underlying binops - poison propagates. -  if (isa<PoisonValue>(Op) || Op->containsPoisonElement()) -    return PoisonValue::get(VT->getElementType()); +  if (Op->containsPoisonElement()) +    return PoisonValue::get(OpVT->getElementType()); + +  // Shortcut non-accumulating reductions. +  if (Constant *SplatVal = Op->getSplatValue()) { +    switch (IID) { +    case Intrinsic::vector_reduce_and: +    case Intrinsic::vector_reduce_or: +    case Intrinsic::vector_reduce_smin: +    case Intrinsic::vector_reduce_smax: +    case Intrinsic::vector_reduce_umin: +    case Intrinsic::vector_reduce_umax: +      return SplatVal; +    case Intrinsic::vector_reduce_add: +      if (SplatVal->isNullValue()) +        return SplatVal; +      break; +    case Intrinsic::vector_reduce_mul: +      if (SplatVal->isNullValue() || SplatVal->isOneValue()) +        return SplatVal; +      break; +    case Intrinsic::vector_reduce_xor: +      if (SplatVal->isNullValue()) +        return SplatVal; +      if (OpVT->getElementCount().isKnownMultipleOf(2)) +        return Constant::getNullValue(OpVT->getElementType()); +      break; +    } +  } + +  FixedVectorType *VT = dyn_cast<FixedVectorType>(OpVT); +  if (!VT) +    return nullptr;    // TODO: Handle undef.    auto *EltC = dyn_cast_or_null<ConstantInt>(Op->getAggregateElement(0U)); diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index 84ee8c0..11d8294 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -2854,14 +2854,18 @@ bool DependenceInfo::testMIV(const SCEV *Src, const SCEV *Dst,           banerjeeMIVtest(Src, Dst, Loops, Result);  } -// Given a product, e.g., 10*X*Y, returns the first constant operand, -// in this case 10. If there is no constant part, returns std::nullopt. -static std::optional<APInt> getConstantPart(const SCEV *Expr) { +/// Given a SCEVMulExpr, returns its first operand if its first operand is a +/// constant and the product doesn't overflow in a signed sense. Otherwise, +/// returns std::nullopt. For example, given (10 * X * Y)<nsw>, it returns 10. +/// Notably, if it doesn't have nsw, the multiplication may overflow, and if +/// so, it may not a multiple of 10. +static std::optional<APInt> getConstanCoefficient(const SCEV *Expr) {    if (const auto *Constant = dyn_cast<SCEVConstant>(Expr))      return Constant->getAPInt();    if (const auto *Product = dyn_cast<SCEVMulExpr>(Expr))      if (const auto *Constant = dyn_cast<SCEVConstant>(Product->getOperand(0))) -      return Constant->getAPInt(); +      if (Product->hasNoSignedWrap()) +        return Constant->getAPInt();    return std::nullopt;  } @@ -2887,7 +2891,7 @@ bool DependenceInfo::accumulateCoefficientsGCD(const SCEV *Expr,    if (AddRec->getLoop() == CurLoop) {      CurLoopCoeff = Step;    } else { -    std::optional<APInt> ConstCoeff = getConstantPart(Step); +    std::optional<APInt> ConstCoeff = getConstanCoefficient(Step);      // If the coefficient is the product of a constant and other stuff, we can      // use the constant in the GCD computation. @@ -2940,7 +2944,7 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,      const SCEV *Coeff = AddRec->getStepRecurrence(*SE);      // If the coefficient is the product of a constant and other stuff,      // we can use the constant in the GCD computation. -    std::optional<APInt> ConstCoeff = getConstantPart(Coeff); +    std::optional<APInt> ConstCoeff = getConstanCoefficient(Coeff);      if (!ConstCoeff)        return false;      RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff->abs()); @@ -2958,7 +2962,7 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,      const SCEV *Coeff = AddRec->getStepRecurrence(*SE);      // If the coefficient is the product of a constant and other stuff,      // we can use the constant in the GCD computation. -    std::optional<APInt> ConstCoeff = getConstantPart(Coeff); +    std::optional<APInt> ConstCoeff = getConstanCoefficient(Coeff);      if (!ConstCoeff)        return false;      RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff->abs()); @@ -2979,7 +2983,7 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,        } else if (const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Operand)) {          // Search for constant operand to participate in GCD;          // If none found; return false. -        std::optional<APInt> ConstOp = getConstantPart(Product); +        std::optional<APInt> ConstOp = getConstanCoefficient(Product);          if (!ConstOp)            return false;          ExtraGCD = APIntOps::GreatestCommonDivisor(ExtraGCD, ConstOp->abs()); @@ -3032,7 +3036,7 @@ bool DependenceInfo::gcdMIVtest(const SCEV *Src, const SCEV *Dst,      Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);      // If the coefficient is the product of a constant and other stuff,      // we can use the constant in the GCD computation. -    std::optional<APInt> ConstCoeff = getConstantPart(Delta); +    std::optional<APInt> ConstCoeff = getConstanCoefficient(Delta);      if (!ConstCoeff)        // The difference of the two coefficients might not be a product        // or constant, in which case we give up on this direction. diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp index 4529123..8974ce5 100644 --- a/llvm/lib/Analysis/HashRecognize.cpp +++ b/llvm/lib/Analysis/HashRecognize.cpp @@ -468,8 +468,11 @@ std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {      // Ensure that the PHIs have exactly two uses:      // the bit-shift, and the XOR (or a cast feeding into the XOR). +    // Also ensure that the SimpleRecurrence's evolution doesn't have stray +    // users.      if (!ConditionalRecurrence.Phi->hasNUses(2) || -        !SimpleRecurrence.Phi->hasNUses(2)) +        !SimpleRecurrence.Phi->hasNUses(2) || +        SimpleRecurrence.BO->getUniqueUndroppableUser() != SimpleRecurrence.Phi)        return "Recurrences have stray uses";      // Check that the SelectInst ConditionalRecurrence.Step is conditional on diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 7597f3a..c9baeda 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -15670,31 +15670,31 @@ void ScalarEvolution::LoopGuards::collectFromBlock(      // predicate.      const SCEV *One = SE.getOne(RHS->getType());      switch (Predicate) { -      case CmpInst::ICMP_ULT: -        if (RHS->getType()->isPointerTy()) -          return; -        RHS = SE.getUMaxExpr(RHS, One); -        [[fallthrough]]; -      case CmpInst::ICMP_SLT: { -        RHS = SE.getMinusSCEV(RHS, One); -        RHS = getPreviousSCEVDivisibleByDivisor(RHS, DividesBy, SE); -        break; -      } -      case CmpInst::ICMP_UGT: -      case CmpInst::ICMP_SGT: -        RHS = SE.getAddExpr(RHS, One); -        RHS = getNextSCEVDivisibleByDivisor(RHS, DividesBy, SE); -        break; -      case CmpInst::ICMP_ULE: -      case CmpInst::ICMP_SLE: -        RHS = getPreviousSCEVDivisibleByDivisor(RHS, DividesBy, SE); -        break; -      case CmpInst::ICMP_UGE: -      case CmpInst::ICMP_SGE: -        RHS = getNextSCEVDivisibleByDivisor(RHS, DividesBy, SE); -        break; -      default: -        break; +    case CmpInst::ICMP_ULT: +      if (RHS->getType()->isPointerTy()) +        return; +      RHS = SE.getUMaxExpr(RHS, One); +      [[fallthrough]]; +    case CmpInst::ICMP_SLT: { +      RHS = SE.getMinusSCEV(RHS, One); +      RHS = getPreviousSCEVDivisibleByDivisor(RHS, DividesBy, SE); +      break; +    } +    case CmpInst::ICMP_UGT: +    case CmpInst::ICMP_SGT: +      RHS = SE.getAddExpr(RHS, One); +      RHS = getNextSCEVDivisibleByDivisor(RHS, DividesBy, SE); +      break; +    case CmpInst::ICMP_ULE: +    case CmpInst::ICMP_SLE: +      RHS = getPreviousSCEVDivisibleByDivisor(RHS, DividesBy, SE); +      break; +    case CmpInst::ICMP_UGE: +    case CmpInst::ICMP_SGE: +      RHS = getNextSCEVDivisibleByDivisor(RHS, DividesBy, SE); +      break; +    default: +      break;      }      SmallVector<const SCEV *, 16> Worklist(1, LHS); | 
