diff options
Diffstat (limited to 'include/llvm/Transforms/Utils')
| -rw-r--r-- | include/llvm/Transforms/Utils/BasicBlockUtils.h | 67 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/BuildLibCalls.h | 14 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/CanonicalizeAliases.h | 32 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/Cloning.h | 66 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/CodeExtractor.h | 23 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/FunctionImportUtils.h | 3 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/GuardUtils.h | 30 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/Local.h | 74 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/LoopRotationUtils.h | 5 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/LoopUtils.h | 450 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/ModuleUtils.h | 18 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/OrderedInstructions.h | 65 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/PredicateInfo.h | 2 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/SSAUpdater.h | 4 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/SSAUpdaterImpl.h | 7 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/SimplifyLibCalls.h | 25 | ||||
| -rw-r--r-- | include/llvm/Transforms/Utils/UnrollLoop.h | 23 |
17 files changed, 408 insertions, 500 deletions
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 3dfc73b64842..5b16a2c0d0b1 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -20,6 +20,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/InstrTypes.h" #include <cassert> @@ -27,19 +28,27 @@ namespace llvm { class BlockFrequencyInfo; class BranchProbabilityInfo; -class DeferredDominance; class DominatorTree; +class DomTreeUpdater; class Function; class Instruction; class LoopInfo; class MDNode; class MemoryDependenceResults; +class MemorySSAUpdater; class ReturnInst; class TargetLibraryInfo; class Value; /// Delete the specified block, which must have no predecessors. -void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = nullptr); +void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); + +/// Delete the specified blocks from \p BB. The set of deleted blocks must have +/// no predecessors that are not being deleted themselves. \p BBs must have no +/// duplicating blocks. If there are loops among this set of blocks, all +/// relevant loop info updates should be done before this function is called. +void DeleteDeadBlocks(SmallVectorImpl <BasicBlock *> &BBs, + DomTreeUpdater *DTU = nullptr); /// We know that BB has one predecessor. If there are any single-entry PHI nodes /// in it, fold them away. This handles the case when all entries to the PHI @@ -56,10 +65,10 @@ bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr); /// Attempts to merge a block into its predecessor, if possible. The return /// value indicates success or failure. -bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr, +bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU = nullptr, LoopInfo *LI = nullptr, - MemoryDependenceResults *MemDep = nullptr, - DeferredDominance *DDT = nullptr); + MemorySSAUpdater *MSSAU = nullptr, + MemoryDependenceResults *MemDep = nullptr); /// Replace all uses of an instruction (specified by BI) with a value, then /// remove and delete the original instruction. @@ -84,13 +93,15 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To); struct CriticalEdgeSplittingOptions { DominatorTree *DT; LoopInfo *LI; + MemorySSAUpdater *MSSAU; bool MergeIdenticalEdges = false; bool DontDeleteUselessPHIs = false; bool PreserveLCSSA = false; CriticalEdgeSplittingOptions(DominatorTree *DT = nullptr, - LoopInfo *LI = nullptr) - : DT(DT), LI(LI) {} + LoopInfo *LI = nullptr, + MemorySSAUpdater *MSSAU = nullptr) + : DT(DT), LI(LI), MSSAU(MSSAU) {} CriticalEdgeSplittingOptions &setMergeIdenticalEdges() { MergeIdenticalEdges = true; @@ -124,7 +135,7 @@ struct CriticalEdgeSplittingOptions { /// IndirectBrInst. Splitting these edges will almost always create an invalid /// program because the address of the new block won't be the one that is jumped /// to. -BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, +BasicBlock *SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options = CriticalEdgeSplittingOptions()); @@ -144,7 +155,7 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, const CriticalEdgeSplittingOptions &Options = CriticalEdgeSplittingOptions()) { bool MadeChange = false; - TerminatorInst *TI = (*PI)->getTerminator(); + Instruction *TI = (*PI)->getTerminator(); for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) if (TI->getSuccessor(i) == Succ) MadeChange |= !!SplitCriticalEdge(TI, i, Options); @@ -158,7 +169,7 @@ inline BasicBlock * SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, const CriticalEdgeSplittingOptions &Options = CriticalEdgeSplittingOptions()) { - TerminatorInst *TI = Src->getTerminator(); + Instruction *TI = Src->getTerminator(); unsigned i = 0; while (true) { assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); @@ -176,14 +187,16 @@ unsigned SplitAllCriticalEdges(Function &F, /// Split the edge connecting specified block. BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, - DominatorTree *DT = nullptr, LoopInfo *LI = nullptr); + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, + MemorySSAUpdater *MSSAU = nullptr); /// Split the specified block at the specified instruction - everything before /// SplitPt stays in Old and everything starting with SplitPt moves to a new /// block. The two blocks are joined by an unconditional branch and the loop /// info is updated. BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, - DominatorTree *DT = nullptr, LoopInfo *LI = nullptr); + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, + MemorySSAUpdater *MSSAU = nullptr); /// This method introduces at least one new basic block into the function and /// moves some of the predecessors of BB to be predecessors of the new block. @@ -203,6 +216,7 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock *> Preds, const char *Suffix, DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, + MemorySSAUpdater *MSSAU = nullptr, bool PreserveLCSSA = false); /// This method transforms the landing pad, OrigBB, by introducing two new basic @@ -216,20 +230,19 @@ BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock *> Preds, /// no other analyses. In particular, it does not preserve LoopSimplify /// (because it's complicated to handle the case where one of the edges being /// split is an exit of a loop with other exits). -void SplitLandingPadPredecessors(BasicBlock *OrigBB, - ArrayRef<BasicBlock *> Preds, - const char *Suffix, const char *Suffix2, - SmallVectorImpl<BasicBlock *> &NewBBs, - DominatorTree *DT = nullptr, - LoopInfo *LI = nullptr, - bool PreserveLCSSA = false); +void SplitLandingPadPredecessors( + BasicBlock *OrigBB, ArrayRef<BasicBlock *> Preds, const char *Suffix, + const char *Suffix2, SmallVectorImpl<BasicBlock *> &NewBBs, + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, + MemorySSAUpdater *MSSAU = nullptr, bool PreserveLCSSA = false); /// This method duplicates the specified return instruction into a predecessor /// which ends in an unconditional branch. If the return instruction returns a /// value defined by a PHI, propagate the right value into the return. It /// returns the new return instruction in the predecessor. ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, - BasicBlock *Pred); + BasicBlock *Pred, + DomTreeUpdater *DTU = nullptr); /// Split the containing block at the specified instruction - everything before /// SplitBefore stays in the old basic block, and the rest of the instructions @@ -251,11 +264,11 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, /// Returns the NewBasicBlock's terminator. /// /// Updates DT and LI if given. -TerminatorInst *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, - bool Unreachable, - MDNode *BranchWeights = nullptr, - DominatorTree *DT = nullptr, - LoopInfo *LI = nullptr); +Instruction *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, + bool Unreachable, + MDNode *BranchWeights = nullptr, + DominatorTree *DT = nullptr, + LoopInfo *LI = nullptr); /// SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, /// but also creates the ElseBlock. @@ -272,8 +285,8 @@ TerminatorInst *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, /// SplitBefore /// Tail void SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore, - TerminatorInst **ThenTerm, - TerminatorInst **ElseTerm, + Instruction **ThenTerm, + Instruction **ElseTerm, MDNode *BranchWeights = nullptr); /// Check whether BB is the merge point of a if-region. diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index bdcdf6f361f2..28efce6ac3fb 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -29,6 +29,7 @@ namespace llvm { /// /// Returns true if any attributes were set and false otherwise. bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI); + bool inferLibFuncAttributes(Module *M, StringRef Name, const TargetLibraryInfo &TLI); /// Check whether the overloaded unary floating point function /// corresponding to \a Ty is available. @@ -36,6 +37,12 @@ namespace llvm { LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn); + /// Get the name of the overloaded unary floating point function + /// corresponding to \a Ty. + StringRef getUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn); + /// Return V if it is an i8*, otherwise cast it to i8*. Value *castToCStr(Value *V, IRBuilder<> &B); @@ -93,6 +100,13 @@ namespace llvm { Value *emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, const AttributeList &Attrs); + /// Emit a call to the unary function DoubleFn, FloatFn or LongDoubleFn, + /// depending of the type of Op. + Value *emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn, IRBuilder<> &B, + const AttributeList &Attrs); + /// Emit a call to the binary function named 'Name' (e.g. 'fmin'). This /// function is known to take type matching 'Op1' and 'Op2' and return one /// value with the same type. If 'Op1/Op2' are long double, 'l' is added as diff --git a/include/llvm/Transforms/Utils/CanonicalizeAliases.h b/include/llvm/Transforms/Utils/CanonicalizeAliases.h new file mode 100644 index 000000000000..f23263783fec --- /dev/null +++ b/include/llvm/Transforms/Utils/CanonicalizeAliases.h @@ -0,0 +1,32 @@ +//===-- CanonicalizeAliases.h - Alias Canonicalization Pass -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file canonicalizes aliases. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CANONICALIZE_ALIASES_H +#define LLVM_TRANSFORMS_UTILS_CANONICALIZE_ALIASES_H + +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Simple pass that canonicalizes aliases. +class CanonicalizeAliasesPass : public PassInfoMixin<CanonicalizeAliasesPass> { +public: + CanonicalizeAliasesPass() = default; + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_CANONICALIZE_ALIASESH diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 7531fb2d69b3..f5e997324fc8 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -22,6 +22,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/InlineCost.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Transforms/Utils/ValueMapper.h" @@ -46,9 +47,9 @@ class LoopInfo; class Module; class ProfileSummaryInfo; class ReturnInst; +class DomTreeUpdater; /// Return an exact copy of the specified module -/// std::unique_ptr<Module> CloneModule(const Module &M); std::unique_ptr<Module> CloneModule(const Module &M, ValueToValueMapTy &VMap); @@ -60,17 +61,15 @@ std::unique_ptr<Module> CloneModule(const Module &M, ValueToValueMapTy &VMap, function_ref<bool(const GlobalValue *)> ShouldCloneDefinition); -/// ClonedCodeInfo - This struct can be used to capture information about code +/// This struct can be used to capture information about code /// being cloned, while it is being cloned. struct ClonedCodeInfo { - /// ContainsCalls - This is set to true if the cloned code contains a normal - /// call instruction. + /// This is set to true if the cloned code contains a normal call instruction. bool ContainsCalls = false; - /// ContainsDynamicAllocas - This is set to true if the cloned code contains - /// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in - /// the entry block or they are in the entry block but are not a constant - /// size. + /// This is set to true if the cloned code contains a 'dynamic' alloca. + /// Dynamic allocas are allocas that are either not in the entry block or they + /// are in the entry block but are not a constant size. bool ContainsDynamicAllocas = false; /// All cloned call sites that have operand bundles attached are appended to @@ -81,7 +80,7 @@ struct ClonedCodeInfo { ClonedCodeInfo() = default; }; -/// CloneBasicBlock - Return a copy of the specified basic block, but without +/// Return a copy of the specified basic block, but without /// embedding the block into a particular function. The block returned is an /// exact copy of the specified basic block, without any remapping having been /// performed. Because of this, this is only suitable for applications where @@ -108,13 +107,12 @@ struct ClonedCodeInfo { /// If you would like to collect additional information about the cloned /// function, you can specify a ClonedCodeInfo object with the optional fifth /// parameter. -/// BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix = "", Function *F = nullptr, ClonedCodeInfo *CodeInfo = nullptr, DebugInfoFinder *DIFinder = nullptr); -/// CloneFunction - Return a copy of the specified function and add it to that +/// Return a copy of the specified function and add it to that /// function's module. Also, any references specified in the VMap are changed /// to refer to their mapped value instead of the original one. If any of the /// arguments to the function are in the VMap, the arguments are deleted from @@ -153,7 +151,7 @@ void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = nullptr); -/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, +/// This works exactly like CloneFunctionInto, /// except that it does some simple constant prop and DCE on the fly. The /// effect of this is to copy significantly less code in cases where (for /// example) a function call with constant arguments is inlined, and those @@ -171,8 +169,8 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, ClonedCodeInfo *CodeInfo = nullptr, Instruction *TheCall = nullptr); -/// InlineFunctionInfo - This class captures the data input to the -/// InlineFunction call, and records the auxiliary results produced by it. +/// This class captures the data input to the InlineFunction call, and records +/// the auxiliary results produced by it. class InlineFunctionInfo { public: explicit InlineFunctionInfo(CallGraph *cg = nullptr, @@ -184,19 +182,19 @@ public: : CG(cg), GetAssumptionCache(GetAssumptionCache), PSI(PSI), CallerBFI(CallerBFI), CalleeBFI(CalleeBFI) {} - /// CG - If non-null, InlineFunction will update the callgraph to reflect the + /// If non-null, InlineFunction will update the callgraph to reflect the /// changes it makes. CallGraph *CG; std::function<AssumptionCache &(Function &)> *GetAssumptionCache; ProfileSummaryInfo *PSI; BlockFrequencyInfo *CallerBFI, *CalleeBFI; - /// StaticAllocas - InlineFunction fills this in with all static allocas that - /// get copied into the caller. + /// InlineFunction fills this in with all static allocas that get copied into + /// the caller. SmallVector<AllocaInst *, 4> StaticAllocas; - /// InlinedCalls - InlineFunction fills this in with callsites that were - /// inlined from the callee. This is only filled in if CG is non-null. + /// InlineFunction fills this in with callsites that were inlined from the + /// callee. This is only filled in if CG is non-null. SmallVector<WeakTrackingVH, 8> InlinedCalls; /// All of the new call sites inlined into the caller. @@ -213,7 +211,7 @@ public: } }; -/// InlineFunction - This function inlines the called function into the basic +/// This function inlines the called function into the basic /// block of the caller. This returns false if it is not possible to inline /// this call. The program is still in a well defined state if this occurs /// though. @@ -232,13 +230,16 @@ public: /// and all varargs at the callsite will be passed to any calls to /// ForwardVarArgsTo. The caller of InlineFunction has to make sure any varargs /// are only used by ForwardVarArgsTo. -bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI, - AAResults *CalleeAAR = nullptr, bool InsertLifetime = true); -bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, - AAResults *CalleeAAR = nullptr, bool InsertLifetime = true); -bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, - AAResults *CalleeAAR = nullptr, bool InsertLifetime = true, - Function *ForwardVarArgsTo = nullptr); +InlineResult InlineFunction(CallInst *C, InlineFunctionInfo &IFI, + AAResults *CalleeAAR = nullptr, + bool InsertLifetime = true); +InlineResult InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI, + AAResults *CalleeAAR = nullptr, + bool InsertLifetime = true); +InlineResult InlineFunction(CallSite CS, InlineFunctionInfo &IFI, + AAResults *CalleeAAR = nullptr, + bool InsertLifetime = true, + Function *ForwardVarArgsTo = nullptr); /// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p /// Blocks. @@ -262,11 +263,12 @@ void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks, /// we replace them with the uses of corresponding Phi inputs. ValueMapping /// is used to map the original instructions from BB to their newly-created /// copies. Returns the split block. -BasicBlock * -DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB, - Instruction *StopAt, - ValueToValueMapTy &ValueMapping, - DominatorTree *DT = nullptr); +BasicBlock *DuplicateInstructionsInSplitBetween(BasicBlock *BB, + BasicBlock *PredBB, + Instruction *StopAt, + ValueToValueMapTy &ValueMapping, + DomTreeUpdater &DTU); + } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_CLONING_H diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h index 0e5254acb0d3..fee79fdc3bff 100644 --- a/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include <limits> namespace llvm { @@ -26,6 +27,7 @@ class BasicBlock; class BlockFrequency; class BlockFrequencyInfo; class BranchProbabilityInfo; +class CallInst; class DominatorTree; class Function; class Instruction; @@ -64,6 +66,11 @@ class Value; unsigned NumExitBlocks = std::numeric_limits<unsigned>::max(); Type *RetTy; + // Suffix to use when creating extracted function (appended to the original + // function name + "."). If empty, the default is to use the entry block + // label, if non-empty, otherwise "extracted". + std::string Suffix; + public: /// Create a code extractor for a sequence of blocks. /// @@ -78,7 +85,8 @@ class Value; CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = nullptr, bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr, BranchProbabilityInfo *BPI = nullptr, - bool AllowVarArgs = false, bool AllowAlloca = false); + bool AllowVarArgs = false, bool AllowAlloca = false, + std::string Suffix = ""); /// Create a code extractor for a loop body. /// @@ -86,7 +94,8 @@ class Value; /// block sequence of the loop. CodeExtractor(DominatorTree &DT, Loop &L, bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr, - BranchProbabilityInfo *BPI = nullptr); + BranchProbabilityInfo *BPI = nullptr, + std::string Suffix = ""); /// Perform the extraction, returning the new function. /// @@ -139,7 +148,8 @@ class Value; BasicBlock *findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock); private: - void severSplitPHINodes(BasicBlock *&Header); + void severSplitPHINodesOfEntry(BasicBlock *&Header); + void severSplitPHINodesOfExits(const SmallPtrSetImpl<BasicBlock *> &Exits); void splitReturnBlocks(); Function *constructFunction(const ValueSet &inputs, @@ -155,10 +165,9 @@ class Value; DenseMap<BasicBlock *, BlockFrequency> &ExitWeights, BranchProbabilityInfo *BPI); - void emitCallAndSwitchStatement(Function *newFunction, - BasicBlock *newHeader, - ValueSet &inputs, - ValueSet &outputs); + CallInst *emitCallAndSwitchStatement(Function *newFunction, + BasicBlock *newHeader, + ValueSet &inputs, ValueSet &outputs); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Utils/FunctionImportUtils.h b/include/llvm/Transforms/Utils/FunctionImportUtils.h index b9fbef04cdc3..e24398b90012 100644 --- a/include/llvm/Transforms/Utils/FunctionImportUtils.h +++ b/include/llvm/Transforms/Utils/FunctionImportUtils.h @@ -114,6 +114,9 @@ bool renameModuleForThinLTO( Module &M, const ModuleSummaryIndex &Index, SetVector<GlobalValue *> *GlobalsToImport = nullptr); +/// Compute synthetic function entry counts. +void computeSyntheticCounts(ModuleSummaryIndex &Index); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/GuardUtils.h b/include/llvm/Transforms/Utils/GuardUtils.h new file mode 100644 index 000000000000..537045edafe4 --- /dev/null +++ b/include/llvm/Transforms/Utils/GuardUtils.h @@ -0,0 +1,30 @@ +//===-- GuardUtils.h - Utils for work with guards ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Utils that are used to perform transformations related to guards and their +// conditions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_GUARDUTILS_H +#define LLVM_TRANSFORMS_UTILS_GUARDUTILS_H + +namespace llvm { + +class CallInst; +class Function; + +/// Splits control flow at point of \p Guard, replacing it with explicit branch +/// by the condition of guard's first argument. The taken branch then goes to +/// the block that contains \p Guard's successors, and the non-taken branch +/// goes to a newly-created deopt block that contains a sole call of the +/// deoptimize function \p DeoptIntrinsic. +void makeGuardControlFlowExplicit(Function *DeoptIntrinsic, CallInst *Guard); + +} // llvm + +#endif // LLVM_TRANSFORMS_UTILS_GUARDUTILS_H diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index b8df32565723..ec8b0eda3641 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -26,6 +26,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DomTreeUpdater.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Operator.h" @@ -43,7 +44,7 @@ class AssumptionCache; class BasicBlock; class BranchInst; class CallInst; -class DbgInfoIntrinsic; +class DbgVariableIntrinsic; class DbgValueInst; class DIBuilder; class Function; @@ -51,6 +52,7 @@ class Instruction; class LazyValueInfo; class LoadInst; class MDNode; +class MemorySSAUpdater; class PHINode; class StoreInst; class TargetLibraryInfo; @@ -120,7 +122,7 @@ struct SimplifyCFGOptions { /// DeleteDeadConditions is true. bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false, const TargetLibraryInfo *TLI = nullptr, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); //===----------------------------------------------------------------------===// // Local dead code elimination. @@ -140,8 +142,9 @@ bool wouldInstructionBeTriviallyDead(Instruction *I, /// If the specified value is a trivially dead instruction, delete it. /// If that makes any of its operands trivially dead, delete them too, /// recursively. Return true if any instructions were deleted. -bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, - const TargetLibraryInfo *TLI = nullptr); +bool RecursivelyDeleteTriviallyDeadInstructions( + Value *V, const TargetLibraryInfo *TLI = nullptr, + MemorySSAUpdater *MSSAU = nullptr); /// Delete all of the instructions in `DeadInsts`, and all other instructions /// that deleting these in turn causes to be trivially dead. @@ -153,7 +156,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, /// empty afterward. void RecursivelyDeleteTriviallyDeadInstructions( SmallVectorImpl<Instruction *> &DeadInsts, - const TargetLibraryInfo *TLI = nullptr); + const TargetLibraryInfo *TLI = nullptr, MemorySSAUpdater *MSSAU = nullptr); /// If the specified value is an effectively dead PHI node, due to being a /// def-use chain of single-use nodes that either forms a cycle or is terminated @@ -171,6 +174,12 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN, bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr); +/// Replace all the uses of an SSA value in @llvm.dbg intrinsics with +/// undef. This is useful for signaling that a variable, e.g. has been +/// found dead and hence it's unavailable at a given program point. +/// Returns true if the dbg values have been changed. +bool replaceDbgUsesWithUndef(Instruction *I); + //===----------------------------------------------------------------------===// // Control Flow Graph Restructuring. // @@ -187,20 +196,19 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the 'and' to 0. void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// BB is a block with one predecessor and its predecessor is known to have one /// successor (BB!). Eliminate the edge between them, moving the instructions in /// the predecessor into BB. This deletes the predecessor block. -void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr, - DeferredDominance *DDT = nullptr); +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); /// BB is known to contain an unconditional branch, and contains no instructions /// other than PHI nodes, potential debug intrinsics and the branch. If /// possible, eliminate BB by rewriting all the predecessors to branch to the /// successor block and return true. If we can't transform, return false. bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// Check for and eliminate duplicate PHI nodes in this block. This doesn't try /// to be clever about PHI nodes which differ only in the order of the incoming @@ -270,17 +278,17 @@ inline unsigned getKnownAlignment(Value *V, const DataLayout &DL, /// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value /// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic. -void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII, +void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, StoreInst *SI, DIBuilder &Builder); /// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value /// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic. -void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII, +void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, LoadInst *LI, DIBuilder &Builder); /// Inserts a llvm.dbg.value intrinsic after a phi that has an associated /// llvm.dbg.declare or llvm.dbg.addr intrinsic. -void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII, +void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, PHINode *LI, DIBuilder &Builder); /// Lowers llvm.dbg.declare intrinsics into appropriate set of @@ -294,13 +302,13 @@ void insertDebugValuesForPHIs(BasicBlock *BB, /// Finds all intrinsics declaring local variables as living in the memory that /// 'V' points to. This may include a mix of dbg.declare and /// dbg.addr intrinsics. -TinyPtrVector<DbgInfoIntrinsic *> FindDbgAddrUses(Value *V); +TinyPtrVector<DbgVariableIntrinsic *> FindDbgAddrUses(Value *V); /// Finds the llvm.dbg.value intrinsics describing a value. void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V); /// Finds the debug info intrinsics describing a value. -void findDbgUsers(SmallVectorImpl<DbgInfoIntrinsic *> &DbgInsts, Value *V); +void findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, Value *V); /// Replaces llvm.dbg.declare instruction when the address it /// describes is replaced with a new value. If Deref is true, an @@ -359,7 +367,7 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB); /// instruction, making it and the rest of the code in the block dead. unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap, bool PreserveLCSSA = false, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr); /// Convert the CallInst to InvokeInst with the specified unwind edge basic /// block. This also splits the basic block where CI is located, because @@ -374,24 +382,36 @@ BasicBlock *changeToInvokeAndSplitBasicBlock(CallInst *CI, /// /// \param BB Block whose terminator will be replaced. Its terminator must /// have an unwind successor. -void removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT = nullptr); +void removeUnwindEdge(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); /// Remove all blocks that can not be reached from the function's entry. /// /// Returns true if any basic block was removed. bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr, - DeferredDominance *DDT = nullptr); + DomTreeUpdater *DTU = nullptr, + MemorySSAUpdater *MSSAU = nullptr); -/// Combine the metadata of two instructions so that K can replace J +/// Combine the metadata of two instructions so that K can replace J. Some +/// metadata kinds can only be kept if K does not move, meaning it dominated +/// J in the original IR. /// /// Metadata not listed as known via KnownIDs is removed -void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs); +void combineMetadata(Instruction *K, const Instruction *J, + ArrayRef<unsigned> KnownIDs, bool DoesKMove); /// Combine the metadata of two instructions so that K can replace J. This -/// specifically handles the case of CSE-like transformations. +/// specifically handles the case of CSE-like transformations. Some +/// metadata can only be kept if K dominates J. For this to be correct, +/// K cannot be hoisted. /// /// Unknown metadata is removed. -void combineMetadataForCSE(Instruction *K, const Instruction *J); +void combineMetadataForCSE(Instruction *K, const Instruction *J, + bool DoesKMove); + +/// Patch the replacement so that it is not more restrictive than the value +/// being replaced. It assumes that the replacement does not get moved from +/// its original position. +void patchReplacementInstruction(Instruction *I, Value *Repl); // Replace each use of 'From' with 'To', if that use does not belong to basic // block where 'From' is defined. Returns the number of replacements made. @@ -429,6 +449,18 @@ void copyNonnullMetadata(const LoadInst &OldLI, MDNode *N, LoadInst &NewLI); void copyRangeMetadata(const DataLayout &DL, const LoadInst &OldLI, MDNode *N, LoadInst &NewLI); +/// Remove the debug intrinsic instructions for the given instruction. +void dropDebugUsers(Instruction &I); + +/// Hoist all of the instructions in the \p IfBlock to the dominant block +/// \p DomBlock, by moving its instructions to the insertion point \p InsertPt. +/// +/// The moved instructions receive the insertion point debug location values +/// (DILocations) and their debug intrinsic instructions (dbg.values) are +/// removed. +void hoistAllInstructionsInto(BasicBlock *DomBlock, Instruction *InsertPt, + BasicBlock *BB); + //===----------------------------------------------------------------------===// // Intrinsic pattern matching // diff --git a/include/llvm/Transforms/Utils/LoopRotationUtils.h b/include/llvm/Transforms/Utils/LoopRotationUtils.h index 231e5bbb6dee..cd5bc4301018 100644 --- a/include/llvm/Transforms/Utils/LoopRotationUtils.h +++ b/include/llvm/Transforms/Utils/LoopRotationUtils.h @@ -20,6 +20,7 @@ class AssumptionCache; class DominatorTree; class Loop; class LoopInfo; +class MemorySSAUpdater; class ScalarEvolution; struct SimplifyQuery; class TargetTransformInfo; @@ -32,8 +33,8 @@ class TargetTransformInfo; /// LoopRotation. If it is true, the profitability heuristic will be ignored. bool LoopRotation(Loop *L, LoopInfo *LI, const TargetTransformInfo *TTI, AssumptionCache *AC, DominatorTree *DT, ScalarEvolution *SE, - const SimplifyQuery &SQ, bool RotationOnly, - unsigned Threshold, bool IsUtilMode); + MemorySSAUpdater *MSSAU, const SimplifyQuery &SQ, + bool RotationOnly, unsigned Threshold, bool IsUtilMode); } // namespace llvm diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index eb4c99102a63..8c2527b6ae68 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -23,6 +23,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/DemandedBits.h" #include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/IVDescriptors.h" #include "llvm/Analysis/MustExecute.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Dominators.h" @@ -40,6 +41,7 @@ class BasicBlock; class DataLayout; class Loop; class LoopInfo; +class MemorySSAUpdater; class OptimizationRemarkEmitter; class PredicatedScalarEvolution; class PredIteratorCache; @@ -48,318 +50,6 @@ class SCEV; class TargetLibraryInfo; class TargetTransformInfo; - -/// The RecurrenceDescriptor is used to identify recurrences variables in a -/// loop. Reduction is a special case of recurrence that has uses of the -/// recurrence variable outside the loop. The method isReductionPHI identifies -/// reductions that are basic recurrences. -/// -/// Basic recurrences are defined as the summation, product, OR, AND, XOR, min, -/// or max of a set of terms. For example: for(i=0; i<n; i++) { total += -/// array[i]; } is a summation of array elements. Basic recurrences are a -/// special case of chains of recurrences (CR). See ScalarEvolution for CR -/// references. - -/// This struct holds information about recurrence variables. -class RecurrenceDescriptor { -public: - /// This enum represents the kinds of recurrences that we support. - enum RecurrenceKind { - RK_NoRecurrence, ///< Not a recurrence. - RK_IntegerAdd, ///< Sum of integers. - RK_IntegerMult, ///< Product of integers. - RK_IntegerOr, ///< Bitwise or logical OR of numbers. - RK_IntegerAnd, ///< Bitwise or logical AND of numbers. - RK_IntegerXor, ///< Bitwise or logical XOR of numbers. - RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()). - RK_FloatAdd, ///< Sum of floats. - RK_FloatMult, ///< Product of floats. - RK_FloatMinMax ///< Min/max implemented in terms of select(cmp()). - }; - - // This enum represents the kind of minmax recurrence. - enum MinMaxRecurrenceKind { - MRK_Invalid, - MRK_UIntMin, - MRK_UIntMax, - MRK_SIntMin, - MRK_SIntMax, - MRK_FloatMin, - MRK_FloatMax - }; - - RecurrenceDescriptor() = default; - - RecurrenceDescriptor(Value *Start, Instruction *Exit, RecurrenceKind K, - MinMaxRecurrenceKind MK, Instruction *UAI, Type *RT, - bool Signed, SmallPtrSetImpl<Instruction *> &CI) - : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK), - UnsafeAlgebraInst(UAI), RecurrenceType(RT), IsSigned(Signed) { - CastInsts.insert(CI.begin(), CI.end()); - } - - /// This POD struct holds information about a potential recurrence operation. - class InstDesc { - public: - InstDesc(bool IsRecur, Instruction *I, Instruction *UAI = nullptr) - : IsRecurrence(IsRecur), PatternLastInst(I), MinMaxKind(MRK_Invalid), - UnsafeAlgebraInst(UAI) {} - - InstDesc(Instruction *I, MinMaxRecurrenceKind K, Instruction *UAI = nullptr) - : IsRecurrence(true), PatternLastInst(I), MinMaxKind(K), - UnsafeAlgebraInst(UAI) {} - - bool isRecurrence() { return IsRecurrence; } - - bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } - - Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } - - MinMaxRecurrenceKind getMinMaxKind() { return MinMaxKind; } - - Instruction *getPatternInst() { return PatternLastInst; } - - private: - // Is this instruction a recurrence candidate. - bool IsRecurrence; - // The last instruction in a min/max pattern (select of the select(icmp()) - // pattern), or the current recurrence instruction otherwise. - Instruction *PatternLastInst; - // If this is a min/max pattern the comparison predicate. - MinMaxRecurrenceKind MinMaxKind; - // Recurrence has unsafe algebra. - Instruction *UnsafeAlgebraInst; - }; - - /// Returns a struct describing if the instruction 'I' can be a recurrence - /// variable of type 'Kind'. If the recurrence is a min/max pattern of - /// select(icmp()) this function advances the instruction pointer 'I' from the - /// compare instruction to the select instruction and stores this pointer in - /// 'PatternLastInst' member of the returned struct. - static InstDesc isRecurrenceInstr(Instruction *I, RecurrenceKind Kind, - InstDesc &Prev, bool HasFunNoNaNAttr); - - /// Returns true if instruction I has multiple uses in Insts - static bool hasMultipleUsesOf(Instruction *I, - SmallPtrSetImpl<Instruction *> &Insts); - - /// Returns true if all uses of the instruction I is within the Set. - static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set); - - /// Returns a struct describing if the instruction if the instruction is a - /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y) - /// or max(X, Y). - static InstDesc isMinMaxSelectCmpPattern(Instruction *I, InstDesc &Prev); - - /// Returns identity corresponding to the RecurrenceKind. - static Constant *getRecurrenceIdentity(RecurrenceKind K, Type *Tp); - - /// Returns the opcode of binary operation corresponding to the - /// RecurrenceKind. - static unsigned getRecurrenceBinOp(RecurrenceKind Kind); - - /// Returns a Min/Max operation corresponding to MinMaxRecurrenceKind. - static Value *createMinMaxOp(IRBuilder<> &Builder, MinMaxRecurrenceKind RK, - Value *Left, Value *Right); - - /// Returns true if Phi is a reduction of type Kind and adds it to the - /// RecurrenceDescriptor. If either \p DB is non-null or \p AC and \p DT are - /// non-null, the minimal bit width needed to compute the reduction will be - /// computed. - static bool AddReductionVar(PHINode *Phi, RecurrenceKind Kind, Loop *TheLoop, - bool HasFunNoNaNAttr, - RecurrenceDescriptor &RedDes, - DemandedBits *DB = nullptr, - AssumptionCache *AC = nullptr, - DominatorTree *DT = nullptr); - - /// Returns true if Phi is a reduction in TheLoop. The RecurrenceDescriptor - /// is returned in RedDes. If either \p DB is non-null or \p AC and \p DT are - /// non-null, the minimal bit width needed to compute the reduction will be - /// computed. - static bool isReductionPHI(PHINode *Phi, Loop *TheLoop, - RecurrenceDescriptor &RedDes, - DemandedBits *DB = nullptr, - AssumptionCache *AC = nullptr, - DominatorTree *DT = nullptr); - - /// Returns true if Phi is a first-order recurrence. A first-order recurrence - /// is a non-reduction recurrence relation in which the value of the - /// recurrence in the current loop iteration equals a value defined in the - /// previous iteration. \p SinkAfter includes pairs of instructions where the - /// first will be rescheduled to appear after the second if/when the loop is - /// vectorized. It may be augmented with additional pairs if needed in order - /// to handle Phi as a first-order recurrence. - static bool - isFirstOrderRecurrence(PHINode *Phi, Loop *TheLoop, - DenseMap<Instruction *, Instruction *> &SinkAfter, - DominatorTree *DT); - - RecurrenceKind getRecurrenceKind() { return Kind; } - - MinMaxRecurrenceKind getMinMaxRecurrenceKind() { return MinMaxKind; } - - TrackingVH<Value> getRecurrenceStartValue() { return StartValue; } - - Instruction *getLoopExitInstr() { return LoopExitInstr; } - - /// Returns true if the recurrence has unsafe algebra which requires a relaxed - /// floating-point model. - bool hasUnsafeAlgebra() { return UnsafeAlgebraInst != nullptr; } - - /// Returns first unsafe algebra instruction in the PHI node's use-chain. - Instruction *getUnsafeAlgebraInst() { return UnsafeAlgebraInst; } - - /// Returns true if the recurrence kind is an integer kind. - static bool isIntegerRecurrenceKind(RecurrenceKind Kind); - - /// Returns true if the recurrence kind is a floating point kind. - static bool isFloatingPointRecurrenceKind(RecurrenceKind Kind); - - /// Returns true if the recurrence kind is an arithmetic kind. - static bool isArithmeticRecurrenceKind(RecurrenceKind Kind); - - /// Returns the type of the recurrence. This type can be narrower than the - /// actual type of the Phi if the recurrence has been type-promoted. - Type *getRecurrenceType() { return RecurrenceType; } - - /// Returns a reference to the instructions used for type-promoting the - /// recurrence. - SmallPtrSet<Instruction *, 8> &getCastInsts() { return CastInsts; } - - /// Returns true if all source operands of the recurrence are SExtInsts. - bool isSigned() { return IsSigned; } - -private: - // The starting value of the recurrence. - // It does not have to be zero! - TrackingVH<Value> StartValue; - // The instruction who's value is used outside the loop. - Instruction *LoopExitInstr = nullptr; - // The kind of the recurrence. - RecurrenceKind Kind = RK_NoRecurrence; - // If this a min/max recurrence the kind of recurrence. - MinMaxRecurrenceKind MinMaxKind = MRK_Invalid; - // First occurrence of unasfe algebra in the PHI's use-chain. - Instruction *UnsafeAlgebraInst = nullptr; - // The type of the recurrence. - Type *RecurrenceType = nullptr; - // True if all source operands of the recurrence are SExtInsts. - bool IsSigned = false; - // Instructions used for type-promoting the recurrence. - SmallPtrSet<Instruction *, 8> CastInsts; -}; - -/// A struct for saving information about induction variables. -class InductionDescriptor { -public: - /// This enum represents the kinds of inductions that we support. - enum InductionKind { - IK_NoInduction, ///< Not an induction variable. - IK_IntInduction, ///< Integer induction variable. Step = C. - IK_PtrInduction, ///< Pointer induction var. Step = C / sizeof(elem). - IK_FpInduction ///< Floating point induction variable. - }; - -public: - /// Default constructor - creates an invalid induction. - InductionDescriptor() = default; - - /// Get the consecutive direction. Returns: - /// 0 - unknown or non-consecutive. - /// 1 - consecutive and increasing. - /// -1 - consecutive and decreasing. - int getConsecutiveDirection() const; - - /// Compute the transformed value of Index at offset StartValue using step - /// StepValue. - /// For integer induction, returns StartValue + Index * StepValue. - /// For pointer induction, returns StartValue[Index * StepValue]. - /// FIXME: The newly created binary instructions should contain nsw/nuw - /// flags, which can be found from the original scalar operations. - Value *transform(IRBuilder<> &B, Value *Index, ScalarEvolution *SE, - const DataLayout& DL) const; - - Value *getStartValue() const { return StartValue; } - InductionKind getKind() const { return IK; } - const SCEV *getStep() const { return Step; } - ConstantInt *getConstIntStepValue() const; - - /// Returns true if \p Phi is an induction in the loop \p L. If \p Phi is an - /// induction, the induction descriptor \p D will contain the data describing - /// this induction. If by some other means the caller has a better SCEV - /// expression for \p Phi than the one returned by the ScalarEvolution - /// analysis, it can be passed through \p Expr. If the def-use chain - /// associated with the phi includes casts (that we know we can ignore - /// under proper runtime checks), they are passed through \p CastsToIgnore. - static bool - isInductionPHI(PHINode *Phi, const Loop* L, ScalarEvolution *SE, - InductionDescriptor &D, const SCEV *Expr = nullptr, - SmallVectorImpl<Instruction *> *CastsToIgnore = nullptr); - - /// Returns true if \p Phi is a floating point induction in the loop \p L. - /// If \p Phi is an induction, the induction descriptor \p D will contain - /// the data describing this induction. - static bool isFPInductionPHI(PHINode *Phi, const Loop* L, - ScalarEvolution *SE, InductionDescriptor &D); - - /// Returns true if \p Phi is a loop \p L induction, in the context associated - /// with the run-time predicate of PSE. If \p Assume is true, this can add - /// further SCEV predicates to \p PSE in order to prove that \p Phi is an - /// induction. - /// If \p Phi is an induction, \p D will contain the data describing this - /// induction. - static bool isInductionPHI(PHINode *Phi, const Loop* L, - PredicatedScalarEvolution &PSE, - InductionDescriptor &D, bool Assume = false); - - /// Returns true if the induction type is FP and the binary operator does - /// not have the "fast-math" property. Such operation requires a relaxed FP - /// mode. - bool hasUnsafeAlgebra() { - return InductionBinOp && !cast<FPMathOperator>(InductionBinOp)->isFast(); - } - - /// Returns induction operator that does not have "fast-math" property - /// and requires FP unsafe mode. - Instruction *getUnsafeAlgebraInst() { - if (!InductionBinOp || cast<FPMathOperator>(InductionBinOp)->isFast()) - return nullptr; - return InductionBinOp; - } - - /// Returns binary opcode of the induction operator. - Instruction::BinaryOps getInductionOpcode() const { - return InductionBinOp ? InductionBinOp->getOpcode() : - Instruction::BinaryOpsEnd; - } - - /// Returns a reference to the type cast instructions in the induction - /// update chain, that are redundant when guarded with a runtime - /// SCEV overflow check. - const SmallVectorImpl<Instruction *> &getCastInsts() const { - return RedundantCasts; - } - -private: - /// Private constructor - used by \c isInductionPHI. - InductionDescriptor(Value *Start, InductionKind K, const SCEV *Step, - BinaryOperator *InductionBinOp = nullptr, - SmallVectorImpl<Instruction *> *Casts = nullptr); - - /// Start value. - TrackingVH<Value> StartValue; - /// Induction kind. - InductionKind IK = IK_NoInduction; - /// Step value. - const SCEV *Step = nullptr; - // Instruction that advances induction variable. - BinaryOperator *InductionBinOp = nullptr; - // Instructions used for type-casts of the induction variable, - // that are redundant when guarded with a runtime SCEV overflow check. - SmallVector<Instruction *, 2> RedundantCasts; -}; - BasicBlock *InsertPreheaderForLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, bool PreserveLCSSA); @@ -420,7 +110,7 @@ bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, /// arguments. Diagnostics is emitted via \p ORE. It returns changed status. bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, TargetTransformInfo *, Loop *, - AliasSetTracker *, LoopSafetyInfo *, + AliasSetTracker *, MemorySSAUpdater *, ICFLoopSafetyInfo *, OptimizationRemarkEmitter *ORE); /// Walk the specified region of the CFG (defined by all blocks @@ -433,7 +123,8 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, /// ORE. It returns changed status. bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, Loop *, AliasSetTracker *, - LoopSafetyInfo *, OptimizationRemarkEmitter *ORE); + MemorySSAUpdater *, ICFLoopSafetyInfo *, + OptimizationRemarkEmitter *ORE); /// This function deletes dead loops. The caller of this function needs to /// guarantee that the loop is infact dead. @@ -462,7 +153,8 @@ bool promoteLoopAccessesToScalars(const SmallSetVector<Value *, 8> &, SmallVectorImpl<Instruction *> &, PredIteratorCache &, LoopInfo *, DominatorTree *, const TargetLibraryInfo *, - Loop *, AliasSetTracker *, LoopSafetyInfo *, + Loop *, AliasSetTracker *, + ICFLoopSafetyInfo *, OptimizationRemarkEmitter *); /// Does a BFS from a given node to all of its children inside a given loop. @@ -478,9 +170,80 @@ SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L); /// If it has a value (e.g. {"llvm.distribute", 1} return the value as an /// operand or null otherwise. If the string metadata is not found return /// Optional's not-a-value. -Optional<const MDOperand *> findStringMetadataForLoop(Loop *TheLoop, +Optional<const MDOperand *> findStringMetadataForLoop(const Loop *TheLoop, StringRef Name); +/// Find named metadata for a loop with an integer value. +llvm::Optional<int> getOptionalIntLoopAttribute(Loop *TheLoop, StringRef Name); + +/// Create a new loop identifier for a loop created from a loop transformation. +/// +/// @param OrigLoopID The loop ID of the loop before the transformation. +/// @param FollowupAttrs List of attribute names that contain attributes to be +/// added to the new loop ID. +/// @param InheritOptionsAttrsPrefix Selects which attributes should be inherited +/// from the original loop. The following values +/// are considered: +/// nullptr : Inherit all attributes from @p OrigLoopID. +/// "" : Do not inherit any attribute from @p OrigLoopID; only use +/// those specified by a followup attribute. +/// "<prefix>": Inherit all attributes except those which start with +/// <prefix>; commonly used to remove metadata for the +/// applied transformation. +/// @param AlwaysNew If true, do not try to reuse OrigLoopID and never return +/// None. +/// +/// @return The loop ID for the after-transformation loop. The following values +/// can be returned: +/// None : No followup attribute was found; it is up to the +/// transformation to choose attributes that make sense. +/// @p OrigLoopID: The original identifier can be reused. +/// nullptr : The new loop has no attributes. +/// MDNode* : A new unique loop identifier. +Optional<MDNode *> +makeFollowupLoopID(MDNode *OrigLoopID, ArrayRef<StringRef> FollowupAttrs, + const char *InheritOptionsAttrsPrefix = "", + bool AlwaysNew = false); + +/// Look for the loop attribute that disables all transformation heuristic. +bool hasDisableAllTransformsHint(const Loop *L); + +/// The mode sets how eager a transformation should be applied. +enum TransformationMode { + /// The pass can use heuristics to determine whether a transformation should + /// be applied. + TM_Unspecified, + + /// The transformation should be applied without considering a cost model. + TM_Enable, + + /// The transformation should not be applied. + TM_Disable, + + /// Force is a flag and should not be used alone. + TM_Force = 0x04, + + /// The transformation was directed by the user, e.g. by a #pragma in + /// the source code. If the transformation could not be applied, a + /// warning should be emitted. + TM_ForcedByUser = TM_Enable | TM_Force, + + /// The transformation must not be applied. For instance, `#pragma clang loop + /// unroll(disable)` explicitly forbids any unrolling to take place. Unlike + /// general loop metadata, it must not be dropped. Most passes should not + /// behave differently under TM_Disable and TM_SuppressedByUser. + TM_SuppressedByUser = TM_Disable | TM_Force +}; + +/// @{ +/// Get the mode for LLVM's supported loop transformations. +TransformationMode hasUnrollTransformation(Loop *L); +TransformationMode hasUnrollAndJamTransformation(Loop *L); +TransformationMode hasVectorizeTransformation(Loop *L); +TransformationMode hasDistributeTransformation(Loop *L); +TransformationMode hasLICMVersioningTransformation(Loop *L); +/// @} + /// Set input string into loop metadata by keeping other values intact. void addStringMetadataToLoop(Loop *TheLoop, const char *MDString, unsigned V = 0); @@ -490,6 +253,11 @@ void addStringMetadataToLoop(Loop *TheLoop, const char *MDString, /// estimate can not be made. Optional<unsigned> getLoopEstimatedTripCount(Loop *L); +/// Check inner loop (L) backedge count is known to be invariant on all +/// iterations of its outer loop. If the loop has no parent, this is trivially +/// true. +bool hasIterationCountInvariantInParent(Loop *L, ScalarEvolution &SE); + /// Helper to consistently add the set of standard passes to a loop pass's \c /// AnalysisUsage. /// @@ -497,18 +265,25 @@ Optional<unsigned> getLoopEstimatedTripCount(Loop *L); /// getAnalysisUsage. void getLoopAnalysisUsage(AnalysisUsage &AU); -/// Returns true if the hoister and sinker can handle this instruction. -/// If SafetyInfo is null, we are checking for sinking instructions from -/// preheader to loop body (no speculation). -/// If SafetyInfo is not null, we are checking for hoisting/sinking -/// instructions from loop body to preheader/exit. Check if the instruction -/// can execute speculatively. +/// Returns true if is legal to hoist or sink this instruction disregarding the +/// possible introduction of faults. Reasoning about potential faulting +/// instructions is the responsibility of the caller since it is challenging to +/// do efficiently from within this routine. +/// \p TargetExecutesOncePerLoop is true only when it is guaranteed that the +/// target executes at most once per execution of the loop body. This is used +/// to assess the legality of duplicating atomic loads. Generally, this is +/// true when moving out of loop and not true when moving into loops. /// If \p ORE is set use it to emit optimization remarks. bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, Loop *CurLoop, AliasSetTracker *CurAST, - LoopSafetyInfo *SafetyInfo, + MemorySSAUpdater *MSSAU, bool TargetExecutesOncePerLoop, OptimizationRemarkEmitter *ORE = nullptr); +/// Returns a Min/Max operation corresponding to MinMaxRecurrenceKind. +Value *createMinMaxOp(IRBuilder<> &Builder, + RecurrenceDescriptor::MinMaxRecurrenceKind RK, + Value *Left, Value *Right); + /// Generates an ordered vector reduction using extracts to reduce the value. Value * getOrderedReduction(IRBuilder<> &Builder, Value *Acc, Value *Src, unsigned Op, @@ -527,12 +302,12 @@ Value *getShuffleReduction(IRBuilder<> &Builder, Value *Src, unsigned Op, /// additional information supplied in \p Flags. /// The target is queried to determine if intrinsics or shuffle sequences are /// required to implement the reduction. -Value * -createSimpleTargetReduction(IRBuilder<> &B, const TargetTransformInfo *TTI, - unsigned Opcode, Value *Src, - TargetTransformInfo::ReductionFlags Flags = - TargetTransformInfo::ReductionFlags(), - ArrayRef<Value *> RedOps = None); +Value *createSimpleTargetReduction(IRBuilder<> &B, + const TargetTransformInfo *TTI, + unsigned Opcode, Value *Src, + TargetTransformInfo::ReductionFlags Flags = + TargetTransformInfo::ReductionFlags(), + ArrayRef<Value *> RedOps = None); /// Create a generic target reduction using a recurrence descriptor \p Desc /// The target is queried to determine if intrinsics or shuffle sequences are @@ -548,6 +323,23 @@ Value *createTargetReduction(IRBuilder<> &B, const TargetTransformInfo *TTI, /// Flag set: NSW, NUW, exact, and all of fast-math. void propagateIRFlags(Value *I, ArrayRef<Value *> VL, Value *OpValue = nullptr); +/// Returns true if we can prove that \p S is defined and always negative in +/// loop \p L. +bool isKnownNegativeInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE); + +/// Returns true if we can prove that \p S is defined and always non-negative in +/// loop \p L. +bool isKnownNonNegativeInLoop(const SCEV *S, const Loop *L, + ScalarEvolution &SE); + +/// Returns true if \p S is defined and never is equal to signed/unsigned max. +bool cannotBeMaxInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE, + bool Signed); + +/// Returns true if \p S is defined and never is equal to signed/unsigned min. +bool cannotBeMinInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE, + bool Signed); + } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_LOOPUTILS_H diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index 14615c25d093..fee492be2a90 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -58,6 +58,24 @@ std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions( ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, StringRef VersionCheckName = StringRef()); +/// Creates sanitizer constructor function lazily. If a constructor and init +/// function already exist, this function returns it. Otherwise it calls \c +/// createSanitizerCtorAndInitFunctions. The FunctionsCreatedCallback is invoked +/// in that case, passing the new Ctor and Init function. +/// +/// \return Returns pair of pointers to constructor, and init functions +/// respectively. +std::pair<Function *, Function *> getOrCreateSanitizerCtorAndInitFunctions( + Module &M, StringRef CtorName, StringRef InitName, + ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, + function_ref<void(Function *, Function *)> FunctionsCreatedCallback, + StringRef VersionCheckName = StringRef()); + +// Creates and returns a sanitizer init function without argument if it doesn't +// exist, and adds it to the global constructors list. Otherwise it returns the +// existing function. +Function *getOrCreateInitFunction(Module &M, StringRef Name); + /// Rename all the anon globals in the module using a hash computed from /// the list of public globals in the module. bool nameUnamedGlobals(Module &M); diff --git a/include/llvm/Transforms/Utils/OrderedInstructions.h b/include/llvm/Transforms/Utils/OrderedInstructions.h deleted file mode 100644 index 7f57fde638b8..000000000000 --- a/include/llvm/Transforms/Utils/OrderedInstructions.h +++ /dev/null @@ -1,65 +0,0 @@ -//===- llvm/Transforms/Utils/OrderedInstructions.h -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an efficient way to check for dominance relation between 2 -// instructions. -// -// This interface dispatches to appropriate dominance check given 2 -// instructions, i.e. in case the instructions are in the same basic block, -// OrderedBasicBlock (with instruction numbering and caching) are used. -// Otherwise, dominator tree is used. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H -#define LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Analysis/OrderedBasicBlock.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Operator.h" - -namespace llvm { - -class OrderedInstructions { - /// Used to check dominance for instructions in same basic block. - mutable DenseMap<const BasicBlock *, std::unique_ptr<OrderedBasicBlock>> - OBBMap; - - /// The dominator tree of the parent function. - DominatorTree *DT; - - /// Return true if the first instruction comes before the second in the - /// same basic block. It will create an ordered basic block, if it does - /// not yet exist in OBBMap. - bool localDominates(const Instruction *, const Instruction *) const; - -public: - /// Constructor. - OrderedInstructions(DominatorTree *DT) : DT(DT) {} - - /// Return true if first instruction dominates the second. - bool dominates(const Instruction *, const Instruction *) const; - - /// Return true if the first instruction comes before the second in the - /// dominator tree DFS traversal if they are in different basic blocks, - /// or if the first instruction comes before the second in the same basic - /// block. - bool dfsBefore(const Instruction *, const Instruction *) const; - - /// Invalidate the OrderedBasicBlock cache when its basic block changes. - /// i.e. If an instruction is deleted or added to the basic block, the user - /// should call this function to invalidate the OrderedBasicBlock cache for - /// this basic block. - void invalidateBlock(const BasicBlock *BB) { OBBMap.erase(BB); } -}; - -} // end namespace llvm - -#endif // LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H diff --git a/include/llvm/Transforms/Utils/PredicateInfo.h b/include/llvm/Transforms/Utils/PredicateInfo.h index b53eda7e5a42..2fc38089f3f1 100644 --- a/include/llvm/Transforms/Utils/PredicateInfo.h +++ b/include/llvm/Transforms/Utils/PredicateInfo.h @@ -60,6 +60,7 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" #include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/OrderedInstructions.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Instructions.h" @@ -76,7 +77,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Transforms/Utils/OrderedInstructions.h" #include <algorithm> #include <cassert> #include <cstddef> diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index 4a7911662990..d02607acbbb5 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -76,6 +76,10 @@ public: /// block. bool HasValueForBlock(BasicBlock *BB) const; + /// Return the value for the specified block if the SSAUpdater has one, + /// otherwise return nullptr. + Value *FindValueForBlock(BasicBlock *BB) const; + /// Construct SSA form, materializing a value that is live at the end /// of the specified block. Value *GetValueAtEndOfBlock(BasicBlock *BB); diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h index b7649ba88334..cab0f3e71575 100644 --- a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h +++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -357,10 +357,9 @@ public: BBInfo *Info = *I; if (Info->DefBB != Info) { - // Record the available value at join nodes to speed up subsequent - // uses of this SSAUpdater for the same value. - if (Info->NumPreds > 1) - (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal; + // Record the available value to speed up subsequent uses of this + // SSAUpdater for the same value. + (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal; continue; } diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index d007f909c6a4..025bcd44e310 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -77,21 +77,34 @@ private: OptimizationRemarkEmitter &ORE; bool UnsafeFPShrink; function_ref<void(Instruction *, Value *)> Replacer; + function_ref<void(Instruction *)> Eraser; /// Internal wrapper for RAUW that is the default implementation. /// /// Other users may provide an alternate function with this signature instead /// of this one. - static void replaceAllUsesWithDefault(Instruction *I, Value *With); + static void replaceAllUsesWithDefault(Instruction *I, Value *With) { + I->replaceAllUsesWith(With); + } + + /// Internal wrapper for eraseFromParent that is the default implementation. + static void eraseFromParentDefault(Instruction *I) { I->eraseFromParent(); } /// Replace an instruction's uses with a value using our replacer. void replaceAllUsesWith(Instruction *I, Value *With); + /// Erase an instruction from its parent with our eraser. + void eraseFromParent(Instruction *I); + + Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B); + public: - LibCallSimplifier(const DataLayout &DL, const TargetLibraryInfo *TLI, - OptimizationRemarkEmitter &ORE, - function_ref<void(Instruction *, Value *)> Replacer = - &replaceAllUsesWithDefault); + LibCallSimplifier( + const DataLayout &DL, const TargetLibraryInfo *TLI, + OptimizationRemarkEmitter &ORE, + function_ref<void(Instruction *, Value *)> Replacer = + &replaceAllUsesWithDefault, + function_ref<void(Instruction *)> Eraser = &eraseFromParentDefault); /// optimizeCall - Take the given call instruction and return a more /// optimal value to replace the instruction with or 0 if a more @@ -131,8 +144,8 @@ private: // Math Library Optimizations Value *optimizeCAbs(CallInst *CI, IRBuilder<> &B); - Value *optimizeCos(CallInst *CI, IRBuilder<> &B); Value *optimizePow(CallInst *CI, IRBuilder<> &B); + Value *replacePowWithExp(CallInst *Pow, IRBuilder<> &B); Value *replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B); Value *optimizeExp2(CallInst *CI, IRBuilder<> &B); Value *optimizeFMinFMax(CallInst *CI, IRBuilder<> &B); diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index a6b84af068a5..70e936d75008 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -35,6 +35,15 @@ class ScalarEvolution; using NewLoopsMap = SmallDenseMap<const Loop *, Loop *, 4>; +/// @{ +/// Metadata attribute names +const char *const LLVMLoopUnrollFollowupAll = "llvm.loop.unroll.followup_all"; +const char *const LLVMLoopUnrollFollowupUnrolled = + "llvm.loop.unroll.followup_unrolled"; +const char *const LLVMLoopUnrollFollowupRemainder = + "llvm.loop.unroll.followup_remainder"; +/// @} + const Loop* addClonedBlockToLoopInfo(BasicBlock *OriginalBB, BasicBlock *ClonedBB, LoopInfo *LI, NewLoopsMap &NewLoops); @@ -61,15 +70,16 @@ LoopUnrollResult UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, unsigned PeelCount, bool UnrollRemainder, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC, - OptimizationRemarkEmitter *ORE, bool PreserveLCSSA); + OptimizationRemarkEmitter *ORE, bool PreserveLCSSA, + Loop **RemainderLoop = nullptr); bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count, bool AllowExpensiveTripCount, bool UseEpilogRemainder, bool UnrollRemainder, - LoopInfo *LI, - ScalarEvolution *SE, DominatorTree *DT, - AssumptionCache *AC, - bool PreserveLCSSA); + LoopInfo *LI, ScalarEvolution *SE, + DominatorTree *DT, AssumptionCache *AC, + bool PreserveLCSSA, + Loop **ResultLoop = nullptr); void computePeelCount(Loop *L, unsigned LoopSize, TargetTransformInfo::UnrollingPreferences &UP, @@ -84,7 +94,8 @@ LoopUnrollResult UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount, unsigned TripMultiple, bool UnrollRemainder, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC, - OptimizationRemarkEmitter *ORE); + OptimizationRemarkEmitter *ORE, + Loop **EpilogueLoop = nullptr); bool isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree &DT, DependenceInfo &DI); |
