diff options
Diffstat (limited to 'llvm/lib/Analysis')
| -rw-r--r-- | llvm/lib/Analysis/AliasAnalysis.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 198 | ||||
| -rw-r--r-- | llvm/lib/Analysis/TargetTransformInfo.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 76 | 
4 files changed, 130 insertions, 152 deletions
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp index f2dc25f..26a5602 100644 --- a/llvm/lib/Analysis/AliasAnalysis.cpp +++ b/llvm/lib/Analysis/AliasAnalysis.cpp @@ -75,7 +75,7 @@ AAResults::AAResults(const TargetLibraryInfo &TLI) : TLI(TLI) {}  AAResults::AAResults(AAResults &&Arg)      : TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) {} -AAResults::~AAResults() {} +AAResults::~AAResults() = default;  bool AAResults::invalidate(Function &F, const PreservedAnalyses &PA,                             FunctionAnalysisManager::Invalidator &Inv) { diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index c9baeda..a31f17b 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -2424,10 +2424,10 @@ ScalarEvolution::getStrengthenedNoWrapFlagsFromBinOp(  // We're trying to construct a SCEV of type `Type' with `Ops' as operands and  // `OldFlags' as can't-wrap behavior.  Infer a more aggressive set of  // can't-overflow flags for the operation if possible. -static SCEV::NoWrapFlags -StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type, -                      const ArrayRef<const SCEV *> Ops, -                      SCEV::NoWrapFlags Flags) { +static SCEV::NoWrapFlags StrengthenNoWrapFlags(ScalarEvolution *SE, +                                               SCEVTypes Type, +                                               ArrayRef<const SCEV *> Ops, +                                               SCEV::NoWrapFlags Flags) {    using namespace std::placeholders;    using OBO = OverflowingBinaryOperator; @@ -2540,7 +2540,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,    unsigned Idx = isa<SCEVConstant>(Ops[0]) ? 1 : 0;    // Delay expensive flag strengthening until necessary. -  auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) { +  auto ComputeFlags = [this, OrigFlags](ArrayRef<const SCEV *> Ops) {      return StrengthenNoWrapFlags(this, scAddExpr, Ops, OrigFlags);    }; @@ -3125,7 +3125,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,      return Folded;    // Delay expensive flag strengthening until necessary. -  auto ComputeFlags = [this, OrigFlags](const ArrayRef<const SCEV *> Ops) { +  auto ComputeFlags = [this, OrigFlags](ArrayRef<const SCEV *> Ops) {      return StrengthenNoWrapFlags(this, scMulExpr, Ops, OrigFlags);    }; @@ -15510,6 +15510,78 @@ static const SCEV *getNextSCEVDivisibleByDivisor(const SCEV *Expr,    return SE.getConstant(*ExprVal + DivisorVal - Rem);  } +static bool collectDivisibilityInformation( +    ICmpInst::Predicate Predicate, const SCEV *LHS, const SCEV *RHS, +    DenseMap<const SCEV *, const SCEV *> &DivInfo, +    DenseMap<const SCEV *, APInt> &Multiples, ScalarEvolution &SE) { +  // If we have LHS == 0, check if LHS is computing a property of some unknown +  // SCEV %v which we can rewrite %v to express explicitly. +  if (Predicate != CmpInst::ICMP_EQ || !match(RHS, m_scev_Zero())) +    return false; +  // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to +  // explicitly express that. +  const SCEVUnknown *URemLHS = nullptr; +  const SCEV *URemRHS = nullptr; +  if (!match(LHS, m_scev_URem(m_SCEVUnknown(URemLHS), m_SCEV(URemRHS), SE))) +    return false; + +  const SCEV *Multiple = +      SE.getMulExpr(SE.getUDivExpr(URemLHS, URemRHS), URemRHS); +  DivInfo[URemLHS] = Multiple; +  if (auto *C = dyn_cast<SCEVConstant>(URemRHS)) +    Multiples[URemLHS] = C->getAPInt(); +  return true; +} + +// Check if the condition is a divisibility guard (A % B == 0). +static bool isDivisibilityGuard(const SCEV *LHS, const SCEV *RHS, +                                ScalarEvolution &SE) { +  const SCEV *X, *Y; +  return match(LHS, m_scev_URem(m_SCEV(X), m_SCEV(Y), SE)) && RHS->isZero(); +} + +// Apply divisibility by \p Divisor on MinMaxExpr with constant values, +// recursively. This is done by aligning up/down the constant value to the +// Divisor. +static const SCEV *applyDivisibilityOnMinMaxExpr(const SCEV *MinMaxExpr, +                                                 APInt Divisor, +                                                 ScalarEvolution &SE) { +  // Return true if \p Expr is a MinMax SCEV expression with a non-negative +  // constant operand. If so, return in \p SCTy the SCEV type and in \p RHS +  // the non-constant operand and in \p LHS the constant operand. +  auto IsMinMaxSCEVWithNonNegativeConstant = +      [&](const SCEV *Expr, SCEVTypes &SCTy, const SCEV *&LHS, +          const SCEV *&RHS) { +        if (auto *MinMax = dyn_cast<SCEVMinMaxExpr>(Expr)) { +          if (MinMax->getNumOperands() != 2) +            return false; +          if (auto *C = dyn_cast<SCEVConstant>(MinMax->getOperand(0))) { +            if (C->getAPInt().isNegative()) +              return false; +            SCTy = MinMax->getSCEVType(); +            LHS = MinMax->getOperand(0); +            RHS = MinMax->getOperand(1); +            return true; +          } +        } +        return false; +      }; + +  const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr; +  SCEVTypes SCTy; +  if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS, +                                           MinMaxRHS)) +    return MinMaxExpr; +  auto IsMin = isa<SCEVSMinExpr>(MinMaxExpr) || isa<SCEVUMinExpr>(MinMaxExpr); +  assert(SE.isKnownNonNegative(MinMaxLHS) && "Expected non-negative operand!"); +  auto *DivisibleExpr = +      IsMin ? getPreviousSCEVDivisibleByDivisor(MinMaxLHS, Divisor, SE) +            : getNextSCEVDivisibleByDivisor(MinMaxLHS, Divisor, SE); +  SmallVector<const SCEV *> Ops = { +      applyDivisibilityOnMinMaxExpr(MinMaxRHS, Divisor, SE), DivisibleExpr}; +  return SE.getMinMaxExpr(SCTy, Ops); +} +  void ScalarEvolution::LoopGuards::collectFromBlock(      ScalarEvolution &SE, ScalarEvolution::LoopGuards &Guards,      const BasicBlock *Block, const BasicBlock *Pred, @@ -15520,19 +15592,13 @@ void ScalarEvolution::LoopGuards::collectFromBlock(    SmallVector<const SCEV *> ExprsToRewrite;    auto CollectCondition = [&](ICmpInst::Predicate Predicate, const SCEV *LHS,                                const SCEV *RHS, -                              DenseMap<const SCEV *, const SCEV *> -                                  &RewriteMap) { +                              DenseMap<const SCEV *, const SCEV *> &RewriteMap, +                              const LoopGuards &DivGuards) {      // WARNING: It is generally unsound to apply any wrap flags to the proposed      // replacement SCEV which isn't directly implied by the structure of that      // SCEV.  In particular, using contextual facts to imply flags is *NOT*      // legal.  See the scoping rules for flags in the header to understand why. -    // If LHS is a constant, apply information to the other expression. -    if (isa<SCEVConstant>(LHS)) { -      std::swap(LHS, RHS); -      Predicate = CmpInst::getSwappedPredicate(Predicate); -    } -      // Check for a condition of the form (-C1 + X < C2).  InstCombine will      // create this form when combining two checks of the form (X u< C2 + C1) and      // (X >=u C1). @@ -15565,67 +15631,6 @@ void ScalarEvolution::LoopGuards::collectFromBlock(      if (MatchRangeCheckIdiom())        return; -    // Return true if \p Expr is a MinMax SCEV expression with a non-negative -    // constant operand. If so, return in \p SCTy the SCEV type and in \p RHS -    // the non-constant operand and in \p LHS the constant operand. -    auto IsMinMaxSCEVWithNonNegativeConstant = -        [&](const SCEV *Expr, SCEVTypes &SCTy, const SCEV *&LHS, -            const SCEV *&RHS) { -          const APInt *C; -          SCTy = Expr->getSCEVType(); -          return match(Expr, m_scev_MinMax(m_SCEV(LHS), m_SCEV(RHS))) && -                 match(LHS, m_scev_APInt(C)) && C->isNonNegative(); -        }; - -    // Apply divisibilty by \p Divisor on MinMaxExpr with constant values, -    // recursively. This is done by aligning up/down the constant value to the -    // Divisor. -    std::function<const SCEV *(const SCEV *, const SCEV *)> -        ApplyDivisibiltyOnMinMaxExpr = [&](const SCEV *MinMaxExpr, -                                           const SCEV *Divisor) { -          auto *ConstDivisor = dyn_cast<SCEVConstant>(Divisor); -          if (!ConstDivisor) -            return MinMaxExpr; -          const APInt &DivisorVal = ConstDivisor->getAPInt(); - -          const SCEV *MinMaxLHS = nullptr, *MinMaxRHS = nullptr; -          SCEVTypes SCTy; -          if (!IsMinMaxSCEVWithNonNegativeConstant(MinMaxExpr, SCTy, MinMaxLHS, -                                                   MinMaxRHS)) -            return MinMaxExpr; -          auto IsMin = -              isa<SCEVSMinExpr>(MinMaxExpr) || isa<SCEVUMinExpr>(MinMaxExpr); -          assert(SE.isKnownNonNegative(MinMaxLHS) && -                 "Expected non-negative operand!"); -          auto *DivisibleExpr = -              IsMin -                  ? getPreviousSCEVDivisibleByDivisor(MinMaxLHS, DivisorVal, SE) -                  : getNextSCEVDivisibleByDivisor(MinMaxLHS, DivisorVal, SE); -          SmallVector<const SCEV *> Ops = { -              ApplyDivisibiltyOnMinMaxExpr(MinMaxRHS, Divisor), DivisibleExpr}; -          return SE.getMinMaxExpr(SCTy, Ops); -        }; - -    // If we have LHS == 0, check if LHS is computing a property of some unknown -    // SCEV %v which we can rewrite %v to express explicitly. -    if (Predicate == CmpInst::ICMP_EQ && match(RHS, m_scev_Zero())) { -      // If LHS is A % B, i.e. A % B == 0, rewrite A to (A /u B) * B to -      // explicitly express that. -      const SCEVUnknown *URemLHS = nullptr; -      const SCEV *URemRHS = nullptr; -      if (match(LHS, -                m_scev_URem(m_SCEVUnknown(URemLHS), m_SCEV(URemRHS), SE))) { -        auto I = RewriteMap.find(URemLHS); -        const SCEV *RewrittenLHS = I != RewriteMap.end() ? I->second : URemLHS; -        RewrittenLHS = ApplyDivisibiltyOnMinMaxExpr(RewrittenLHS, URemRHS); -        const auto *Multiple = -            SE.getMulExpr(SE.getUDivExpr(RewrittenLHS, URemRHS), URemRHS); -        RewriteMap[URemLHS] = Multiple; -        ExprsToRewrite.push_back(URemLHS); -        return; -      } -    } -      // Do not apply information for constants or if RHS contains an AddRec.      if (isa<SCEVConstant>(LHS) || SE.containsAddRecurrence(RHS))        return; @@ -15655,7 +15660,9 @@ void ScalarEvolution::LoopGuards::collectFromBlock(      };      const SCEV *RewrittenLHS = GetMaybeRewritten(LHS); -    const APInt &DividesBy = SE.getConstantMultiple(RewrittenLHS); +    // Apply divisibility information when computing the constant multiple. +    const APInt &DividesBy = +        SE.getConstantMultiple(DivGuards.rewrite(RewrittenLHS));      // Collect rewrites for LHS and its transitive operands based on the      // condition. @@ -15840,8 +15847,11 @@ void ScalarEvolution::LoopGuards::collectFromBlock(    // Now apply the information from the collected conditions to    // Guards.RewriteMap. Conditions are processed in reverse order, so the -  // earliest conditions is processed first. This ensures the SCEVs with the +  // earliest conditions is processed first, except guards with divisibility +  // information, which are moved to the back. This ensures the SCEVs with the    // shortest dependency chains are constructed first. +  SmallVector<std::tuple<CmpInst::Predicate, const SCEV *, const SCEV *>> +      GuardsToProcess;    for (auto [Term, EnterIfTrue] : reverse(Terms)) {      SmallVector<Value *, 8> Worklist;      SmallPtrSet<Value *, 8> Visited; @@ -15856,7 +15866,14 @@ void ScalarEvolution::LoopGuards::collectFromBlock(              EnterIfTrue ? Cmp->getPredicate() : Cmp->getInversePredicate();          const auto *LHS = SE.getSCEV(Cmp->getOperand(0));          const auto *RHS = SE.getSCEV(Cmp->getOperand(1)); -        CollectCondition(Predicate, LHS, RHS, Guards.RewriteMap); +        // If LHS is a constant, apply information to the other expression. +        // TODO: If LHS is not a constant, check if using CompareSCEVComplexity +        // can improve results. +        if (isa<SCEVConstant>(LHS)) { +          std::swap(LHS, RHS); +          Predicate = CmpInst::getSwappedPredicate(Predicate); +        } +        GuardsToProcess.emplace_back(Predicate, LHS, RHS);          continue;        } @@ -15869,6 +15886,31 @@ void ScalarEvolution::LoopGuards::collectFromBlock(      }    } +  // Process divisibility guards in reverse order to populate DivGuards early. +  DenseMap<const SCEV *, APInt> Multiples; +  LoopGuards DivGuards(SE); +  for (const auto &[Predicate, LHS, RHS] : GuardsToProcess) { +    if (!isDivisibilityGuard(LHS, RHS, SE)) +      continue; +    collectDivisibilityInformation(Predicate, LHS, RHS, DivGuards.RewriteMap, +                                   Multiples, SE); +  } + +  for (const auto &[Predicate, LHS, RHS] : GuardsToProcess) +    CollectCondition(Predicate, LHS, RHS, Guards.RewriteMap, DivGuards); + +  // Apply divisibility information last. This ensures it is applied to the +  // outermost expression after other rewrites for the given value. +  for (const auto &[K, Divisor] : Multiples) { +    const SCEV *DivisorSCEV = SE.getConstant(Divisor); +    Guards.RewriteMap[K] = +        SE.getMulExpr(SE.getUDivExpr(applyDivisibilityOnMinMaxExpr( +                                         Guards.rewrite(K), Divisor, SE), +                                     DivisorSCEV), +                      DivisorSCEV); +    ExprsToRewrite.push_back(K); +  } +    // Let the rewriter preserve NUW/NSW flags if the unsigned/signed ranges of    // the replacement expressions are contained in the ranges of the replaced    // expressions. diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index c47a1c1..0426ac7 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -1353,9 +1353,9 @@ TargetTransformInfo::getInlineCallPenalty(const Function *F,    return TTIImpl->getInlineCallPenalty(F, Call, DefaultCallPenalty);  } -bool TargetTransformInfo::areTypesABICompatible( -    const Function *Caller, const Function *Callee, -    const ArrayRef<Type *> &Types) const { +bool TargetTransformInfo::areTypesABICompatible(const Function *Caller, +                                                const Function *Callee, +                                                ArrayRef<Type *> Types) const {    return TTIImpl->areTypesABICompatible(Caller, Callee, Types);  } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 0a72076..523374b 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -7419,84 +7419,20 @@ static bool canCreateUndefOrPoison(const Operator *Op, UndefPoisonKind Kind,          if (cast<ConstantInt>(II->getArgOperand(1))->isNullValue())            return false;          break; -      case Intrinsic::ctpop: -      case Intrinsic::bswap: -      case Intrinsic::bitreverse: -      case Intrinsic::fshl: -      case Intrinsic::fshr: -      case Intrinsic::smax: -      case Intrinsic::smin: -      case Intrinsic::scmp: -      case Intrinsic::umax: -      case Intrinsic::umin: -      case Intrinsic::ucmp: -      case Intrinsic::ptrmask: -      case Intrinsic::fptoui_sat: -      case Intrinsic::fptosi_sat: -      case Intrinsic::sadd_with_overflow: -      case Intrinsic::ssub_with_overflow: -      case Intrinsic::smul_with_overflow: -      case Intrinsic::uadd_with_overflow: -      case Intrinsic::usub_with_overflow: -      case Intrinsic::umul_with_overflow: -      case Intrinsic::sadd_sat: -      case Intrinsic::uadd_sat: -      case Intrinsic::ssub_sat: -      case Intrinsic::usub_sat: -        return false;        case Intrinsic::sshl_sat:        case Intrinsic::ushl_sat: -        return includesPoison(Kind) && -               !shiftAmountKnownInRange(II->getArgOperand(1)); -      case Intrinsic::fma: -      case Intrinsic::fmuladd: -      case Intrinsic::sqrt: -      case Intrinsic::powi: -      case Intrinsic::sin: -      case Intrinsic::cos: -      case Intrinsic::pow: -      case Intrinsic::log: -      case Intrinsic::log10: -      case Intrinsic::log2: -      case Intrinsic::exp: -      case Intrinsic::exp2: -      case Intrinsic::exp10: -      case Intrinsic::fabs: -      case Intrinsic::copysign: -      case Intrinsic::floor: -      case Intrinsic::ceil: -      case Intrinsic::trunc: -      case Intrinsic::rint: -      case Intrinsic::nearbyint: -      case Intrinsic::round: -      case Intrinsic::roundeven: -      case Intrinsic::fptrunc_round: -      case Intrinsic::canonicalize: -      case Intrinsic::arithmetic_fence: -      case Intrinsic::minnum: -      case Intrinsic::maxnum: -      case Intrinsic::minimum: -      case Intrinsic::maximum: -      case Intrinsic::minimumnum: -      case Intrinsic::maximumnum: -      case Intrinsic::is_fpclass: -      case Intrinsic::ldexp: -      case Intrinsic::frexp: -        return false; -      case Intrinsic::lround: -      case Intrinsic::llround: -      case Intrinsic::lrint: -      case Intrinsic::llrint: -        // If the value doesn't fit an unspecified value is returned (but this -        // is not poison). -        return false; +        if (!includesPoison(Kind) || +            shiftAmountKnownInRange(II->getArgOperand(1))) +          return false; +        break;        }      }      [[fallthrough]];    case Instruction::CallBr:    case Instruction::Invoke: {      const auto *CB = cast<CallBase>(Op); -    return !CB->hasRetAttr(Attribute::NoUndef); +    return !CB->hasRetAttr(Attribute::NoUndef) && +           !CB->hasFnAttr(Attribute::NoCreateUndefOrPoison);    }    case Instruction::InsertElement:    case Instruction::ExtractElement: {  | 
