18fb3d57eSArtur Pilipenko //===-- LoopPredication.cpp - Guard based loop predication pass -----------===//
28fb3d57eSArtur Pilipenko //
38fb3d57eSArtur Pilipenko //                     The LLVM Compiler Infrastructure
48fb3d57eSArtur Pilipenko //
58fb3d57eSArtur Pilipenko // This file is distributed under the University of Illinois Open Source
68fb3d57eSArtur Pilipenko // License. See LICENSE.TXT for details.
78fb3d57eSArtur Pilipenko //
88fb3d57eSArtur Pilipenko //===----------------------------------------------------------------------===//
98fb3d57eSArtur Pilipenko //
108fb3d57eSArtur Pilipenko // The LoopPredication pass tries to convert loop variant range checks to loop
118fb3d57eSArtur Pilipenko // invariant by widening checks across loop iterations. For example, it will
128fb3d57eSArtur Pilipenko // convert
138fb3d57eSArtur Pilipenko //
148fb3d57eSArtur Pilipenko //   for (i = 0; i < n; i++) {
158fb3d57eSArtur Pilipenko //     guard(i < len);
168fb3d57eSArtur Pilipenko //     ...
178fb3d57eSArtur Pilipenko //   }
188fb3d57eSArtur Pilipenko //
198fb3d57eSArtur Pilipenko // to
208fb3d57eSArtur Pilipenko //
218fb3d57eSArtur Pilipenko //   for (i = 0; i < n; i++) {
228fb3d57eSArtur Pilipenko //     guard(n - 1 < len);
238fb3d57eSArtur Pilipenko //     ...
248fb3d57eSArtur Pilipenko //   }
258fb3d57eSArtur Pilipenko //
268fb3d57eSArtur Pilipenko // After this transformation the condition of the guard is loop invariant, so
278fb3d57eSArtur Pilipenko // loop-unswitch can later unswitch the loop by this condition which basically
288fb3d57eSArtur Pilipenko // predicates the loop by the widened condition:
298fb3d57eSArtur Pilipenko //
308fb3d57eSArtur Pilipenko //   if (n - 1 < len)
318fb3d57eSArtur Pilipenko //     for (i = 0; i < n; i++) {
328fb3d57eSArtur Pilipenko //       ...
338fb3d57eSArtur Pilipenko //     }
348fb3d57eSArtur Pilipenko //   else
358fb3d57eSArtur Pilipenko //     deoptimize
368fb3d57eSArtur Pilipenko //
378fb3d57eSArtur Pilipenko //===----------------------------------------------------------------------===//
388fb3d57eSArtur Pilipenko 
398fb3d57eSArtur Pilipenko #include "llvm/Transforms/Scalar/LoopPredication.h"
408fb3d57eSArtur Pilipenko #include "llvm/Pass.h"
418fb3d57eSArtur Pilipenko #include "llvm/Analysis/LoopInfo.h"
428fb3d57eSArtur Pilipenko #include "llvm/Analysis/LoopPass.h"
438fb3d57eSArtur Pilipenko #include "llvm/Analysis/ScalarEvolution.h"
448fb3d57eSArtur Pilipenko #include "llvm/Analysis/ScalarEvolutionExpander.h"
458fb3d57eSArtur Pilipenko #include "llvm/Analysis/ScalarEvolutionExpressions.h"
468fb3d57eSArtur Pilipenko #include "llvm/IR/Function.h"
478fb3d57eSArtur Pilipenko #include "llvm/IR/GlobalValue.h"
488fb3d57eSArtur Pilipenko #include "llvm/IR/IntrinsicInst.h"
498fb3d57eSArtur Pilipenko #include "llvm/IR/Module.h"
508fb3d57eSArtur Pilipenko #include "llvm/IR/PatternMatch.h"
518fb3d57eSArtur Pilipenko #include "llvm/Support/Debug.h"
528fb3d57eSArtur Pilipenko #include "llvm/Transforms/Scalar.h"
538fb3d57eSArtur Pilipenko #include "llvm/Transforms/Utils/LoopUtils.h"
548fb3d57eSArtur Pilipenko 
558fb3d57eSArtur Pilipenko #define DEBUG_TYPE "loop-predication"
568fb3d57eSArtur Pilipenko 
578fb3d57eSArtur Pilipenko using namespace llvm;
588fb3d57eSArtur Pilipenko 
598fb3d57eSArtur Pilipenko namespace {
608fb3d57eSArtur Pilipenko class LoopPredication {
61a6c27804SArtur Pilipenko   /// Represents an induction variable check:
62a6c27804SArtur Pilipenko   ///   icmp Pred, <induction variable>, <loop invariant limit>
63a6c27804SArtur Pilipenko   struct LoopICmp {
64a6c27804SArtur Pilipenko     ICmpInst::Predicate Pred;
65a6c27804SArtur Pilipenko     const SCEVAddRecExpr *IV;
66a6c27804SArtur Pilipenko     const SCEV *Limit;
67*c488dfabSArtur Pilipenko     LoopICmp(ICmpInst::Predicate Pred, const SCEVAddRecExpr *IV,
68*c488dfabSArtur Pilipenko              const SCEV *Limit)
69a6c27804SArtur Pilipenko         : Pred(Pred), IV(IV), Limit(Limit) {}
70a6c27804SArtur Pilipenko     LoopICmp() {}
71a6c27804SArtur Pilipenko   };
72*c488dfabSArtur Pilipenko 
73*c488dfabSArtur Pilipenko   ScalarEvolution *SE;
74*c488dfabSArtur Pilipenko 
75*c488dfabSArtur Pilipenko   Loop *L;
76*c488dfabSArtur Pilipenko   const DataLayout *DL;
77*c488dfabSArtur Pilipenko   BasicBlock *Preheader;
78*c488dfabSArtur Pilipenko 
79a6c27804SArtur Pilipenko   Optional<LoopICmp> parseLoopICmp(ICmpInst *ICI);
80a6c27804SArtur Pilipenko 
816780ba65SArtur Pilipenko   Value *expandCheck(SCEVExpander &Expander, IRBuilder<> &Builder,
826780ba65SArtur Pilipenko                      ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS,
836780ba65SArtur Pilipenko                      Instruction *InsertAt);
846780ba65SArtur Pilipenko 
858fb3d57eSArtur Pilipenko   Optional<Value *> widenICmpRangeCheck(ICmpInst *ICI, SCEVExpander &Expander,
868fb3d57eSArtur Pilipenko                                         IRBuilder<> &Builder);
878fb3d57eSArtur Pilipenko   bool widenGuardConditions(IntrinsicInst *II, SCEVExpander &Expander);
888fb3d57eSArtur Pilipenko 
898fb3d57eSArtur Pilipenko public:
908fb3d57eSArtur Pilipenko   LoopPredication(ScalarEvolution *SE) : SE(SE){};
918fb3d57eSArtur Pilipenko   bool runOnLoop(Loop *L);
928fb3d57eSArtur Pilipenko };
938fb3d57eSArtur Pilipenko 
948fb3d57eSArtur Pilipenko class LoopPredicationLegacyPass : public LoopPass {
958fb3d57eSArtur Pilipenko public:
968fb3d57eSArtur Pilipenko   static char ID;
978fb3d57eSArtur Pilipenko   LoopPredicationLegacyPass() : LoopPass(ID) {
988fb3d57eSArtur Pilipenko     initializeLoopPredicationLegacyPassPass(*PassRegistry::getPassRegistry());
998fb3d57eSArtur Pilipenko   }
1008fb3d57eSArtur Pilipenko 
1018fb3d57eSArtur Pilipenko   void getAnalysisUsage(AnalysisUsage &AU) const override {
1028fb3d57eSArtur Pilipenko     getLoopAnalysisUsage(AU);
1038fb3d57eSArtur Pilipenko   }
1048fb3d57eSArtur Pilipenko 
1058fb3d57eSArtur Pilipenko   bool runOnLoop(Loop *L, LPPassManager &LPM) override {
1068fb3d57eSArtur Pilipenko     if (skipLoop(L))
1078fb3d57eSArtur Pilipenko       return false;
1088fb3d57eSArtur Pilipenko     auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1098fb3d57eSArtur Pilipenko     LoopPredication LP(SE);
1108fb3d57eSArtur Pilipenko     return LP.runOnLoop(L);
1118fb3d57eSArtur Pilipenko   }
1128fb3d57eSArtur Pilipenko };
1138fb3d57eSArtur Pilipenko 
1148fb3d57eSArtur Pilipenko char LoopPredicationLegacyPass::ID = 0;
1158fb3d57eSArtur Pilipenko } // end namespace llvm
1168fb3d57eSArtur Pilipenko 
1178fb3d57eSArtur Pilipenko INITIALIZE_PASS_BEGIN(LoopPredicationLegacyPass, "loop-predication",
1188fb3d57eSArtur Pilipenko                       "Loop predication", false, false)
1198fb3d57eSArtur Pilipenko INITIALIZE_PASS_DEPENDENCY(LoopPass)
1208fb3d57eSArtur Pilipenko INITIALIZE_PASS_END(LoopPredicationLegacyPass, "loop-predication",
1218fb3d57eSArtur Pilipenko                     "Loop predication", false, false)
1228fb3d57eSArtur Pilipenko 
1238fb3d57eSArtur Pilipenko Pass *llvm::createLoopPredicationPass() {
1248fb3d57eSArtur Pilipenko   return new LoopPredicationLegacyPass();
1258fb3d57eSArtur Pilipenko }
1268fb3d57eSArtur Pilipenko 
1278fb3d57eSArtur Pilipenko PreservedAnalyses LoopPredicationPass::run(Loop &L, LoopAnalysisManager &AM,
1288fb3d57eSArtur Pilipenko                                            LoopStandardAnalysisResults &AR,
1298fb3d57eSArtur Pilipenko                                            LPMUpdater &U) {
1308fb3d57eSArtur Pilipenko   LoopPredication LP(&AR.SE);
1318fb3d57eSArtur Pilipenko   if (!LP.runOnLoop(&L))
1328fb3d57eSArtur Pilipenko     return PreservedAnalyses::all();
1338fb3d57eSArtur Pilipenko 
1348fb3d57eSArtur Pilipenko   return getLoopPassPreservedAnalyses();
1358fb3d57eSArtur Pilipenko }
1368fb3d57eSArtur Pilipenko 
137a6c27804SArtur Pilipenko Optional<LoopPredication::LoopICmp>
138a6c27804SArtur Pilipenko LoopPredication::parseLoopICmp(ICmpInst *ICI) {
139a6c27804SArtur Pilipenko   ICmpInst::Predicate Pred = ICI->getPredicate();
140a6c27804SArtur Pilipenko 
141a6c27804SArtur Pilipenko   Value *LHS = ICI->getOperand(0);
142a6c27804SArtur Pilipenko   Value *RHS = ICI->getOperand(1);
143a6c27804SArtur Pilipenko   const SCEV *LHSS = SE->getSCEV(LHS);
144a6c27804SArtur Pilipenko   if (isa<SCEVCouldNotCompute>(LHSS))
145a6c27804SArtur Pilipenko     return None;
146a6c27804SArtur Pilipenko   const SCEV *RHSS = SE->getSCEV(RHS);
147a6c27804SArtur Pilipenko   if (isa<SCEVCouldNotCompute>(RHSS))
148a6c27804SArtur Pilipenko     return None;
149a6c27804SArtur Pilipenko 
150a6c27804SArtur Pilipenko   // Canonicalize RHS to be loop invariant bound, LHS - a loop computable IV
151a6c27804SArtur Pilipenko   if (SE->isLoopInvariant(LHSS, L)) {
152a6c27804SArtur Pilipenko     std::swap(LHS, RHS);
153a6c27804SArtur Pilipenko     std::swap(LHSS, RHSS);
154a6c27804SArtur Pilipenko     Pred = ICmpInst::getSwappedPredicate(Pred);
155a6c27804SArtur Pilipenko   }
156a6c27804SArtur Pilipenko 
157a6c27804SArtur Pilipenko   const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(LHSS);
158a6c27804SArtur Pilipenko   if (!AR || AR->getLoop() != L)
159a6c27804SArtur Pilipenko     return None;
160a6c27804SArtur Pilipenko 
161a6c27804SArtur Pilipenko   return LoopICmp(Pred, AR, RHSS);
162a6c27804SArtur Pilipenko }
163a6c27804SArtur Pilipenko 
1646780ba65SArtur Pilipenko Value *LoopPredication::expandCheck(SCEVExpander &Expander,
1656780ba65SArtur Pilipenko                                     IRBuilder<> &Builder,
1666780ba65SArtur Pilipenko                                     ICmpInst::Predicate Pred, const SCEV *LHS,
1676780ba65SArtur Pilipenko                                     const SCEV *RHS, Instruction *InsertAt) {
1686780ba65SArtur Pilipenko   Type *Ty = LHS->getType();
1696780ba65SArtur Pilipenko   assert(Ty == RHS->getType() && "expandCheck operands have different types?");
1706780ba65SArtur Pilipenko   Value *LHSV = Expander.expandCodeFor(LHS, Ty, InsertAt);
1716780ba65SArtur Pilipenko   Value *RHSV = Expander.expandCodeFor(RHS, Ty, InsertAt);
1726780ba65SArtur Pilipenko   return Builder.CreateICmp(Pred, LHSV, RHSV);
1736780ba65SArtur Pilipenko }
1746780ba65SArtur Pilipenko 
1758fb3d57eSArtur Pilipenko /// If ICI can be widened to a loop invariant condition emits the loop
1768fb3d57eSArtur Pilipenko /// invariant condition in the loop preheader and return it, otherwise
1778fb3d57eSArtur Pilipenko /// returns None.
1788fb3d57eSArtur Pilipenko Optional<Value *> LoopPredication::widenICmpRangeCheck(ICmpInst *ICI,
1798fb3d57eSArtur Pilipenko                                                        SCEVExpander &Expander,
1808fb3d57eSArtur Pilipenko                                                        IRBuilder<> &Builder) {
1818fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "Analyzing ICmpInst condition:\n");
1828fb3d57eSArtur Pilipenko   DEBUG(ICI->dump());
1838fb3d57eSArtur Pilipenko 
184a6c27804SArtur Pilipenko   auto RangeCheck = parseLoopICmp(ICI);
185a6c27804SArtur Pilipenko   if (!RangeCheck)
1868fb3d57eSArtur Pilipenko     return None;
1878fb3d57eSArtur Pilipenko 
188a6c27804SArtur Pilipenko   ICmpInst::Predicate Pred = RangeCheck->Pred;
189a6c27804SArtur Pilipenko   const SCEVAddRecExpr *IndexAR = RangeCheck->IV;
190a6c27804SArtur Pilipenko   const SCEV *RHSS = RangeCheck->Limit;
191aab28666SArtur Pilipenko 
192aab28666SArtur Pilipenko   auto CanExpand = [this](const SCEV *S) {
193aab28666SArtur Pilipenko     return SE->isLoopInvariant(S, L) && isSafeToExpand(S, *SE);
194aab28666SArtur Pilipenko   };
195aab28666SArtur Pilipenko   if (!CanExpand(RHSS))
1968fb3d57eSArtur Pilipenko     return None;
1978fb3d57eSArtur Pilipenko 
1988fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "IndexAR: ");
1998fb3d57eSArtur Pilipenko   DEBUG(IndexAR->dump());
2008fb3d57eSArtur Pilipenko 
2018fb3d57eSArtur Pilipenko   bool IsIncreasing = false;
2028fb3d57eSArtur Pilipenko   if (!SE->isMonotonicPredicate(IndexAR, Pred, IsIncreasing))
2038fb3d57eSArtur Pilipenko     return None;
2048fb3d57eSArtur Pilipenko 
2058fb3d57eSArtur Pilipenko   // If the predicate is increasing the condition can change from false to true
2068fb3d57eSArtur Pilipenko   // as the loop progresses, in this case take the value on the first iteration
2078fb3d57eSArtur Pilipenko   // for the widened check. Otherwise the condition can change from true to
2088fb3d57eSArtur Pilipenko   // false as the loop progresses, so take the value on the last iteration.
2098fb3d57eSArtur Pilipenko   const SCEV *NewLHSS = IsIncreasing
2108fb3d57eSArtur Pilipenko                             ? IndexAR->getStart()
2118fb3d57eSArtur Pilipenko                             : SE->getSCEVAtScope(IndexAR, L->getParentLoop());
2128fb3d57eSArtur Pilipenko   if (NewLHSS == IndexAR) {
2132cbaded5SArtur Pilipenko     DEBUG(dbgs() << "Can't compute NewLHSS!\n");
2148fb3d57eSArtur Pilipenko     return None;
2158fb3d57eSArtur Pilipenko   }
2168fb3d57eSArtur Pilipenko 
2178fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "NewLHSS: ");
2188fb3d57eSArtur Pilipenko   DEBUG(NewLHSS->dump());
2198fb3d57eSArtur Pilipenko 
220aab28666SArtur Pilipenko   if (!CanExpand(NewLHSS))
2218fb3d57eSArtur Pilipenko     return None;
2228fb3d57eSArtur Pilipenko 
2238fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "NewLHSS is loop invariant and safe to expand. Expand!\n");
2248fb3d57eSArtur Pilipenko 
2250860bfc6SArtur Pilipenko   Instruction *InsertAt = Preheader->getTerminator();
2266780ba65SArtur Pilipenko   return expandCheck(Expander, Builder, Pred, NewLHSS, RHSS, InsertAt);
2278fb3d57eSArtur Pilipenko }
2288fb3d57eSArtur Pilipenko 
2298fb3d57eSArtur Pilipenko bool LoopPredication::widenGuardConditions(IntrinsicInst *Guard,
2308fb3d57eSArtur Pilipenko                                            SCEVExpander &Expander) {
2318fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "Processing guard:\n");
2328fb3d57eSArtur Pilipenko   DEBUG(Guard->dump());
2338fb3d57eSArtur Pilipenko 
2348fb3d57eSArtur Pilipenko   IRBuilder<> Builder(cast<Instruction>(Preheader->getTerminator()));
2358fb3d57eSArtur Pilipenko 
2368fb3d57eSArtur Pilipenko   // The guard condition is expected to be in form of:
2378fb3d57eSArtur Pilipenko   //   cond1 && cond2 && cond3 ...
2388fb3d57eSArtur Pilipenko   // Iterate over subconditions looking for for icmp conditions which can be
2398fb3d57eSArtur Pilipenko   // widened across loop iterations. Widening these conditions remember the
2408fb3d57eSArtur Pilipenko   // resulting list of subconditions in Checks vector.
2418fb3d57eSArtur Pilipenko   SmallVector<Value *, 4> Worklist(1, Guard->getOperand(0));
2428fb3d57eSArtur Pilipenko   SmallPtrSet<Value *, 4> Visited;
2438fb3d57eSArtur Pilipenko 
2448fb3d57eSArtur Pilipenko   SmallVector<Value *, 4> Checks;
2458fb3d57eSArtur Pilipenko 
2468fb3d57eSArtur Pilipenko   unsigned NumWidened = 0;
2478fb3d57eSArtur Pilipenko   do {
2488fb3d57eSArtur Pilipenko     Value *Condition = Worklist.pop_back_val();
2498fb3d57eSArtur Pilipenko     if (!Visited.insert(Condition).second)
2508fb3d57eSArtur Pilipenko       continue;
2518fb3d57eSArtur Pilipenko 
2528fb3d57eSArtur Pilipenko     Value *LHS, *RHS;
2538fb3d57eSArtur Pilipenko     using namespace llvm::PatternMatch;
2548fb3d57eSArtur Pilipenko     if (match(Condition, m_And(m_Value(LHS), m_Value(RHS)))) {
2558fb3d57eSArtur Pilipenko       Worklist.push_back(LHS);
2568fb3d57eSArtur Pilipenko       Worklist.push_back(RHS);
2578fb3d57eSArtur Pilipenko       continue;
2588fb3d57eSArtur Pilipenko     }
2598fb3d57eSArtur Pilipenko 
2608fb3d57eSArtur Pilipenko     if (ICmpInst *ICI = dyn_cast<ICmpInst>(Condition)) {
2618fb3d57eSArtur Pilipenko       if (auto NewRangeCheck = widenICmpRangeCheck(ICI, Expander, Builder)) {
2628fb3d57eSArtur Pilipenko         Checks.push_back(NewRangeCheck.getValue());
2638fb3d57eSArtur Pilipenko         NumWidened++;
2648fb3d57eSArtur Pilipenko         continue;
2658fb3d57eSArtur Pilipenko       }
2668fb3d57eSArtur Pilipenko     }
2678fb3d57eSArtur Pilipenko 
2688fb3d57eSArtur Pilipenko     // Save the condition as is if we can't widen it
2698fb3d57eSArtur Pilipenko     Checks.push_back(Condition);
2708fb3d57eSArtur Pilipenko   } while (Worklist.size() != 0);
2718fb3d57eSArtur Pilipenko 
2728fb3d57eSArtur Pilipenko   if (NumWidened == 0)
2738fb3d57eSArtur Pilipenko     return false;
2748fb3d57eSArtur Pilipenko 
2758fb3d57eSArtur Pilipenko   // Emit the new guard condition
2768fb3d57eSArtur Pilipenko   Builder.SetInsertPoint(Guard);
2778fb3d57eSArtur Pilipenko   Value *LastCheck = nullptr;
2788fb3d57eSArtur Pilipenko   for (auto *Check : Checks)
2798fb3d57eSArtur Pilipenko     if (!LastCheck)
2808fb3d57eSArtur Pilipenko       LastCheck = Check;
2818fb3d57eSArtur Pilipenko     else
2828fb3d57eSArtur Pilipenko       LastCheck = Builder.CreateAnd(LastCheck, Check);
2838fb3d57eSArtur Pilipenko   Guard->setOperand(0, LastCheck);
2848fb3d57eSArtur Pilipenko 
2858fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "Widened checks = " << NumWidened << "\n");
2868fb3d57eSArtur Pilipenko   return true;
2878fb3d57eSArtur Pilipenko }
2888fb3d57eSArtur Pilipenko 
2898fb3d57eSArtur Pilipenko bool LoopPredication::runOnLoop(Loop *Loop) {
2908fb3d57eSArtur Pilipenko   L = Loop;
2918fb3d57eSArtur Pilipenko 
2928fb3d57eSArtur Pilipenko   DEBUG(dbgs() << "Analyzing ");
2938fb3d57eSArtur Pilipenko   DEBUG(L->dump());
2948fb3d57eSArtur Pilipenko 
2958fb3d57eSArtur Pilipenko   Module *M = L->getHeader()->getModule();
2968fb3d57eSArtur Pilipenko 
2978fb3d57eSArtur Pilipenko   // There is nothing to do if the module doesn't use guards
2988fb3d57eSArtur Pilipenko   auto *GuardDecl =
2998fb3d57eSArtur Pilipenko       M->getFunction(Intrinsic::getName(Intrinsic::experimental_guard));
3008fb3d57eSArtur Pilipenko   if (!GuardDecl || GuardDecl->use_empty())
3018fb3d57eSArtur Pilipenko     return false;
3028fb3d57eSArtur Pilipenko 
3038fb3d57eSArtur Pilipenko   DL = &M->getDataLayout();
3048fb3d57eSArtur Pilipenko 
3058fb3d57eSArtur Pilipenko   Preheader = L->getLoopPreheader();
3068fb3d57eSArtur Pilipenko   if (!Preheader)
3078fb3d57eSArtur Pilipenko     return false;
3088fb3d57eSArtur Pilipenko 
3098fb3d57eSArtur Pilipenko   // Collect all the guards into a vector and process later, so as not
3108fb3d57eSArtur Pilipenko   // to invalidate the instruction iterator.
3118fb3d57eSArtur Pilipenko   SmallVector<IntrinsicInst *, 4> Guards;
3128fb3d57eSArtur Pilipenko   for (const auto BB : L->blocks())
3138fb3d57eSArtur Pilipenko     for (auto &I : *BB)
3148fb3d57eSArtur Pilipenko       if (auto *II = dyn_cast<IntrinsicInst>(&I))
3158fb3d57eSArtur Pilipenko         if (II->getIntrinsicID() == Intrinsic::experimental_guard)
3168fb3d57eSArtur Pilipenko           Guards.push_back(II);
3178fb3d57eSArtur Pilipenko 
31846c4e0a4SArtur Pilipenko   if (Guards.empty())
31946c4e0a4SArtur Pilipenko     return false;
32046c4e0a4SArtur Pilipenko 
3218fb3d57eSArtur Pilipenko   SCEVExpander Expander(*SE, *DL, "loop-predication");
3228fb3d57eSArtur Pilipenko 
3238fb3d57eSArtur Pilipenko   bool Changed = false;
3248fb3d57eSArtur Pilipenko   for (auto *Guard : Guards)
3258fb3d57eSArtur Pilipenko     Changed |= widenGuardConditions(Guard, Expander);
3268fb3d57eSArtur Pilipenko 
3278fb3d57eSArtur Pilipenko   return Changed;
3288fb3d57eSArtur Pilipenko }
329