1ff0cc061SDimitry Andric //===-- LoopUtils.cpp - Loop Utility functions -------------------------===//
2ff0cc061SDimitry Andric //
3ff0cc061SDimitry Andric // The LLVM Compiler Infrastructure
4ff0cc061SDimitry Andric //
5ff0cc061SDimitry Andric // This file is distributed under the University of Illinois Open Source
6ff0cc061SDimitry Andric // License. See LICENSE.TXT for details.
7ff0cc061SDimitry Andric //
8ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
9ff0cc061SDimitry Andric //
10ff0cc061SDimitry Andric // This file defines common loop utility functions.
11ff0cc061SDimitry Andric //
12ff0cc061SDimitry Andric //===----------------------------------------------------------------------===//
13ff0cc061SDimitry Andric
14d88c1a5aSDimitry Andric #include "llvm/Transforms/Utils/LoopUtils.h"
15edd7eaddSDimitry Andric #include "llvm/ADT/ScopeExit.h"
163ca95b02SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
173ca95b02SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h"
183ca95b02SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
194ba319b5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
20d88c1a5aSDimitry Andric #include "llvm/Analysis/LoopInfo.h"
21d88c1a5aSDimitry Andric #include "llvm/Analysis/LoopPass.h"
224ba319b5SDimitry Andric #include "llvm/Analysis/MustExecute.h"
237d523365SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h"
24d88c1a5aSDimitry Andric #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
253ca95b02SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpander.h"
267d523365SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h"
27db17bf38SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
284f8786afSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
29*b5893f02SDimitry Andric #include "llvm/IR/DIBuilder.h"
30*b5893f02SDimitry Andric #include "llvm/IR/DomTreeUpdater.h"
313ca95b02SDimitry Andric #include "llvm/IR/Dominators.h"
32ff0cc061SDimitry Andric #include "llvm/IR/Instructions.h"
33*b5893f02SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
347d523365SDimitry Andric #include "llvm/IR/Module.h"
35ff0cc061SDimitry Andric #include "llvm/IR/PatternMatch.h"
36ff0cc061SDimitry Andric #include "llvm/IR/ValueHandle.h"
373ca95b02SDimitry Andric #include "llvm/Pass.h"
38ff0cc061SDimitry Andric #include "llvm/Support/Debug.h"
394f8786afSDimitry Andric #include "llvm/Support/KnownBits.h"
40edd7eaddSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
41ff0cc061SDimitry Andric
42ff0cc061SDimitry Andric using namespace llvm;
43ff0cc061SDimitry Andric using namespace llvm::PatternMatch;
44ff0cc061SDimitry Andric
45ff0cc061SDimitry Andric #define DEBUG_TYPE "loop-utils"
46ff0cc061SDimitry Andric
47*b5893f02SDimitry Andric static const char *LLVMLoopDisableNonforced = "llvm.loop.disable_nonforced";
487d523365SDimitry Andric
formDedicatedExitBlocks(Loop * L,DominatorTree * DT,LoopInfo * LI,bool PreserveLCSSA)49edd7eaddSDimitry Andric bool llvm::formDedicatedExitBlocks(Loop *L, DominatorTree *DT, LoopInfo *LI,
50edd7eaddSDimitry Andric bool PreserveLCSSA) {
51edd7eaddSDimitry Andric bool Changed = false;
52edd7eaddSDimitry Andric
53edd7eaddSDimitry Andric // We re-use a vector for the in-loop predecesosrs.
54edd7eaddSDimitry Andric SmallVector<BasicBlock *, 4> InLoopPredecessors;
55edd7eaddSDimitry Andric
56edd7eaddSDimitry Andric auto RewriteExit = [&](BasicBlock *BB) {
57edd7eaddSDimitry Andric assert(InLoopPredecessors.empty() &&
58edd7eaddSDimitry Andric "Must start with an empty predecessors list!");
59edd7eaddSDimitry Andric auto Cleanup = make_scope_exit([&] { InLoopPredecessors.clear(); });
60edd7eaddSDimitry Andric
61edd7eaddSDimitry Andric // See if there are any non-loop predecessors of this exit block and
62edd7eaddSDimitry Andric // keep track of the in-loop predecessors.
63edd7eaddSDimitry Andric bool IsDedicatedExit = true;
64edd7eaddSDimitry Andric for (auto *PredBB : predecessors(BB))
65edd7eaddSDimitry Andric if (L->contains(PredBB)) {
66edd7eaddSDimitry Andric if (isa<IndirectBrInst>(PredBB->getTerminator()))
67edd7eaddSDimitry Andric // We cannot rewrite exiting edges from an indirectbr.
68edd7eaddSDimitry Andric return false;
69edd7eaddSDimitry Andric
70edd7eaddSDimitry Andric InLoopPredecessors.push_back(PredBB);
71edd7eaddSDimitry Andric } else {
72edd7eaddSDimitry Andric IsDedicatedExit = false;
73edd7eaddSDimitry Andric }
74edd7eaddSDimitry Andric
75edd7eaddSDimitry Andric assert(!InLoopPredecessors.empty() && "Must have *some* loop predecessor!");
76edd7eaddSDimitry Andric
77edd7eaddSDimitry Andric // Nothing to do if this is already a dedicated exit.
78edd7eaddSDimitry Andric if (IsDedicatedExit)
79edd7eaddSDimitry Andric return false;
80edd7eaddSDimitry Andric
81edd7eaddSDimitry Andric auto *NewExitBB = SplitBlockPredecessors(
82*b5893f02SDimitry Andric BB, InLoopPredecessors, ".loopexit", DT, LI, nullptr, PreserveLCSSA);
83edd7eaddSDimitry Andric
84edd7eaddSDimitry Andric if (!NewExitBB)
854ba319b5SDimitry Andric LLVM_DEBUG(
864ba319b5SDimitry Andric dbgs() << "WARNING: Can't create a dedicated exit block for loop: "
87edd7eaddSDimitry Andric << *L << "\n");
88edd7eaddSDimitry Andric else
894ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "
90edd7eaddSDimitry Andric << NewExitBB->getName() << "\n");
91edd7eaddSDimitry Andric return true;
92edd7eaddSDimitry Andric };
93edd7eaddSDimitry Andric
94edd7eaddSDimitry Andric // Walk the exit blocks directly rather than building up a data structure for
95edd7eaddSDimitry Andric // them, but only visit each one once.
96edd7eaddSDimitry Andric SmallPtrSet<BasicBlock *, 4> Visited;
97edd7eaddSDimitry Andric for (auto *BB : L->blocks())
98edd7eaddSDimitry Andric for (auto *SuccBB : successors(BB)) {
99edd7eaddSDimitry Andric // We're looking for exit blocks so skip in-loop successors.
100edd7eaddSDimitry Andric if (L->contains(SuccBB))
101edd7eaddSDimitry Andric continue;
102edd7eaddSDimitry Andric
103edd7eaddSDimitry Andric // Visit each exit block exactly once.
104edd7eaddSDimitry Andric if (!Visited.insert(SuccBB).second)
105edd7eaddSDimitry Andric continue;
106edd7eaddSDimitry Andric
107edd7eaddSDimitry Andric Changed |= RewriteExit(SuccBB);
108edd7eaddSDimitry Andric }
109edd7eaddSDimitry Andric
110edd7eaddSDimitry Andric return Changed;
111edd7eaddSDimitry Andric }
112edd7eaddSDimitry Andric
1134ba319b5SDimitry Andric /// Returns the instructions that use values defined in the loop.
findDefsUsedOutsideOfLoop(Loop * L)1147d523365SDimitry Andric SmallVector<Instruction *, 8> llvm::findDefsUsedOutsideOfLoop(Loop *L) {
1157d523365SDimitry Andric SmallVector<Instruction *, 8> UsedOutside;
1167d523365SDimitry Andric
1177d523365SDimitry Andric for (auto *Block : L->getBlocks())
1187d523365SDimitry Andric // FIXME: I believe that this could use copy_if if the Inst reference could
1197d523365SDimitry Andric // be adapted into a pointer.
1207d523365SDimitry Andric for (auto &Inst : *Block) {
1217d523365SDimitry Andric auto Users = Inst.users();
122d88c1a5aSDimitry Andric if (any_of(Users, [&](User *U) {
1237d523365SDimitry Andric auto *Use = cast<Instruction>(U);
1247d523365SDimitry Andric return !L->contains(Use->getParent());
1257d523365SDimitry Andric }))
1267d523365SDimitry Andric UsedOutside.push_back(&Inst);
1277d523365SDimitry Andric }
1287d523365SDimitry Andric
1297d523365SDimitry Andric return UsedOutside;
1307d523365SDimitry Andric }
1313ca95b02SDimitry Andric
getLoopAnalysisUsage(AnalysisUsage & AU)1323ca95b02SDimitry Andric void llvm::getLoopAnalysisUsage(AnalysisUsage &AU) {
1333ca95b02SDimitry Andric // By definition, all loop passes need the LoopInfo analysis and the
1343ca95b02SDimitry Andric // Dominator tree it depends on. Because they all participate in the loop
1353ca95b02SDimitry Andric // pass manager, they must also preserve these.
1363ca95b02SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>();
1373ca95b02SDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>();
1383ca95b02SDimitry Andric AU.addRequired<LoopInfoWrapperPass>();
1393ca95b02SDimitry Andric AU.addPreserved<LoopInfoWrapperPass>();
1403ca95b02SDimitry Andric
1413ca95b02SDimitry Andric // We must also preserve LoopSimplify and LCSSA. We locally access their IDs
1423ca95b02SDimitry Andric // here because users shouldn't directly get them from this header.
1433ca95b02SDimitry Andric extern char &LoopSimplifyID;
1443ca95b02SDimitry Andric extern char &LCSSAID;
1453ca95b02SDimitry Andric AU.addRequiredID(LoopSimplifyID);
1463ca95b02SDimitry Andric AU.addPreservedID(LoopSimplifyID);
1473ca95b02SDimitry Andric AU.addRequiredID(LCSSAID);
1483ca95b02SDimitry Andric AU.addPreservedID(LCSSAID);
149d88c1a5aSDimitry Andric // This is used in the LPPassManager to perform LCSSA verification on passes
150d88c1a5aSDimitry Andric // which preserve lcssa form
151d88c1a5aSDimitry Andric AU.addRequired<LCSSAVerificationPass>();
152d88c1a5aSDimitry Andric AU.addPreserved<LCSSAVerificationPass>();
1533ca95b02SDimitry Andric
1543ca95b02SDimitry Andric // Loop passes are designed to run inside of a loop pass manager which means
1553ca95b02SDimitry Andric // that any function analyses they require must be required by the first loop
1563ca95b02SDimitry Andric // pass in the manager (so that it is computed before the loop pass manager
1573ca95b02SDimitry Andric // runs) and preserved by all loop pasess in the manager. To make this
1583ca95b02SDimitry Andric // reasonably robust, the set needed for most loop passes is maintained here.
1593ca95b02SDimitry Andric // If your loop pass requires an analysis not listed here, you will need to
1603ca95b02SDimitry Andric // carefully audit the loop pass manager nesting structure that results.
1613ca95b02SDimitry Andric AU.addRequired<AAResultsWrapperPass>();
1623ca95b02SDimitry Andric AU.addPreserved<AAResultsWrapperPass>();
1633ca95b02SDimitry Andric AU.addPreserved<BasicAAWrapperPass>();
1643ca95b02SDimitry Andric AU.addPreserved<GlobalsAAWrapperPass>();
1653ca95b02SDimitry Andric AU.addPreserved<SCEVAAWrapperPass>();
1663ca95b02SDimitry Andric AU.addRequired<ScalarEvolutionWrapperPass>();
1673ca95b02SDimitry Andric AU.addPreserved<ScalarEvolutionWrapperPass>();
1683ca95b02SDimitry Andric }
1693ca95b02SDimitry Andric
1703ca95b02SDimitry Andric /// Manually defined generic "LoopPass" dependency initialization. This is used
1713ca95b02SDimitry Andric /// to initialize the exact set of passes from above in \c
1723ca95b02SDimitry Andric /// getLoopAnalysisUsage. It can be used within a loop pass's initialization
1733ca95b02SDimitry Andric /// with:
1743ca95b02SDimitry Andric ///
1753ca95b02SDimitry Andric /// INITIALIZE_PASS_DEPENDENCY(LoopPass)
1763ca95b02SDimitry Andric ///
1773ca95b02SDimitry Andric /// As-if "LoopPass" were a pass.
initializeLoopPassPass(PassRegistry & Registry)1783ca95b02SDimitry Andric void llvm::initializeLoopPassPass(PassRegistry &Registry) {
1793ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
1803ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
1813ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
1823ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LCSSAWrapperPass)
1833ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
1843ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
1853ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
1863ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
1873ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
1883ca95b02SDimitry Andric }
1893ca95b02SDimitry Andric
1904ba319b5SDimitry Andric /// Find string metadata for loop
1913ca95b02SDimitry Andric ///
1923ca95b02SDimitry Andric /// If it has a value (e.g. {"llvm.distribute", 1} return the value as an
1933ca95b02SDimitry Andric /// operand or null otherwise. If the string metadata is not found return
1943ca95b02SDimitry Andric /// Optional's not-a-value.
findStringMetadataForLoop(const Loop * TheLoop,StringRef Name)195*b5893f02SDimitry Andric Optional<const MDOperand *> llvm::findStringMetadataForLoop(const Loop *TheLoop,
1963ca95b02SDimitry Andric StringRef Name) {
197*b5893f02SDimitry Andric MDNode *MD = findOptionMDForLoop(TheLoop, Name);
1983ca95b02SDimitry Andric if (!MD)
199*b5893f02SDimitry Andric return None;
2003ca95b02SDimitry Andric switch (MD->getNumOperands()) {
2013ca95b02SDimitry Andric case 1:
2023ca95b02SDimitry Andric return nullptr;
2033ca95b02SDimitry Andric case 2:
2043ca95b02SDimitry Andric return &MD->getOperand(1);
2053ca95b02SDimitry Andric default:
2063ca95b02SDimitry Andric llvm_unreachable("loop metadata has 0 or 1 operand");
2073ca95b02SDimitry Andric }
2083ca95b02SDimitry Andric }
209*b5893f02SDimitry Andric
getOptionalBoolLoopAttribute(const Loop * TheLoop,StringRef Name)210*b5893f02SDimitry Andric static Optional<bool> getOptionalBoolLoopAttribute(const Loop *TheLoop,
211*b5893f02SDimitry Andric StringRef Name) {
212*b5893f02SDimitry Andric MDNode *MD = findOptionMDForLoop(TheLoop, Name);
213*b5893f02SDimitry Andric if (!MD)
2143ca95b02SDimitry Andric return None;
215*b5893f02SDimitry Andric switch (MD->getNumOperands()) {
216*b5893f02SDimitry Andric case 1:
217*b5893f02SDimitry Andric // When the value is absent it is interpreted as 'attribute set'.
218*b5893f02SDimitry Andric return true;
219*b5893f02SDimitry Andric case 2:
220*b5893f02SDimitry Andric if (ConstantInt *IntMD =
221*b5893f02SDimitry Andric mdconst::extract_or_null<ConstantInt>(MD->getOperand(1).get()))
222*b5893f02SDimitry Andric return IntMD->getZExtValue();
223*b5893f02SDimitry Andric return true;
224*b5893f02SDimitry Andric }
225*b5893f02SDimitry Andric llvm_unreachable("unexpected number of options");
226*b5893f02SDimitry Andric }
227*b5893f02SDimitry Andric
getBooleanLoopAttribute(const Loop * TheLoop,StringRef Name)228*b5893f02SDimitry Andric static bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name) {
229*b5893f02SDimitry Andric return getOptionalBoolLoopAttribute(TheLoop, Name).getValueOr(false);
230*b5893f02SDimitry Andric }
231*b5893f02SDimitry Andric
getOptionalIntLoopAttribute(Loop * TheLoop,StringRef Name)232*b5893f02SDimitry Andric llvm::Optional<int> llvm::getOptionalIntLoopAttribute(Loop *TheLoop,
233*b5893f02SDimitry Andric StringRef Name) {
234*b5893f02SDimitry Andric const MDOperand *AttrMD =
235*b5893f02SDimitry Andric findStringMetadataForLoop(TheLoop, Name).getValueOr(nullptr);
236*b5893f02SDimitry Andric if (!AttrMD)
237*b5893f02SDimitry Andric return None;
238*b5893f02SDimitry Andric
239*b5893f02SDimitry Andric ConstantInt *IntMD = mdconst::extract_or_null<ConstantInt>(AttrMD->get());
240*b5893f02SDimitry Andric if (!IntMD)
241*b5893f02SDimitry Andric return None;
242*b5893f02SDimitry Andric
243*b5893f02SDimitry Andric return IntMD->getSExtValue();
244*b5893f02SDimitry Andric }
245*b5893f02SDimitry Andric
makeFollowupLoopID(MDNode * OrigLoopID,ArrayRef<StringRef> FollowupOptions,const char * InheritOptionsExceptPrefix,bool AlwaysNew)246*b5893f02SDimitry Andric Optional<MDNode *> llvm::makeFollowupLoopID(
247*b5893f02SDimitry Andric MDNode *OrigLoopID, ArrayRef<StringRef> FollowupOptions,
248*b5893f02SDimitry Andric const char *InheritOptionsExceptPrefix, bool AlwaysNew) {
249*b5893f02SDimitry Andric if (!OrigLoopID) {
250*b5893f02SDimitry Andric if (AlwaysNew)
251*b5893f02SDimitry Andric return nullptr;
252*b5893f02SDimitry Andric return None;
253*b5893f02SDimitry Andric }
254*b5893f02SDimitry Andric
255*b5893f02SDimitry Andric assert(OrigLoopID->getOperand(0) == OrigLoopID);
256*b5893f02SDimitry Andric
257*b5893f02SDimitry Andric bool InheritAllAttrs = !InheritOptionsExceptPrefix;
258*b5893f02SDimitry Andric bool InheritSomeAttrs =
259*b5893f02SDimitry Andric InheritOptionsExceptPrefix && InheritOptionsExceptPrefix[0] != '\0';
260*b5893f02SDimitry Andric SmallVector<Metadata *, 8> MDs;
261*b5893f02SDimitry Andric MDs.push_back(nullptr);
262*b5893f02SDimitry Andric
263*b5893f02SDimitry Andric bool Changed = false;
264*b5893f02SDimitry Andric if (InheritAllAttrs || InheritSomeAttrs) {
265*b5893f02SDimitry Andric for (const MDOperand &Existing : drop_begin(OrigLoopID->operands(), 1)) {
266*b5893f02SDimitry Andric MDNode *Op = cast<MDNode>(Existing.get());
267*b5893f02SDimitry Andric
268*b5893f02SDimitry Andric auto InheritThisAttribute = [InheritSomeAttrs,
269*b5893f02SDimitry Andric InheritOptionsExceptPrefix](MDNode *Op) {
270*b5893f02SDimitry Andric if (!InheritSomeAttrs)
271*b5893f02SDimitry Andric return false;
272*b5893f02SDimitry Andric
273*b5893f02SDimitry Andric // Skip malformatted attribute metadata nodes.
274*b5893f02SDimitry Andric if (Op->getNumOperands() == 0)
275*b5893f02SDimitry Andric return true;
276*b5893f02SDimitry Andric Metadata *NameMD = Op->getOperand(0).get();
277*b5893f02SDimitry Andric if (!isa<MDString>(NameMD))
278*b5893f02SDimitry Andric return true;
279*b5893f02SDimitry Andric StringRef AttrName = cast<MDString>(NameMD)->getString();
280*b5893f02SDimitry Andric
281*b5893f02SDimitry Andric // Do not inherit excluded attributes.
282*b5893f02SDimitry Andric return !AttrName.startswith(InheritOptionsExceptPrefix);
283*b5893f02SDimitry Andric };
284*b5893f02SDimitry Andric
285*b5893f02SDimitry Andric if (InheritThisAttribute(Op))
286*b5893f02SDimitry Andric MDs.push_back(Op);
287*b5893f02SDimitry Andric else
288*b5893f02SDimitry Andric Changed = true;
289*b5893f02SDimitry Andric }
290*b5893f02SDimitry Andric } else {
291*b5893f02SDimitry Andric // Modified if we dropped at least one attribute.
292*b5893f02SDimitry Andric Changed = OrigLoopID->getNumOperands() > 1;
293*b5893f02SDimitry Andric }
294*b5893f02SDimitry Andric
295*b5893f02SDimitry Andric bool HasAnyFollowup = false;
296*b5893f02SDimitry Andric for (StringRef OptionName : FollowupOptions) {
297*b5893f02SDimitry Andric MDNode *FollowupNode = findOptionMDForLoopID(OrigLoopID, OptionName);
298*b5893f02SDimitry Andric if (!FollowupNode)
299*b5893f02SDimitry Andric continue;
300*b5893f02SDimitry Andric
301*b5893f02SDimitry Andric HasAnyFollowup = true;
302*b5893f02SDimitry Andric for (const MDOperand &Option : drop_begin(FollowupNode->operands(), 1)) {
303*b5893f02SDimitry Andric MDs.push_back(Option.get());
304*b5893f02SDimitry Andric Changed = true;
305*b5893f02SDimitry Andric }
306*b5893f02SDimitry Andric }
307*b5893f02SDimitry Andric
308*b5893f02SDimitry Andric // Attributes of the followup loop not specified explicity, so signal to the
309*b5893f02SDimitry Andric // transformation pass to add suitable attributes.
310*b5893f02SDimitry Andric if (!AlwaysNew && !HasAnyFollowup)
311*b5893f02SDimitry Andric return None;
312*b5893f02SDimitry Andric
313*b5893f02SDimitry Andric // If no attributes were added or remove, the previous loop Id can be reused.
314*b5893f02SDimitry Andric if (!AlwaysNew && !Changed)
315*b5893f02SDimitry Andric return OrigLoopID;
316*b5893f02SDimitry Andric
317*b5893f02SDimitry Andric // No attributes is equivalent to having no !llvm.loop metadata at all.
318*b5893f02SDimitry Andric if (MDs.size() == 1)
319*b5893f02SDimitry Andric return nullptr;
320*b5893f02SDimitry Andric
321*b5893f02SDimitry Andric // Build the new loop ID.
322*b5893f02SDimitry Andric MDTuple *FollowupLoopID = MDNode::get(OrigLoopID->getContext(), MDs);
323*b5893f02SDimitry Andric FollowupLoopID->replaceOperandWith(0, FollowupLoopID);
324*b5893f02SDimitry Andric return FollowupLoopID;
325*b5893f02SDimitry Andric }
326*b5893f02SDimitry Andric
hasDisableAllTransformsHint(const Loop * L)327*b5893f02SDimitry Andric bool llvm::hasDisableAllTransformsHint(const Loop *L) {
328*b5893f02SDimitry Andric return getBooleanLoopAttribute(L, LLVMLoopDisableNonforced);
329*b5893f02SDimitry Andric }
330*b5893f02SDimitry Andric
hasUnrollTransformation(Loop * L)331*b5893f02SDimitry Andric TransformationMode llvm::hasUnrollTransformation(Loop *L) {
332*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.unroll.disable"))
333*b5893f02SDimitry Andric return TM_SuppressedByUser;
334*b5893f02SDimitry Andric
335*b5893f02SDimitry Andric Optional<int> Count =
336*b5893f02SDimitry Andric getOptionalIntLoopAttribute(L, "llvm.loop.unroll.count");
337*b5893f02SDimitry Andric if (Count.hasValue())
338*b5893f02SDimitry Andric return Count.getValue() == 1 ? TM_SuppressedByUser : TM_ForcedByUser;
339*b5893f02SDimitry Andric
340*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.unroll.enable"))
341*b5893f02SDimitry Andric return TM_ForcedByUser;
342*b5893f02SDimitry Andric
343*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.unroll.full"))
344*b5893f02SDimitry Andric return TM_ForcedByUser;
345*b5893f02SDimitry Andric
346*b5893f02SDimitry Andric if (hasDisableAllTransformsHint(L))
347*b5893f02SDimitry Andric return TM_Disable;
348*b5893f02SDimitry Andric
349*b5893f02SDimitry Andric return TM_Unspecified;
350*b5893f02SDimitry Andric }
351*b5893f02SDimitry Andric
hasUnrollAndJamTransformation(Loop * L)352*b5893f02SDimitry Andric TransformationMode llvm::hasUnrollAndJamTransformation(Loop *L) {
353*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.unroll_and_jam.disable"))
354*b5893f02SDimitry Andric return TM_SuppressedByUser;
355*b5893f02SDimitry Andric
356*b5893f02SDimitry Andric Optional<int> Count =
357*b5893f02SDimitry Andric getOptionalIntLoopAttribute(L, "llvm.loop.unroll_and_jam.count");
358*b5893f02SDimitry Andric if (Count.hasValue())
359*b5893f02SDimitry Andric return Count.getValue() == 1 ? TM_SuppressedByUser : TM_ForcedByUser;
360*b5893f02SDimitry Andric
361*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.unroll_and_jam.enable"))
362*b5893f02SDimitry Andric return TM_ForcedByUser;
363*b5893f02SDimitry Andric
364*b5893f02SDimitry Andric if (hasDisableAllTransformsHint(L))
365*b5893f02SDimitry Andric return TM_Disable;
366*b5893f02SDimitry Andric
367*b5893f02SDimitry Andric return TM_Unspecified;
368*b5893f02SDimitry Andric }
369*b5893f02SDimitry Andric
hasVectorizeTransformation(Loop * L)370*b5893f02SDimitry Andric TransformationMode llvm::hasVectorizeTransformation(Loop *L) {
371*b5893f02SDimitry Andric Optional<bool> Enable =
372*b5893f02SDimitry Andric getOptionalBoolLoopAttribute(L, "llvm.loop.vectorize.enable");
373*b5893f02SDimitry Andric
374*b5893f02SDimitry Andric if (Enable == false)
375*b5893f02SDimitry Andric return TM_SuppressedByUser;
376*b5893f02SDimitry Andric
377*b5893f02SDimitry Andric Optional<int> VectorizeWidth =
378*b5893f02SDimitry Andric getOptionalIntLoopAttribute(L, "llvm.loop.vectorize.width");
379*b5893f02SDimitry Andric Optional<int> InterleaveCount =
380*b5893f02SDimitry Andric getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
381*b5893f02SDimitry Andric
382*b5893f02SDimitry Andric // 'Forcing' vector width and interleave count to one effectively disables
383*b5893f02SDimitry Andric // this tranformation.
384*b5893f02SDimitry Andric if (Enable == true && VectorizeWidth == 1 && InterleaveCount == 1)
385*b5893f02SDimitry Andric return TM_SuppressedByUser;
386*b5893f02SDimitry Andric
387*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.isvectorized"))
388*b5893f02SDimitry Andric return TM_Disable;
389*b5893f02SDimitry Andric
390*b5893f02SDimitry Andric if (Enable == true)
391*b5893f02SDimitry Andric return TM_ForcedByUser;
392*b5893f02SDimitry Andric
393*b5893f02SDimitry Andric if (VectorizeWidth == 1 && InterleaveCount == 1)
394*b5893f02SDimitry Andric return TM_Disable;
395*b5893f02SDimitry Andric
396*b5893f02SDimitry Andric if (VectorizeWidth > 1 || InterleaveCount > 1)
397*b5893f02SDimitry Andric return TM_Enable;
398*b5893f02SDimitry Andric
399*b5893f02SDimitry Andric if (hasDisableAllTransformsHint(L))
400*b5893f02SDimitry Andric return TM_Disable;
401*b5893f02SDimitry Andric
402*b5893f02SDimitry Andric return TM_Unspecified;
403*b5893f02SDimitry Andric }
404*b5893f02SDimitry Andric
hasDistributeTransformation(Loop * L)405*b5893f02SDimitry Andric TransformationMode llvm::hasDistributeTransformation(Loop *L) {
406*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.distribute.enable"))
407*b5893f02SDimitry Andric return TM_ForcedByUser;
408*b5893f02SDimitry Andric
409*b5893f02SDimitry Andric if (hasDisableAllTransformsHint(L))
410*b5893f02SDimitry Andric return TM_Disable;
411*b5893f02SDimitry Andric
412*b5893f02SDimitry Andric return TM_Unspecified;
413*b5893f02SDimitry Andric }
414*b5893f02SDimitry Andric
hasLICMVersioningTransformation(Loop * L)415*b5893f02SDimitry Andric TransformationMode llvm::hasLICMVersioningTransformation(Loop *L) {
416*b5893f02SDimitry Andric if (getBooleanLoopAttribute(L, "llvm.loop.licm_versioning.disable"))
417*b5893f02SDimitry Andric return TM_SuppressedByUser;
418*b5893f02SDimitry Andric
419*b5893f02SDimitry Andric if (hasDisableAllTransformsHint(L))
420*b5893f02SDimitry Andric return TM_Disable;
421*b5893f02SDimitry Andric
422*b5893f02SDimitry Andric return TM_Unspecified;
4233ca95b02SDimitry Andric }
4243ca95b02SDimitry Andric
4252cab237bSDimitry Andric /// Does a BFS from a given node to all of its children inside a given loop.
4262cab237bSDimitry Andric /// The returned vector of nodes includes the starting point.
4272cab237bSDimitry Andric SmallVector<DomTreeNode *, 16>
collectChildrenInLoop(DomTreeNode * N,const Loop * CurLoop)4282cab237bSDimitry Andric llvm::collectChildrenInLoop(DomTreeNode *N, const Loop *CurLoop) {
4292cab237bSDimitry Andric SmallVector<DomTreeNode *, 16> Worklist;
4302cab237bSDimitry Andric auto AddRegionToWorklist = [&](DomTreeNode *DTN) {
4312cab237bSDimitry Andric // Only include subregions in the top level loop.
4322cab237bSDimitry Andric BasicBlock *BB = DTN->getBlock();
4332cab237bSDimitry Andric if (CurLoop->contains(BB))
4342cab237bSDimitry Andric Worklist.push_back(DTN);
4352cab237bSDimitry Andric };
4362cab237bSDimitry Andric
4372cab237bSDimitry Andric AddRegionToWorklist(N);
4382cab237bSDimitry Andric
4392cab237bSDimitry Andric for (size_t I = 0; I < Worklist.size(); I++)
4402cab237bSDimitry Andric for (DomTreeNode *Child : Worklist[I]->getChildren())
4412cab237bSDimitry Andric AddRegionToWorklist(Child);
4422cab237bSDimitry Andric
4432cab237bSDimitry Andric return Worklist;
4442cab237bSDimitry Andric }
4452cab237bSDimitry Andric
deleteDeadLoop(Loop * L,DominatorTree * DT=nullptr,ScalarEvolution * SE=nullptr,LoopInfo * LI=nullptr)4462cab237bSDimitry Andric void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT = nullptr,
4472cab237bSDimitry Andric ScalarEvolution *SE = nullptr,
4482cab237bSDimitry Andric LoopInfo *LI = nullptr) {
4492cab237bSDimitry Andric assert((!DT || L->isLCSSAForm(*DT)) && "Expected LCSSA!");
4502cab237bSDimitry Andric auto *Preheader = L->getLoopPreheader();
4512cab237bSDimitry Andric assert(Preheader && "Preheader should exist!");
4522cab237bSDimitry Andric
4532cab237bSDimitry Andric // Now that we know the removal is safe, remove the loop by changing the
4542cab237bSDimitry Andric // branch from the preheader to go to the single exit block.
4552cab237bSDimitry Andric //
4562cab237bSDimitry Andric // Because we're deleting a large chunk of code at once, the sequence in which
4572cab237bSDimitry Andric // we remove things is very important to avoid invalidation issues.
4582cab237bSDimitry Andric
4592cab237bSDimitry Andric // Tell ScalarEvolution that the loop is deleted. Do this before
4602cab237bSDimitry Andric // deleting the loop so that ScalarEvolution can look at the loop
4612cab237bSDimitry Andric // to determine what it needs to clean up.
4622cab237bSDimitry Andric if (SE)
4632cab237bSDimitry Andric SE->forgetLoop(L);
4642cab237bSDimitry Andric
4652cab237bSDimitry Andric auto *ExitBlock = L->getUniqueExitBlock();
4662cab237bSDimitry Andric assert(ExitBlock && "Should have a unique exit block!");
4672cab237bSDimitry Andric assert(L->hasDedicatedExits() && "Loop should have dedicated exits!");
4682cab237bSDimitry Andric
4692cab237bSDimitry Andric auto *OldBr = dyn_cast<BranchInst>(Preheader->getTerminator());
4702cab237bSDimitry Andric assert(OldBr && "Preheader must end with a branch");
4712cab237bSDimitry Andric assert(OldBr->isUnconditional() && "Preheader must have a single successor");
4722cab237bSDimitry Andric // Connect the preheader to the exit block. Keep the old edge to the header
4732cab237bSDimitry Andric // around to perform the dominator tree update in two separate steps
4742cab237bSDimitry Andric // -- #1 insertion of the edge preheader -> exit and #2 deletion of the edge
4752cab237bSDimitry Andric // preheader -> header.
4762cab237bSDimitry Andric //
4772cab237bSDimitry Andric //
4782cab237bSDimitry Andric // 0. Preheader 1. Preheader 2. Preheader
4792cab237bSDimitry Andric // | | | |
4802cab237bSDimitry Andric // V | V |
4812cab237bSDimitry Andric // Header <--\ | Header <--\ | Header <--\
4822cab237bSDimitry Andric // | | | | | | | | | | |
4832cab237bSDimitry Andric // | V | | | V | | | V |
4842cab237bSDimitry Andric // | Body --/ | | Body --/ | | Body --/
4852cab237bSDimitry Andric // V V V V V
4862cab237bSDimitry Andric // Exit Exit Exit
4872cab237bSDimitry Andric //
4882cab237bSDimitry Andric // By doing this is two separate steps we can perform the dominator tree
4892cab237bSDimitry Andric // update without using the batch update API.
4902cab237bSDimitry Andric //
4912cab237bSDimitry Andric // Even when the loop is never executed, we cannot remove the edge from the
4922cab237bSDimitry Andric // source block to the exit block. Consider the case where the unexecuted loop
4932cab237bSDimitry Andric // branches back to an outer loop. If we deleted the loop and removed the edge
4942cab237bSDimitry Andric // coming to this inner loop, this will break the outer loop structure (by
4952cab237bSDimitry Andric // deleting the backedge of the outer loop). If the outer loop is indeed a
4962cab237bSDimitry Andric // non-loop, it will be deleted in a future iteration of loop deletion pass.
4972cab237bSDimitry Andric IRBuilder<> Builder(OldBr);
4982cab237bSDimitry Andric Builder.CreateCondBr(Builder.getFalse(), L->getHeader(), ExitBlock);
4992cab237bSDimitry Andric // Remove the old branch. The conditional branch becomes a new terminator.
5002cab237bSDimitry Andric OldBr->eraseFromParent();
5012cab237bSDimitry Andric
5022cab237bSDimitry Andric // Rewrite phis in the exit block to get their inputs from the Preheader
5032cab237bSDimitry Andric // instead of the exiting block.
50430785c0eSDimitry Andric for (PHINode &P : ExitBlock->phis()) {
5052cab237bSDimitry Andric // Set the zero'th element of Phi to be from the preheader and remove all
5062cab237bSDimitry Andric // other incoming values. Given the loop has dedicated exits, all other
5072cab237bSDimitry Andric // incoming values must be from the exiting blocks.
5082cab237bSDimitry Andric int PredIndex = 0;
50930785c0eSDimitry Andric P.setIncomingBlock(PredIndex, Preheader);
5102cab237bSDimitry Andric // Removes all incoming values from all other exiting blocks (including
5112cab237bSDimitry Andric // duplicate values from an exiting block).
5122cab237bSDimitry Andric // Nuke all entries except the zero'th entry which is the preheader entry.
5132cab237bSDimitry Andric // NOTE! We need to remove Incoming Values in the reverse order as done
5142cab237bSDimitry Andric // below, to keep the indices valid for deletion (removeIncomingValues
5152cab237bSDimitry Andric // updates getNumIncomingValues and shifts all values down into the operand
5162cab237bSDimitry Andric // being deleted).
51730785c0eSDimitry Andric for (unsigned i = 0, e = P.getNumIncomingValues() - 1; i != e; ++i)
51830785c0eSDimitry Andric P.removeIncomingValue(e - i, false);
5192cab237bSDimitry Andric
52030785c0eSDimitry Andric assert((P.getNumIncomingValues() == 1 &&
52130785c0eSDimitry Andric P.getIncomingBlock(PredIndex) == Preheader) &&
5222cab237bSDimitry Andric "Should have exactly one value and that's from the preheader!");
5232cab237bSDimitry Andric }
5242cab237bSDimitry Andric
5252cab237bSDimitry Andric // Disconnect the loop body by branching directly to its exit.
5262cab237bSDimitry Andric Builder.SetInsertPoint(Preheader->getTerminator());
5272cab237bSDimitry Andric Builder.CreateBr(ExitBlock);
5282cab237bSDimitry Andric // Remove the old branch.
5292cab237bSDimitry Andric Preheader->getTerminator()->eraseFromParent();
5302cab237bSDimitry Andric
531*b5893f02SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
5322cab237bSDimitry Andric if (DT) {
5332cab237bSDimitry Andric // Update the dominator tree by informing it about the new edge from the
5342cab237bSDimitry Andric // preheader to the exit.
535*b5893f02SDimitry Andric DTU.insertEdge(Preheader, ExitBlock);
5362cab237bSDimitry Andric // Inform the dominator tree about the removed edge.
537*b5893f02SDimitry Andric DTU.deleteEdge(Preheader, L->getHeader());
5382cab237bSDimitry Andric }
5392cab237bSDimitry Andric
540*b5893f02SDimitry Andric // Use a map to unique and a vector to guarantee deterministic ordering.
541*b5893f02SDimitry Andric llvm::SmallDenseSet<std::pair<DIVariable *, DIExpression *>, 4> DeadDebugSet;
542*b5893f02SDimitry Andric llvm::SmallVector<DbgVariableIntrinsic *, 4> DeadDebugInst;
543*b5893f02SDimitry Andric
5444ba319b5SDimitry Andric // Given LCSSA form is satisfied, we should not have users of instructions
5454ba319b5SDimitry Andric // within the dead loop outside of the loop. However, LCSSA doesn't take
5464ba319b5SDimitry Andric // unreachable uses into account. We handle them here.
5474ba319b5SDimitry Andric // We could do it after drop all references (in this case all users in the
5484ba319b5SDimitry Andric // loop will be already eliminated and we have less work to do but according
5494ba319b5SDimitry Andric // to API doc of User::dropAllReferences only valid operation after dropping
5504ba319b5SDimitry Andric // references, is deletion. So let's substitute all usages of
5514ba319b5SDimitry Andric // instruction from the loop with undef value of corresponding type first.
5524ba319b5SDimitry Andric for (auto *Block : L->blocks())
5534ba319b5SDimitry Andric for (Instruction &I : *Block) {
5544ba319b5SDimitry Andric auto *Undef = UndefValue::get(I.getType());
5554ba319b5SDimitry Andric for (Value::use_iterator UI = I.use_begin(), E = I.use_end(); UI != E;) {
5564ba319b5SDimitry Andric Use &U = *UI;
5574ba319b5SDimitry Andric ++UI;
5584ba319b5SDimitry Andric if (auto *Usr = dyn_cast<Instruction>(U.getUser()))
5594ba319b5SDimitry Andric if (L->contains(Usr->getParent()))
5604ba319b5SDimitry Andric continue;
5614ba319b5SDimitry Andric // If we have a DT then we can check that uses outside a loop only in
5624ba319b5SDimitry Andric // unreachable block.
5634ba319b5SDimitry Andric if (DT)
5644ba319b5SDimitry Andric assert(!DT->isReachableFromEntry(U) &&
5654ba319b5SDimitry Andric "Unexpected user in reachable block");
5664ba319b5SDimitry Andric U.set(Undef);
5674ba319b5SDimitry Andric }
568*b5893f02SDimitry Andric auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I);
569*b5893f02SDimitry Andric if (!DVI)
570*b5893f02SDimitry Andric continue;
571*b5893f02SDimitry Andric auto Key = DeadDebugSet.find({DVI->getVariable(), DVI->getExpression()});
572*b5893f02SDimitry Andric if (Key != DeadDebugSet.end())
573*b5893f02SDimitry Andric continue;
574*b5893f02SDimitry Andric DeadDebugSet.insert({DVI->getVariable(), DVI->getExpression()});
575*b5893f02SDimitry Andric DeadDebugInst.push_back(DVI);
5764ba319b5SDimitry Andric }
5774ba319b5SDimitry Andric
578*b5893f02SDimitry Andric // After the loop has been deleted all the values defined and modified
579*b5893f02SDimitry Andric // inside the loop are going to be unavailable.
580*b5893f02SDimitry Andric // Since debug values in the loop have been deleted, inserting an undef
581*b5893f02SDimitry Andric // dbg.value truncates the range of any dbg.value before the loop where the
582*b5893f02SDimitry Andric // loop used to be. This is particularly important for constant values.
583*b5893f02SDimitry Andric DIBuilder DIB(*ExitBlock->getModule());
584*b5893f02SDimitry Andric for (auto *DVI : DeadDebugInst)
585*b5893f02SDimitry Andric DIB.insertDbgValueIntrinsic(
586*b5893f02SDimitry Andric UndefValue::get(Builder.getInt32Ty()), DVI->getVariable(),
587*b5893f02SDimitry Andric DVI->getExpression(), DVI->getDebugLoc(), ExitBlock->getFirstNonPHI());
588*b5893f02SDimitry Andric
5892cab237bSDimitry Andric // Remove the block from the reference counting scheme, so that we can
5902cab237bSDimitry Andric // delete it freely later.
5912cab237bSDimitry Andric for (auto *Block : L->blocks())
5922cab237bSDimitry Andric Block->dropAllReferences();
5932cab237bSDimitry Andric
5942cab237bSDimitry Andric if (LI) {
5952cab237bSDimitry Andric // Erase the instructions and the blocks without having to worry
5962cab237bSDimitry Andric // about ordering because we already dropped the references.
5972cab237bSDimitry Andric // NOTE: This iteration is safe because erasing the block does not remove
5982cab237bSDimitry Andric // its entry from the loop's block list. We do that in the next section.
5992cab237bSDimitry Andric for (Loop::block_iterator LpI = L->block_begin(), LpE = L->block_end();
6002cab237bSDimitry Andric LpI != LpE; ++LpI)
6012cab237bSDimitry Andric (*LpI)->eraseFromParent();
6022cab237bSDimitry Andric
6032cab237bSDimitry Andric // Finally, the blocks from loopinfo. This has to happen late because
6042cab237bSDimitry Andric // otherwise our loop iterators won't work.
6052cab237bSDimitry Andric
6062cab237bSDimitry Andric SmallPtrSet<BasicBlock *, 8> blocks;
6072cab237bSDimitry Andric blocks.insert(L->block_begin(), L->block_end());
6082cab237bSDimitry Andric for (BasicBlock *BB : blocks)
6092cab237bSDimitry Andric LI->removeBlock(BB);
6102cab237bSDimitry Andric
6112cab237bSDimitry Andric // The last step is to update LoopInfo now that we've eliminated this loop.
6122cab237bSDimitry Andric LI->erase(L);
6132cab237bSDimitry Andric }
6142cab237bSDimitry Andric }
6152cab237bSDimitry Andric
getLoopEstimatedTripCount(Loop * L)616d88c1a5aSDimitry Andric Optional<unsigned> llvm::getLoopEstimatedTripCount(Loop *L) {
617d88c1a5aSDimitry Andric // Only support loops with a unique exiting block, and a latch.
618d88c1a5aSDimitry Andric if (!L->getExitingBlock())
619d88c1a5aSDimitry Andric return None;
620d88c1a5aSDimitry Andric
6214ba319b5SDimitry Andric // Get the branch weights for the loop's backedge.
622d88c1a5aSDimitry Andric BranchInst *LatchBR =
623d88c1a5aSDimitry Andric dyn_cast<BranchInst>(L->getLoopLatch()->getTerminator());
624d88c1a5aSDimitry Andric if (!LatchBR || LatchBR->getNumSuccessors() != 2)
625d88c1a5aSDimitry Andric return None;
626d88c1a5aSDimitry Andric
627d88c1a5aSDimitry Andric assert((LatchBR->getSuccessor(0) == L->getHeader() ||
628d88c1a5aSDimitry Andric LatchBR->getSuccessor(1) == L->getHeader()) &&
629d88c1a5aSDimitry Andric "At least one edge out of the latch must go to the header");
630d88c1a5aSDimitry Andric
631d88c1a5aSDimitry Andric // To estimate the number of times the loop body was executed, we want to
632d88c1a5aSDimitry Andric // know the number of times the backedge was taken, vs. the number of times
633d88c1a5aSDimitry Andric // we exited the loop.
634d88c1a5aSDimitry Andric uint64_t TrueVal, FalseVal;
635d88c1a5aSDimitry Andric if (!LatchBR->extractProfMetadata(TrueVal, FalseVal))
636d88c1a5aSDimitry Andric return None;
637d88c1a5aSDimitry Andric
638d88c1a5aSDimitry Andric if (!TrueVal || !FalseVal)
639d88c1a5aSDimitry Andric return 0;
640d88c1a5aSDimitry Andric
641d88c1a5aSDimitry Andric // Divide the count of the backedge by the count of the edge exiting the loop,
642d88c1a5aSDimitry Andric // rounding to nearest.
643d88c1a5aSDimitry Andric if (LatchBR->getSuccessor(0) == L->getHeader())
644d88c1a5aSDimitry Andric return (TrueVal + (FalseVal / 2)) / FalseVal;
645d88c1a5aSDimitry Andric else
646d88c1a5aSDimitry Andric return (FalseVal + (TrueVal / 2)) / TrueVal;
647d88c1a5aSDimitry Andric }
6485517e702SDimitry Andric
hasIterationCountInvariantInParent(Loop * InnerLoop,ScalarEvolution & SE)649*b5893f02SDimitry Andric bool llvm::hasIterationCountInvariantInParent(Loop *InnerLoop,
650*b5893f02SDimitry Andric ScalarEvolution &SE) {
651*b5893f02SDimitry Andric Loop *OuterL = InnerLoop->getParentLoop();
652*b5893f02SDimitry Andric if (!OuterL)
653*b5893f02SDimitry Andric return true;
654*b5893f02SDimitry Andric
655*b5893f02SDimitry Andric // Get the backedge taken count for the inner loop
656*b5893f02SDimitry Andric BasicBlock *InnerLoopLatch = InnerLoop->getLoopLatch();
657*b5893f02SDimitry Andric const SCEV *InnerLoopBECountSC = SE.getExitCount(InnerLoop, InnerLoopLatch);
658*b5893f02SDimitry Andric if (isa<SCEVCouldNotCompute>(InnerLoopBECountSC) ||
659*b5893f02SDimitry Andric !InnerLoopBECountSC->getType()->isIntegerTy())
660*b5893f02SDimitry Andric return false;
661*b5893f02SDimitry Andric
662*b5893f02SDimitry Andric // Get whether count is invariant to the outer loop
663*b5893f02SDimitry Andric ScalarEvolution::LoopDisposition LD =
664*b5893f02SDimitry Andric SE.getLoopDisposition(InnerLoopBECountSC, OuterL);
665*b5893f02SDimitry Andric if (LD != ScalarEvolution::LoopInvariant)
666*b5893f02SDimitry Andric return false;
667*b5893f02SDimitry Andric
668*b5893f02SDimitry Andric return true;
669*b5893f02SDimitry Andric }
670*b5893f02SDimitry Andric
6714ba319b5SDimitry Andric /// Adds a 'fast' flag to floating point operations.
addFastMathFlag(Value * V)6725517e702SDimitry Andric static Value *addFastMathFlag(Value *V) {
6735517e702SDimitry Andric if (isa<FPMathOperator>(V)) {
6745517e702SDimitry Andric FastMathFlags Flags;
6752cab237bSDimitry Andric Flags.setFast();
6765517e702SDimitry Andric cast<Instruction>(V)->setFastMathFlags(Flags);
6775517e702SDimitry Andric }
6785517e702SDimitry Andric return V;
6795517e702SDimitry Andric }
6805517e702SDimitry Andric
createMinMaxOp(IRBuilder<> & Builder,RecurrenceDescriptor::MinMaxRecurrenceKind RK,Value * Left,Value * Right)681*b5893f02SDimitry Andric Value *llvm::createMinMaxOp(IRBuilder<> &Builder,
682*b5893f02SDimitry Andric RecurrenceDescriptor::MinMaxRecurrenceKind RK,
683*b5893f02SDimitry Andric Value *Left, Value *Right) {
684*b5893f02SDimitry Andric CmpInst::Predicate P = CmpInst::ICMP_NE;
685*b5893f02SDimitry Andric switch (RK) {
686*b5893f02SDimitry Andric default:
687*b5893f02SDimitry Andric llvm_unreachable("Unknown min/max recurrence kind");
688*b5893f02SDimitry Andric case RecurrenceDescriptor::MRK_UIntMin:
689*b5893f02SDimitry Andric P = CmpInst::ICMP_ULT;
690*b5893f02SDimitry Andric break;
691*b5893f02SDimitry Andric case RecurrenceDescriptor::MRK_UIntMax:
692*b5893f02SDimitry Andric P = CmpInst::ICMP_UGT;
693*b5893f02SDimitry Andric break;
694*b5893f02SDimitry Andric case RecurrenceDescriptor::MRK_SIntMin:
695*b5893f02SDimitry Andric P = CmpInst::ICMP_SLT;
696*b5893f02SDimitry Andric break;
697*b5893f02SDimitry Andric case RecurrenceDescriptor::MRK_SIntMax:
698*b5893f02SDimitry Andric P = CmpInst::ICMP_SGT;
699*b5893f02SDimitry Andric break;
700*b5893f02SDimitry Andric case RecurrenceDescriptor::MRK_FloatMin:
701*b5893f02SDimitry Andric P = CmpInst::FCMP_OLT;
702*b5893f02SDimitry Andric break;
703*b5893f02SDimitry Andric case RecurrenceDescriptor::MRK_FloatMax:
704*b5893f02SDimitry Andric P = CmpInst::FCMP_OGT;
705*b5893f02SDimitry Andric break;
706*b5893f02SDimitry Andric }
707*b5893f02SDimitry Andric
708*b5893f02SDimitry Andric // We only match FP sequences that are 'fast', so we can unconditionally
709*b5893f02SDimitry Andric // set it on any generated instructions.
710*b5893f02SDimitry Andric IRBuilder<>::FastMathFlagGuard FMFG(Builder);
711*b5893f02SDimitry Andric FastMathFlags FMF;
712*b5893f02SDimitry Andric FMF.setFast();
713*b5893f02SDimitry Andric Builder.setFastMathFlags(FMF);
714*b5893f02SDimitry Andric
715*b5893f02SDimitry Andric Value *Cmp;
716*b5893f02SDimitry Andric if (RK == RecurrenceDescriptor::MRK_FloatMin ||
717*b5893f02SDimitry Andric RK == RecurrenceDescriptor::MRK_FloatMax)
718*b5893f02SDimitry Andric Cmp = Builder.CreateFCmp(P, Left, Right, "rdx.minmax.cmp");
719*b5893f02SDimitry Andric else
720*b5893f02SDimitry Andric Cmp = Builder.CreateICmp(P, Left, Right, "rdx.minmax.cmp");
721*b5893f02SDimitry Andric
722*b5893f02SDimitry Andric Value *Select = Builder.CreateSelect(Cmp, Left, Right, "rdx.minmax.select");
723*b5893f02SDimitry Andric return Select;
724*b5893f02SDimitry Andric }
725*b5893f02SDimitry Andric
7264ba319b5SDimitry Andric // Helper to generate an ordered reduction.
7274ba319b5SDimitry Andric Value *
getOrderedReduction(IRBuilder<> & Builder,Value * Acc,Value * Src,unsigned Op,RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind,ArrayRef<Value * > RedOps)7284ba319b5SDimitry Andric llvm::getOrderedReduction(IRBuilder<> &Builder, Value *Acc, Value *Src,
7294ba319b5SDimitry Andric unsigned Op,
7304ba319b5SDimitry Andric RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind,
7314ba319b5SDimitry Andric ArrayRef<Value *> RedOps) {
7324ba319b5SDimitry Andric unsigned VF = Src->getType()->getVectorNumElements();
7334ba319b5SDimitry Andric
7344ba319b5SDimitry Andric // Extract and apply reduction ops in ascending order:
7354ba319b5SDimitry Andric // e.g. ((((Acc + Scl[0]) + Scl[1]) + Scl[2]) + ) ... + Scl[VF-1]
7364ba319b5SDimitry Andric Value *Result = Acc;
7374ba319b5SDimitry Andric for (unsigned ExtractIdx = 0; ExtractIdx != VF; ++ExtractIdx) {
7384ba319b5SDimitry Andric Value *Ext =
7394ba319b5SDimitry Andric Builder.CreateExtractElement(Src, Builder.getInt32(ExtractIdx));
7404ba319b5SDimitry Andric
7414ba319b5SDimitry Andric if (Op != Instruction::ICmp && Op != Instruction::FCmp) {
7424ba319b5SDimitry Andric Result = Builder.CreateBinOp((Instruction::BinaryOps)Op, Result, Ext,
7434ba319b5SDimitry Andric "bin.rdx");
7444ba319b5SDimitry Andric } else {
7454ba319b5SDimitry Andric assert(MinMaxKind != RecurrenceDescriptor::MRK_Invalid &&
7464ba319b5SDimitry Andric "Invalid min/max");
747*b5893f02SDimitry Andric Result = createMinMaxOp(Builder, MinMaxKind, Result, Ext);
7484ba319b5SDimitry Andric }
7494ba319b5SDimitry Andric
7504ba319b5SDimitry Andric if (!RedOps.empty())
7514ba319b5SDimitry Andric propagateIRFlags(Result, RedOps);
7524ba319b5SDimitry Andric }
7534ba319b5SDimitry Andric
7544ba319b5SDimitry Andric return Result;
7554ba319b5SDimitry Andric }
7564ba319b5SDimitry Andric
7575517e702SDimitry Andric // Helper to generate a log2 shuffle reduction.
7585517e702SDimitry Andric Value *
getShuffleReduction(IRBuilder<> & Builder,Value * Src,unsigned Op,RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind,ArrayRef<Value * > RedOps)7595517e702SDimitry Andric llvm::getShuffleReduction(IRBuilder<> &Builder, Value *Src, unsigned Op,
7605517e702SDimitry Andric RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind,
7615517e702SDimitry Andric ArrayRef<Value *> RedOps) {
7625517e702SDimitry Andric unsigned VF = Src->getType()->getVectorNumElements();
7635517e702SDimitry Andric // VF is a power of 2 so we can emit the reduction using log2(VF) shuffles
7645517e702SDimitry Andric // and vector ops, reducing the set of values being computed by half each
7655517e702SDimitry Andric // round.
7665517e702SDimitry Andric assert(isPowerOf2_32(VF) &&
7675517e702SDimitry Andric "Reduction emission only supported for pow2 vectors!");
7685517e702SDimitry Andric Value *TmpVec = Src;
7695517e702SDimitry Andric SmallVector<Constant *, 32> ShuffleMask(VF, nullptr);
7705517e702SDimitry Andric for (unsigned i = VF; i != 1; i >>= 1) {
7715517e702SDimitry Andric // Move the upper half of the vector to the lower half.
7725517e702SDimitry Andric for (unsigned j = 0; j != i / 2; ++j)
7735517e702SDimitry Andric ShuffleMask[j] = Builder.getInt32(i / 2 + j);
7745517e702SDimitry Andric
7755517e702SDimitry Andric // Fill the rest of the mask with undef.
7765517e702SDimitry Andric std::fill(&ShuffleMask[i / 2], ShuffleMask.end(),
7775517e702SDimitry Andric UndefValue::get(Builder.getInt32Ty()));
7785517e702SDimitry Andric
7795517e702SDimitry Andric Value *Shuf = Builder.CreateShuffleVector(
7805517e702SDimitry Andric TmpVec, UndefValue::get(TmpVec->getType()),
7815517e702SDimitry Andric ConstantVector::get(ShuffleMask), "rdx.shuf");
7825517e702SDimitry Andric
7835517e702SDimitry Andric if (Op != Instruction::ICmp && Op != Instruction::FCmp) {
7845517e702SDimitry Andric // Floating point operations had to be 'fast' to enable the reduction.
7855517e702SDimitry Andric TmpVec = addFastMathFlag(Builder.CreateBinOp((Instruction::BinaryOps)Op,
7865517e702SDimitry Andric TmpVec, Shuf, "bin.rdx"));
7875517e702SDimitry Andric } else {
7885517e702SDimitry Andric assert(MinMaxKind != RecurrenceDescriptor::MRK_Invalid &&
7895517e702SDimitry Andric "Invalid min/max");
790*b5893f02SDimitry Andric TmpVec = createMinMaxOp(Builder, MinMaxKind, TmpVec, Shuf);
7915517e702SDimitry Andric }
7925517e702SDimitry Andric if (!RedOps.empty())
7935517e702SDimitry Andric propagateIRFlags(TmpVec, RedOps);
7945517e702SDimitry Andric }
7955517e702SDimitry Andric // The result is in the first element of the vector.
7965517e702SDimitry Andric return Builder.CreateExtractElement(TmpVec, Builder.getInt32(0));
7975517e702SDimitry Andric }
7985517e702SDimitry Andric
7995517e702SDimitry Andric /// Create a simple vector reduction specified by an opcode and some
8005517e702SDimitry Andric /// flags (if generating min/max reductions).
createSimpleTargetReduction(IRBuilder<> & Builder,const TargetTransformInfo * TTI,unsigned Opcode,Value * Src,TargetTransformInfo::ReductionFlags Flags,ArrayRef<Value * > RedOps)8015517e702SDimitry Andric Value *llvm::createSimpleTargetReduction(
8025517e702SDimitry Andric IRBuilder<> &Builder, const TargetTransformInfo *TTI, unsigned Opcode,
8035517e702SDimitry Andric Value *Src, TargetTransformInfo::ReductionFlags Flags,
8045517e702SDimitry Andric ArrayRef<Value *> RedOps) {
8055517e702SDimitry Andric assert(isa<VectorType>(Src->getType()) && "Type must be a vector");
8065517e702SDimitry Andric
8075517e702SDimitry Andric Value *ScalarUdf = UndefValue::get(Src->getType()->getVectorElementType());
8085517e702SDimitry Andric std::function<Value *()> BuildFunc;
8095517e702SDimitry Andric using RD = RecurrenceDescriptor;
8105517e702SDimitry Andric RD::MinMaxRecurrenceKind MinMaxKind = RD::MRK_Invalid;
8115517e702SDimitry Andric // TODO: Support creating ordered reductions.
8122cab237bSDimitry Andric FastMathFlags FMFFast;
8132cab237bSDimitry Andric FMFFast.setFast();
8145517e702SDimitry Andric
8155517e702SDimitry Andric switch (Opcode) {
8165517e702SDimitry Andric case Instruction::Add:
8175517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateAddReduce(Src); };
8185517e702SDimitry Andric break;
8195517e702SDimitry Andric case Instruction::Mul:
8205517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateMulReduce(Src); };
8215517e702SDimitry Andric break;
8225517e702SDimitry Andric case Instruction::And:
8235517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateAndReduce(Src); };
8245517e702SDimitry Andric break;
8255517e702SDimitry Andric case Instruction::Or:
8265517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateOrReduce(Src); };
8275517e702SDimitry Andric break;
8285517e702SDimitry Andric case Instruction::Xor:
8295517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateXorReduce(Src); };
8305517e702SDimitry Andric break;
8315517e702SDimitry Andric case Instruction::FAdd:
8325517e702SDimitry Andric BuildFunc = [&]() {
8335517e702SDimitry Andric auto Rdx = Builder.CreateFAddReduce(ScalarUdf, Src);
8342cab237bSDimitry Andric cast<CallInst>(Rdx)->setFastMathFlags(FMFFast);
8355517e702SDimitry Andric return Rdx;
8365517e702SDimitry Andric };
8375517e702SDimitry Andric break;
8385517e702SDimitry Andric case Instruction::FMul:
8395517e702SDimitry Andric BuildFunc = [&]() {
8405517e702SDimitry Andric auto Rdx = Builder.CreateFMulReduce(ScalarUdf, Src);
8412cab237bSDimitry Andric cast<CallInst>(Rdx)->setFastMathFlags(FMFFast);
8425517e702SDimitry Andric return Rdx;
8435517e702SDimitry Andric };
8445517e702SDimitry Andric break;
8455517e702SDimitry Andric case Instruction::ICmp:
8465517e702SDimitry Andric if (Flags.IsMaxOp) {
8475517e702SDimitry Andric MinMaxKind = Flags.IsSigned ? RD::MRK_SIntMax : RD::MRK_UIntMax;
8485517e702SDimitry Andric BuildFunc = [&]() {
8495517e702SDimitry Andric return Builder.CreateIntMaxReduce(Src, Flags.IsSigned);
8505517e702SDimitry Andric };
8515517e702SDimitry Andric } else {
8525517e702SDimitry Andric MinMaxKind = Flags.IsSigned ? RD::MRK_SIntMin : RD::MRK_UIntMin;
8535517e702SDimitry Andric BuildFunc = [&]() {
8545517e702SDimitry Andric return Builder.CreateIntMinReduce(Src, Flags.IsSigned);
8555517e702SDimitry Andric };
8565517e702SDimitry Andric }
8575517e702SDimitry Andric break;
8585517e702SDimitry Andric case Instruction::FCmp:
8595517e702SDimitry Andric if (Flags.IsMaxOp) {
8605517e702SDimitry Andric MinMaxKind = RD::MRK_FloatMax;
8615517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateFPMaxReduce(Src, Flags.NoNaN); };
8625517e702SDimitry Andric } else {
8635517e702SDimitry Andric MinMaxKind = RD::MRK_FloatMin;
8645517e702SDimitry Andric BuildFunc = [&]() { return Builder.CreateFPMinReduce(Src, Flags.NoNaN); };
8655517e702SDimitry Andric }
8665517e702SDimitry Andric break;
8675517e702SDimitry Andric default:
8685517e702SDimitry Andric llvm_unreachable("Unhandled opcode");
8695517e702SDimitry Andric break;
8705517e702SDimitry Andric }
8715517e702SDimitry Andric if (TTI->useReductionIntrinsic(Opcode, Src->getType(), Flags))
8725517e702SDimitry Andric return BuildFunc();
8735517e702SDimitry Andric return getShuffleReduction(Builder, Src, Opcode, MinMaxKind, RedOps);
8745517e702SDimitry Andric }
8755517e702SDimitry Andric
8765517e702SDimitry Andric /// Create a vector reduction using a given recurrence descriptor.
createTargetReduction(IRBuilder<> & B,const TargetTransformInfo * TTI,RecurrenceDescriptor & Desc,Value * Src,bool NoNaN)8772cab237bSDimitry Andric Value *llvm::createTargetReduction(IRBuilder<> &B,
8785517e702SDimitry Andric const TargetTransformInfo *TTI,
8795517e702SDimitry Andric RecurrenceDescriptor &Desc, Value *Src,
8805517e702SDimitry Andric bool NoNaN) {
8815517e702SDimitry Andric // TODO: Support in-order reductions based on the recurrence descriptor.
8822cab237bSDimitry Andric using RD = RecurrenceDescriptor;
8832cab237bSDimitry Andric RD::RecurrenceKind RecKind = Desc.getRecurrenceKind();
8845517e702SDimitry Andric TargetTransformInfo::ReductionFlags Flags;
8855517e702SDimitry Andric Flags.NoNaN = NoNaN;
8865517e702SDimitry Andric switch (RecKind) {
8872cab237bSDimitry Andric case RD::RK_FloatAdd:
8882cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::FAdd, Src, Flags);
8892cab237bSDimitry Andric case RD::RK_FloatMult:
8902cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::FMul, Src, Flags);
8912cab237bSDimitry Andric case RD::RK_IntegerAdd:
8922cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::Add, Src, Flags);
8932cab237bSDimitry Andric case RD::RK_IntegerMult:
8942cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::Mul, Src, Flags);
8952cab237bSDimitry Andric case RD::RK_IntegerAnd:
8962cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::And, Src, Flags);
8972cab237bSDimitry Andric case RD::RK_IntegerOr:
8982cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::Or, Src, Flags);
8992cab237bSDimitry Andric case RD::RK_IntegerXor:
9002cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::Xor, Src, Flags);
9012cab237bSDimitry Andric case RD::RK_IntegerMinMax: {
9022cab237bSDimitry Andric RD::MinMaxRecurrenceKind MMKind = Desc.getMinMaxRecurrenceKind();
9032cab237bSDimitry Andric Flags.IsMaxOp = (MMKind == RD::MRK_SIntMax || MMKind == RD::MRK_UIntMax);
9042cab237bSDimitry Andric Flags.IsSigned = (MMKind == RD::MRK_SIntMax || MMKind == RD::MRK_SIntMin);
9052cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::ICmp, Src, Flags);
9065517e702SDimitry Andric }
9072cab237bSDimitry Andric case RD::RK_FloatMinMax: {
9082cab237bSDimitry Andric Flags.IsMaxOp = Desc.getMinMaxRecurrenceKind() == RD::MRK_FloatMax;
9092cab237bSDimitry Andric return createSimpleTargetReduction(B, TTI, Instruction::FCmp, Src, Flags);
9105517e702SDimitry Andric }
9115517e702SDimitry Andric default:
9125517e702SDimitry Andric llvm_unreachable("Unhandled RecKind");
9135517e702SDimitry Andric }
9145517e702SDimitry Andric }
9155517e702SDimitry Andric
propagateIRFlags(Value * I,ArrayRef<Value * > VL,Value * OpValue)91637cd60a3SDimitry Andric void llvm::propagateIRFlags(Value *I, ArrayRef<Value *> VL, Value *OpValue) {
91737cd60a3SDimitry Andric auto *VecOp = dyn_cast<Instruction>(I);
91837cd60a3SDimitry Andric if (!VecOp)
91937cd60a3SDimitry Andric return;
92037cd60a3SDimitry Andric auto *Intersection = (OpValue == nullptr) ? dyn_cast<Instruction>(VL[0])
92137cd60a3SDimitry Andric : dyn_cast<Instruction>(OpValue);
92237cd60a3SDimitry Andric if (!Intersection)
92337cd60a3SDimitry Andric return;
92437cd60a3SDimitry Andric const unsigned Opcode = Intersection->getOpcode();
92537cd60a3SDimitry Andric VecOp->copyIRFlags(Intersection);
92637cd60a3SDimitry Andric for (auto *V : VL) {
92737cd60a3SDimitry Andric auto *Instr = dyn_cast<Instruction>(V);
92837cd60a3SDimitry Andric if (!Instr)
92937cd60a3SDimitry Andric continue;
93037cd60a3SDimitry Andric if (OpValue == nullptr || Opcode == Instr->getOpcode())
93137cd60a3SDimitry Andric VecOp->andIRFlags(V);
9325517e702SDimitry Andric }
9335517e702SDimitry Andric }
934*b5893f02SDimitry Andric
isKnownNegativeInLoop(const SCEV * S,const Loop * L,ScalarEvolution & SE)935*b5893f02SDimitry Andric bool llvm::isKnownNegativeInLoop(const SCEV *S, const Loop *L,
936*b5893f02SDimitry Andric ScalarEvolution &SE) {
937*b5893f02SDimitry Andric const SCEV *Zero = SE.getZero(S->getType());
938*b5893f02SDimitry Andric return SE.isAvailableAtLoopEntry(S, L) &&
939*b5893f02SDimitry Andric SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SLT, S, Zero);
940*b5893f02SDimitry Andric }
941*b5893f02SDimitry Andric
isKnownNonNegativeInLoop(const SCEV * S,const Loop * L,ScalarEvolution & SE)942*b5893f02SDimitry Andric bool llvm::isKnownNonNegativeInLoop(const SCEV *S, const Loop *L,
943*b5893f02SDimitry Andric ScalarEvolution &SE) {
944*b5893f02SDimitry Andric const SCEV *Zero = SE.getZero(S->getType());
945*b5893f02SDimitry Andric return SE.isAvailableAtLoopEntry(S, L) &&
946*b5893f02SDimitry Andric SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGE, S, Zero);
947*b5893f02SDimitry Andric }
948*b5893f02SDimitry Andric
cannotBeMinInLoop(const SCEV * S,const Loop * L,ScalarEvolution & SE,bool Signed)949*b5893f02SDimitry Andric bool llvm::cannotBeMinInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE,
950*b5893f02SDimitry Andric bool Signed) {
951*b5893f02SDimitry Andric unsigned BitWidth = cast<IntegerType>(S->getType())->getBitWidth();
952*b5893f02SDimitry Andric APInt Min = Signed ? APInt::getSignedMinValue(BitWidth) :
953*b5893f02SDimitry Andric APInt::getMinValue(BitWidth);
954*b5893f02SDimitry Andric auto Predicate = Signed ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
955*b5893f02SDimitry Andric return SE.isAvailableAtLoopEntry(S, L) &&
956*b5893f02SDimitry Andric SE.isLoopEntryGuardedByCond(L, Predicate, S,
957*b5893f02SDimitry Andric SE.getConstant(Min));
958*b5893f02SDimitry Andric }
959*b5893f02SDimitry Andric
cannotBeMaxInLoop(const SCEV * S,const Loop * L,ScalarEvolution & SE,bool Signed)960*b5893f02SDimitry Andric bool llvm::cannotBeMaxInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE,
961*b5893f02SDimitry Andric bool Signed) {
962*b5893f02SDimitry Andric unsigned BitWidth = cast<IntegerType>(S->getType())->getBitWidth();
963*b5893f02SDimitry Andric APInt Max = Signed ? APInt::getSignedMaxValue(BitWidth) :
964*b5893f02SDimitry Andric APInt::getMaxValue(BitWidth);
965*b5893f02SDimitry Andric auto Predicate = Signed ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
966*b5893f02SDimitry Andric return SE.isAvailableAtLoopEntry(S, L) &&
967*b5893f02SDimitry Andric SE.isLoopEntryGuardedByCond(L, Predicate, S,
968*b5893f02SDimitry Andric SE.getConstant(Max));
969*b5893f02SDimitry Andric }
970