diff options
Diffstat (limited to 'llvm/lib/Transforms/Utils')
| -rw-r--r-- | llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp | 54 | 
1 files changed, 38 insertions, 16 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp b/llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp index 58e42074f96..13f33277ff1 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollPeel.cpp @@ -212,14 +212,11 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount,      const SCEVAddRecExpr *LeftAR = cast<SCEVAddRecExpr>(LeftSCEV);      // Avoid huge SCEV computations in the loop below, make sure we only -    // consider AddRecs of the loop we are trying to peel and avoid -    // non-monotonic predicates, as we will not be able to simplify the loop -    // body. -    // FIXME: For the non-monotonic predicates ICMP_EQ and ICMP_NE we can -    //        simplify the loop, if we peel 1 additional iteration, if there -    //        is no wrapping. +    // consider AddRecs of the loop we are trying to peel. +    if (!LeftAR->isAffine() || LeftAR->getLoop() != &L) +      continue;      bool Increasing; -    if (!LeftAR->isAffine() || LeftAR->getLoop() != &L || +    if (!(ICmpInst::isEquality(Pred) && LeftAR->hasNoSelfWrap()) &&          !SE.isMonotonicPredicate(LeftAR, Pred, Increasing))        continue;      (void)Increasing; @@ -238,18 +235,43 @@ static unsigned countToEliminateCompares(Loop &L, unsigned MaxPeelCount,        Pred = ICmpInst::getInversePredicate(Pred);      const SCEV *Step = LeftAR->getStepRecurrence(SE); -    while (NewPeelCount < MaxPeelCount && -           SE.isKnownPredicate(Pred, IterVal, RightSCEV)) { -      IterVal = SE.getAddExpr(IterVal, Step); +    const SCEV *NextIterVal = SE.getAddExpr(IterVal, Step); +    auto PeelOneMoreIteration = [&IterVal, &NextIterVal, &SE, Step, +                                 &NewPeelCount]() { +      IterVal = NextIterVal; +      NextIterVal = SE.getAddExpr(IterVal, Step);        NewPeelCount++; +    }; + +    auto CanPeelOneMoreIteration = [&NewPeelCount, &MaxPeelCount]() { +      return NewPeelCount < MaxPeelCount; +    }; + +    while (CanPeelOneMoreIteration() && +           SE.isKnownPredicate(Pred, IterVal, RightSCEV)) +      PeelOneMoreIteration(); + +    // With *that* peel count, does the predicate !Pred become known in the +    // first iteration of the loop body after peeling? +    if (!SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), IterVal, +                             RightSCEV)) +      continue; // If not, give up. + +    // However, for equality comparisons, that isn't always sufficient to +    // eliminate the comparsion in loop body, we may need to peel one more +    // iteration. See if that makes !Pred become unknown again. +    if (ICmpInst::isEquality(Pred) && +        !SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), NextIterVal, +                             RightSCEV)) { +      assert(!SE.isKnownPredicate(Pred, IterVal, RightSCEV) && +             SE.isKnownPredicate(Pred, NextIterVal, RightSCEV) && +             "Expected Pred to go from known to unknown."); +      if (!CanPeelOneMoreIteration()) +        continue; // Need to peel one more iteration, but can't. Give up. +      PeelOneMoreIteration(); // Great!      } -    // Only peel the loop if the monotonic predicate !Pred becomes known in the -    // first iteration of the loop body after peeling. -    if (NewPeelCount > DesiredPeelCount && -        SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), IterVal, -                            RightSCEV)) -      DesiredPeelCount = NewPeelCount; +    DesiredPeelCount = std::max(DesiredPeelCount, NewPeelCount);    }    return DesiredPeelCount;  | 

