diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
commit | 67c32a98315f785a9ec9d531c1f571a0196c7463 (patch) | |
tree | 4abb9cbeecc7901726dd0b4a37369596c852e9ef /include/llvm/Transforms/Utils | |
parent | 9f61947910e6ab40de38e6b4034751ef1513200f (diff) |
Diffstat (limited to 'include/llvm/Transforms/Utils')
-rw-r--r-- | include/llvm/Transforms/Utils/BasicBlockUtils.h | 5 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/BuildLibCalls.h | 14 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/Cloning.h | 11 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/CodeExtractor.h | 4 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/CtorUtils.h | 4 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/Local.h | 25 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/LoopUtils.h | 9 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/ModuleUtils.h | 4 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/PromoteMemToReg.h | 4 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/SimplifyLibCalls.h | 175 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/SymbolRewriter.h | 155 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h | 4 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/UnrollLoop.h | 3 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/ValueMapper.h | 21 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/VectorUtils.h | 14 |
15 files changed, 374 insertions, 78 deletions
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index bcafda657c2b..19acf5b2db83 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -133,6 +133,11 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, } } +// SplitAllCriticalEdges - Loop over all of the edges in the CFG, +// breaking critical edges as they are found. Pass P must not be NULL. +// Returns the number of broken edges. +unsigned SplitAllCriticalEdges(Function &F, Pass *P); + /// SplitEdge - Split the edge connecting specified block. Pass P must /// not be NULL. BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 1e407fb468e1..6387c166ec71 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -115,20 +115,6 @@ namespace llvm { /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, const DataLayout *TD, const TargetLibraryInfo *TLI); - - /// SimplifyFortifiedLibCalls - Helper class for folding checked library - /// calls (e.g. __strcpy_chk) into their unchecked counterparts. - class SimplifyFortifiedLibCalls { - protected: - CallInst *CI; - virtual void replaceCall(Value *With) = 0; - virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp, - bool isString) const = 0; - - public: - virtual ~SimplifyFortifiedLibCalls(); - bool fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI); - }; } #endif diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index bdf50ddf5cc6..6584abe822d8 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -43,6 +43,8 @@ class DataLayout; class Loop; class LoopInfo; class AllocaInst; +class AliasAnalysis; +class AssumptionCacheTracker; /// CloneModule - Return an exact copy of the specified module /// @@ -157,13 +159,18 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, /// InlineFunction call, and records the auxiliary results produced by it. class InlineFunctionInfo { public: - explicit InlineFunctionInfo(CallGraph *cg = nullptr, const DataLayout *DL = nullptr) - : CG(cg), DL(DL) {} + explicit InlineFunctionInfo(CallGraph *cg = nullptr, + const DataLayout *DL = nullptr, + AliasAnalysis *AA = nullptr, + AssumptionCacheTracker *ACT = nullptr) + : CG(cg), DL(DL), AA(AA), ACT(ACT) {} /// CG - If non-null, InlineFunction will update the callgraph to reflect the /// changes it makes. CallGraph *CG; const DataLayout *DL; + AliasAnalysis *AA; + AssumptionCacheTracker *ACT; /// StaticAllocas - InlineFunction fills this in with all static allocas that /// get copied into the caller. diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h index 6b41e82dac73..3a96d955cac2 100644 --- a/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H -#define LLVM_TRANSFORMS_UTILS_CODE_EXTRACTOR_H +#ifndef LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H +#define LLVM_TRANSFORMS_UTILS_CODEEXTRACTOR_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SetVector.h" diff --git a/include/llvm/Transforms/Utils/CtorUtils.h b/include/llvm/Transforms/Utils/CtorUtils.h index 81e7b951c252..63e564dcb87a 100644 --- a/include/llvm/Transforms/Utils/CtorUtils.h +++ b/include/llvm/Transforms/Utils/CtorUtils.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H -#define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H +#ifndef LLVM_TRANSFORMS_UTILS_CTORUTILS_H +#define LLVM_TRANSFORMS_UTILS_CTORUTILS_H #include "llvm/ADT/STLExtras.h" diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index c0c690664a9c..14844117f44f 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -34,12 +34,14 @@ class Value; class Pass; class PHINode; class AllocaInst; +class AssumptionCache; class ConstantExpr; class DataLayout; class TargetLibraryInfo; class TargetTransformInfo; class DIBuilder; class AliasAnalysis; +class DominatorTree; template<typename T> class SmallVectorImpl; @@ -136,7 +138,8 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB); /// the basic block that was pointed to. /// bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, - const DataLayout *TD = nullptr); + unsigned BonusInstThreshold, const DataLayout *TD = nullptr, + AssumptionCache *AC = nullptr); /// FlatternCFG - This function is used to flatten a CFG. For /// example, it uses parallel-and and parallel-or mode to collapse @@ -148,7 +151,8 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr); /// and if a predecessor branches to us and one of our successors, fold the /// setcc into the predecessor and use logical operations to pick the right /// destination. -bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr); +bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr, + unsigned BonusInstThreshold = 1); /// DemoteRegToStack - This function takes a virtual register computed by an /// Instruction and replaces it with a slot in the stack frame, allocated via @@ -170,12 +174,18 @@ AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr); /// and it is more than the alignment of the ultimate object, see if we can /// increase the alignment of the ultimate object, making this check succeed. unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, - const DataLayout *TD = nullptr); + const DataLayout *TD = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// getKnownAlignment - Try to infer an alignment for the specified pointer. static inline unsigned getKnownAlignment(Value *V, - const DataLayout *TD = nullptr) { - return getOrEnforceKnownAlignment(V, 0, TD); + const DataLayout *TD = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr) { + return getOrEnforceKnownAlignment(V, 0, TD, AC, CxtI, DT); } /// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the @@ -275,6 +285,11 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, /// Returns true if any basic block was removed. bool removeUnreachableBlocks(Function &F); +/// \brief Combine the metadata of two instructions so that K can replace J +/// +/// Metadata not listed as known via KnownIDs is removed +void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> KnownIDs); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 7e3a74aae93c..f315adc49d15 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -16,6 +16,7 @@ namespace llvm { class AliasAnalysis; +class AssumptionCache; class BasicBlock; class DataLayout; class DominatorTree; @@ -34,7 +35,8 @@ BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); /// passed into it. bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr, - const DataLayout *DL = nullptr); + const DataLayout *DL = nullptr, + AssumptionCache *AC = nullptr); /// \brief Put loop into LCSSA form. /// @@ -47,7 +49,8 @@ bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, /// If ScalarEvolution is passed in, it will be preserved. /// /// Returns true if any modifications are made to the loop. -bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr); +bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, + ScalarEvolution *SE = nullptr); /// \brief Put a loop nest into LCSSA form. /// @@ -58,7 +61,7 @@ bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr); /// If ScalarEvolution is passed in, it will be preserved. /// /// Returns true if any modifications are made to the loop. -bool formLCSSARecursively(Loop &L, DominatorTree &DT, +bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE = nullptr); } diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index 98a19ed426ac..16904f16e369 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -20,7 +20,7 @@ class Module; class Function; class GlobalValue; class GlobalVariable; -template <class PtrType, unsigned SmallSize> class SmallPtrSet; +template <class PtrType> class SmallPtrSetImpl; /// Append F to the list of global ctors of module M with the given Priority. /// This wraps the function in the appropriate structure and stores it along @@ -34,7 +34,7 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority); /// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect /// the initializer elements of that global in Set and return the global itself. GlobalVariable *collectUsedGlobalVariables(Module &M, - SmallPtrSet<GlobalValue *, 8> &Set, + SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index c83fedb0e2ca..d0602bf47c92 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -22,6 +22,7 @@ namespace llvm { class AllocaInst; class DominatorTree; class AliasSetTracker; +class AssumptionCache; /// \brief Return true if this alloca is legal for promotion. /// @@ -41,7 +42,8 @@ bool isAllocaPromotable(const AllocaInst *AI); /// If AST is specified, the specified tracker is updated to reflect changes /// made to the IR. void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT, - AliasSetTracker *AST = nullptr); + AliasSetTracker *AST = nullptr, + AssumptionCache *AC = nullptr); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index a2a5f9a45601..d2f096fd1efd 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -15,40 +15,149 @@ #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H #define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/IRBuilder.h" + namespace llvm { - class Value; - class CallInst; - class DataLayout; - class Instruction; - class TargetLibraryInfo; - class LibCallSimplifierImpl; - - /// LibCallSimplifier - This class implements a collection of optimizations - /// that replace well formed calls to library functions with a more optimal - /// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'. - class LibCallSimplifier { - /// Impl - A pointer to the actual implementation of the library call - /// simplifier. - LibCallSimplifierImpl *Impl; - - public: - LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI, - bool UnsafeFPShrink); - virtual ~LibCallSimplifier(); - - /// optimizeCall - Take the given call instruction and return a more - /// optimal value to replace the instruction with or 0 if a more - /// optimal form can't be found. Note that the returned value may - /// be equal to the instruction being optimized. In this case all - /// other instructions that use the given instruction were modified - /// and the given instruction is dead. - Value *optimizeCall(CallInst *CI); - - /// replaceAllUsesWith - This method is used when the library call - /// simplifier needs to replace instructions other than the library - /// call being modified. - virtual void replaceAllUsesWith(Instruction *I, Value *With) const; - }; +class Value; +class CallInst; +class DataLayout; +class Instruction; +class TargetLibraryInfo; +class BasicBlock; +class Function; + +/// \brief This class implements simplifications for calls to fortified library +/// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to, +/// when possible, replace them with their non-checking counterparts. +/// Other optimizations can also be done, but it's possible to disable them and +/// only simplify needless use of the checking versions (when the object size +/// is unknown) by passing true for OnlyLowerUnknownSize. +class FortifiedLibCallSimplifier { +private: + const DataLayout *DL; + const TargetLibraryInfo *TLI; + bool OnlyLowerUnknownSize; + +public: + FortifiedLibCallSimplifier(const DataLayout *DL, const TargetLibraryInfo *TLI, + bool OnlyLowerUnknownSize = false); + + /// \brief Take the given call instruction and return a more + /// optimal value to replace the instruction with or 0 if a more + /// optimal form can't be found. + /// The call must not be an indirect call. + Value *optimizeCall(CallInst *CI); + +private: + Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCpyChk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCpyChk(CallInst *CI, IRBuilder<> &B); + + /// \brief Checks whether the call \p CI to a fortified libcall is foldable + /// to the non-fortified version. + bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp, + unsigned SizeOp, bool isString); +}; + +/// LibCallSimplifier - This class implements a collection of optimizations +/// that replace well formed calls to library functions with a more optimal +/// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'. +class LibCallSimplifier { +private: + FortifiedLibCallSimplifier FortifiedSimplifier; + const DataLayout *DL; + const TargetLibraryInfo *TLI; + bool UnsafeFPShrink; + +protected: + ~LibCallSimplifier() {} + +public: + LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI); + + /// optimizeCall - Take the given call instruction and return a more + /// optimal value to replace the instruction with or 0 if a more + /// optimal form can't be found. Note that the returned value may + /// be equal to the instruction being optimized. In this case all + /// other instructions that use the given instruction were modified + /// and the given instruction is dead. + /// The call must not be an indirect call. + Value *optimizeCall(CallInst *CI); + + /// replaceAllUsesWith - This method is used when the library call + /// simplifier needs to replace instructions other than the library + /// call being modified. + virtual void replaceAllUsesWith(Instruction *I, Value *With) const; + +private: + // String and Memory Library Call Optimizations + Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCat(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrChr(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrRChr(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeStpCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrNCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrLen(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrPBrk(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrTo(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); + Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); + // Wrapper for all String/Memory Library Call Optimizations + Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B); + + // Math Library Optimizations + Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, bool CheckRetType); + Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B); + Value *optimizeCos(CallInst *CI, IRBuilder<> &B); + Value *optimizePow(CallInst *CI, IRBuilder<> &B); + Value *optimizeExp2(CallInst *CI, IRBuilder<> &B); + Value *optimizeFabs(CallInst *CI, IRBuilder<> &B); + Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B); + Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B); + + // Integer Library Call Optimizations + Value *optimizeFFS(CallInst *CI, IRBuilder<> &B); + Value *optimizeAbs(CallInst *CI, IRBuilder<> &B); + Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B); + Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B); + Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B); + + // Formatting and IO Library Call Optimizations + Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B, + int StreamArg = -1); + Value *optimizePrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B); + Value *optimizePuts(CallInst *CI, IRBuilder<> &B); + + // Helper methods + Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B); + void classifyArgUse(Value *Val, BasicBlock *BB, bool IsFloat, + SmallVectorImpl<CallInst *> &SinCalls, + SmallVectorImpl<CallInst *> &CosCalls, + SmallVectorImpl<CallInst *> &SinCosCalls); + void replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls, Value *Res); + Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B); + Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B); + + /// hasFloatVersion - Checks if there is a float version of the specified + /// function by checking for an existing function with name FuncName + f + bool hasFloatVersion(StringRef FuncName); +}; } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h new file mode 100644 index 000000000000..af7937265795 --- /dev/null +++ b/include/llvm/Transforms/Utils/SymbolRewriter.h @@ -0,0 +1,155 @@ +//===-- SymbolRewriter.h - Symbol Rewriting 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 provides the prototypes and definitions related to the Symbol +// Rewriter pass. +// +// The Symbol Rewriter pass takes a set of rewrite descriptors which define +// transformations for symbol names. These can be either single name to name +// trnsformation or more broad regular expression based transformations. +// +// All the functions are re-written at the IR level. The Symbol Rewriter itself +// is exposed as a module level pass. All symbols at the module level are +// iterated. For any matching symbol, the requested transformation is applied, +// updating references to it as well (a la RAUW). The resulting binary will +// only contain the rewritten symbols. +// +// By performing this operation in the compiler, we are able to catch symbols +// that would otherwise not be possible to catch (e.g. inlined symbols). +// +// This makes it possible to cleanly transform symbols without resorting to +// overly-complex macro tricks and the pre-processor. An example of where this +// is useful is the sanitizers where we would like to intercept a well-defined +// set of functions across the module. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H +#define LLVM_TRANSFORMS_UTILS_SYMBOL_REWRITER_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Module.h" + +namespace llvm { +class MemoryBuffer; + +namespace yaml { +class KeyValueNode; +class MappingNode; +class ScalarNode; +class Stream; +} + +namespace SymbolRewriter { +/// The basic entity representing a rewrite operation. It serves as the base +/// class for any rewrite descriptor. It has a certain set of specializations +/// which describe a particular rewrite. +/// +/// The RewriteMapParser can be used to parse a mapping file that provides the +/// mapping for rewriting the symbols. The descriptors individually describe +/// whether to rewrite a function, global variable, or global alias. Each of +/// these can be selected either by explicitly providing a name for the ones to +/// be rewritten or providing a (posix compatible) regular expression that will +/// select the symbols to rewrite. This descriptor list is passed to the +/// SymbolRewriter pass. +class RewriteDescriptor : public ilist_node<RewriteDescriptor> { + RewriteDescriptor(const RewriteDescriptor &) LLVM_DELETED_FUNCTION; + + const RewriteDescriptor & + operator=(const RewriteDescriptor &) LLVM_DELETED_FUNCTION; + +public: + enum class Type { + Invalid, /// invalid + Function, /// function - descriptor rewrites a function + GlobalVariable, /// global variable - descriptor rewrites a global variable + NamedAlias, /// named alias - descriptor rewrites a global alias + }; + + virtual ~RewriteDescriptor() {} + + Type getType() const { return Kind; } + + virtual bool performOnModule(Module &M) = 0; + +protected: + explicit RewriteDescriptor(Type T) : Kind(T) {} + +private: + const Type Kind; +}; + +typedef iplist<RewriteDescriptor> RewriteDescriptorList; + +class RewriteMapParser { +public: + RewriteMapParser() {} + ~RewriteMapParser() {} + + bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors); + +private: + bool parse(std::unique_ptr<MemoryBuffer> &MapFile, RewriteDescriptorList *DL); + bool parseEntry(yaml::Stream &Stream, yaml::KeyValueNode &Entry, + RewriteDescriptorList *DL); + bool parseRewriteFunctionDescriptor(yaml::Stream &Stream, + yaml::ScalarNode *Key, + yaml::MappingNode *Value, + RewriteDescriptorList *DL); + bool parseRewriteGlobalVariableDescriptor(yaml::Stream &Stream, + yaml::ScalarNode *Key, + yaml::MappingNode *Value, + RewriteDescriptorList *DL); + bool parseRewriteGlobalAliasDescriptor(yaml::Stream &YS, yaml::ScalarNode *K, + yaml::MappingNode *V, + RewriteDescriptorList *DL); +}; +} + +template <> +struct ilist_traits<SymbolRewriter::RewriteDescriptor> + : public ilist_default_traits<SymbolRewriter::RewriteDescriptor> { + mutable ilist_half_node<SymbolRewriter::RewriteDescriptor> Sentinel; + +public: + // createSentinel is used to get a reference to a node marking the end of + // the list. Because the sentinel is relative to this instance, use a + // non-static method. + SymbolRewriter::RewriteDescriptor *createSentinel() const { + // since i[p] lists always publicly derive from the corresponding + // traits, placing a data member in this class will augment the + // i[p]list. Since the NodeTy is expected to publicly derive from + // ilist_node<NodeTy>, there is a legal viable downcast from it to + // NodeTy. We use this trick to superpose i[p]list with a "ghostly" + // NodeTy, which becomes the sentinel. Dereferencing the sentinel is + // forbidden (save the ilist_node<NodeTy>) so no one will ever notice + // the superposition. + return static_cast<SymbolRewriter::RewriteDescriptor *>(&Sentinel); + } + void destroySentinel(SymbolRewriter::RewriteDescriptor *) {} + + SymbolRewriter::RewriteDescriptor *provideInitialHead() const { + return createSentinel(); + } + + SymbolRewriter::RewriteDescriptor * + ensureHead(SymbolRewriter::RewriteDescriptor *&) const { + return createSentinel(); + } + + static void noteHead(SymbolRewriter::RewriteDescriptor *, + SymbolRewriter::RewriteDescriptor *) {} +}; + +ModulePass *createRewriteSymbolsPass(); +ModulePass *createRewriteSymbolsPass(SymbolRewriter::RewriteDescriptorList &); +} + +#endif diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 7ac2572f9af3..550292f6b7a3 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H -#define LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H +#ifndef LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H +#define LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H #include "llvm/Pass.h" diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index aaadd7d48bdc..807367cd4b12 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -18,6 +18,7 @@ namespace llvm { +class AssumptionCache; class Loop; class LoopInfo; class LPPassManager; @@ -25,7 +26,7 @@ class Pass; bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime, unsigned TripMultiple, LoopInfo *LI, Pass *PP, - LPPassManager *LPM); + LPPassManager *LPM, AssumptionCache *AC); bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, LPPassManager* LPM); diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index 5774763575d3..047ab818711b 100644 --- a/include/llvm/Transforms/Utils/ValueMapper.h +++ b/include/llvm/Transforms/Utils/ValueMapper.h @@ -71,20 +71,23 @@ namespace llvm { ValueMapTypeRemapper *TypeMapper = nullptr, ValueMaterializer *Materializer = nullptr); + Metadata *MapMetadata(const Metadata *MD, ValueToValueMapTy &VM, + RemapFlags Flags = RF_None, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); + + /// MapMetadata - provide versions that preserve type safety for MDNodes. + MDNode *MapMetadata(const MDNode *MD, ValueToValueMapTy &VM, + RemapFlags Flags = RF_None, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); + void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, ValueMapTypeRemapper *TypeMapper = nullptr, ValueMaterializer *Materializer = nullptr); - /// MapValue - provide versions that preserve type safety for MDNode and - /// Constants. - inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM, - RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = nullptr, - ValueMaterializer *Materializer = nullptr) { - return cast<MDNode>(MapValue((const Value*)V, VM, Flags, TypeMapper, - Materializer)); - } + /// MapValue - provide versions that preserve type safety for Constants. inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, ValueMapTypeRemapper *TypeMapper = nullptr, diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h index 44a7149eee98..b47acf517b37 100644 --- a/include/llvm/Transforms/Utils/VectorUtils.h +++ b/include/llvm/Transforms/Utils/VectorUtils.h @@ -14,8 +14,8 @@ #ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H #define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H -#include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Target/TargetLibraryInfo.h" namespace llvm { @@ -36,6 +36,8 @@ static inline bool isTriviallyVectorizable(Intrinsic::ID ID) { case Intrinsic::log10: case Intrinsic::log2: case Intrinsic::fabs: + case Intrinsic::minnum: + case Intrinsic::maxnum: case Intrinsic::copysign: case Intrinsic::floor: case Intrinsic::ceil: @@ -99,7 +101,7 @@ getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) { if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) { Intrinsic::ID ID = II->getIntrinsicID(); if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start || - ID == Intrinsic::lifetime_end) + ID == Intrinsic::lifetime_end || ID == Intrinsic::assume) return ID; else return Intrinsic::not_intrinsic; @@ -153,6 +155,14 @@ getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) { case LibFunc::fabsf: case LibFunc::fabsl: return checkUnaryFloatSignature(*CI, Intrinsic::fabs); + case LibFunc::fmin: + case LibFunc::fminf: + case LibFunc::fminl: + return checkBinaryFloatSignature(*CI, Intrinsic::minnum); + case LibFunc::fmax: + case LibFunc::fmaxf: + case LibFunc::fmaxl: + return checkBinaryFloatSignature(*CI, Intrinsic::maxnum); case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: |