Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -2822,6 +2822,59 @@ 4 byte gap between the two fields. This gap represents padding which does not carry useful data and need not be preserved. +'``noalias``' and '``alias.scope``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``noalias`` and ``alias.scope`` metadata provide the ability to specify generic +noalias memory-access sets. This means that some collection of memory access +instructions (loads, stores, memory-accessing calls, etc.) that carry +``noalias`` metadata can specifically be specified not to alias with some other +collection of memory access instructions that carry ``alias.scope`` metadata. +Each type of metadata specifies a list of scopes, and when evaluating an +aliasing query, if one of the instructions has a scope in its ``alias.scope`` +list that is identical to a scope in the other instruction's ``noalias`` list, +or is a descendant (in the scope hierarchy) of a scope in the other +instruction's ``noalias`` list , then the two memory accesses are assumed not +to alias. + +The metadata identifying each scope is itself a list containing one or two +entries. The first entry is the name of the scope. Note that if the name is a +string then it can be combined accross functions and translation units. A +self-reference can be used to create globally unqiue scope names. +Optionally, a metadata reference to a parent scope can be provided as a second +entry in the list. + +For example, + +.. code-block:: llvm + + ; A root scope (which doubles as a list of itself): + !0 = metadata !{metadata !0} + + ; Two child scopes (which must be self-referential to avoid being "uniqued"): + !1 = metadata !{metadata !2} ; A list containing only scope !2 + !2 = metadata !{metadata !2, metadata !0} ; Scope !2 is a descendant of scope !0 + + !3 = metadata !{metadata !4} ; A list containing only scope !4 + !4 = metadata !{metadata !4, metadata !0} ; Scope !4 is a descendant of scope !0 + + ; These two instructions don't alias: + %0 = load float* %c, align 4, !alias.scope !0 + store float %0, float* %arrayidx.i, align 4, !noalias !0 + + ; These two instructions may alias (scope !2 and scope !4 are peers): + %2 = load float* %c, align 4, !alias.scope !1 + store float %2, float* %arrayidx.i2, align 4, !noalias !3 + + ; These two instructions don't alias (scope !2 is a descendant of scope !0 + ; and the store does not alias with anything in scope !0 or any of its descendants): + %2 = load float* %c, align 4, !alias.scope !1 + store float %0, float* %arrayidx.i, align 4, !noalias !0 + + ; These two instructions may alias: + %2 = load float* %c, align 4, !alias.scope !0 + store float %0, float* %arrayidx.i, align 4, !noalias !1 + '``fpmath``' Metadata ^^^^^^^^^^^^^^^^^^^^^ Index: include/llvm-c/Transforms/Scalar.h =================================================================== --- include/llvm-c/Transforms/Scalar.h +++ include/llvm-c/Transforms/Scalar.h @@ -132,6 +132,9 @@ /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); +/** See llvm::createScopedNoAliasAAPass function */ +void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM); + /** See llvm::createBasicAliasAnalysisPass function */ void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); Index: include/llvm/Analysis/AliasAnalysis.h =================================================================== --- include/llvm/Analysis/AliasAnalysis.h +++ include/llvm/Analysis/AliasAnalysis.h @@ -39,6 +39,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Metadata.h" namespace llvm { @@ -112,13 +113,14 @@ /// there are restrictions on stepping out of one object and into another. /// See http://llvm.org/docs/LangRef.html#pointeraliasing uint64_t Size; - /// TBAATag - The metadata node which describes the TBAA type of - /// the location, or null if there is no known unique tag. - const MDNode *TBAATag; + /// AATags - The metadata nodes which describes the aliasing of the + /// location (each member is null if that kind of information is + /// unavailable).. + AAMDNodes AATags; explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize, - const MDNode *N = nullptr) - : Ptr(P), Size(S), TBAATag(N) {} + const AAMDNodes &N = AAMDNodes()) + : Ptr(P), Size(S), AATags(N) {} Location getWithNewPtr(const Value *NewPtr) const { Location Copy(*this); @@ -132,9 +134,9 @@ return Copy; } - Location getWithoutTBAATag() const { + Location getWithoutAATags() const { Location Copy(*this); - Copy.TBAATag = nullptr; + Copy.AATags = AAMDNodes(); return Copy; } }; @@ -578,13 +580,13 @@ static unsigned getHashValue(const AliasAnalysis::Location &Val) { return DenseMapInfo::getHashValue(Val.Ptr) ^ DenseMapInfo::getHashValue(Val.Size) ^ - DenseMapInfo::getHashValue(Val.TBAATag); + DenseMapInfo::getHashValue(Val.AATags); } static bool isEqual(const AliasAnalysis::Location &LHS, const AliasAnalysis::Location &RHS) { return LHS.Ptr == RHS.Ptr && LHS.Size == RHS.Size && - LHS.TBAATag == RHS.TBAATag; + LHS.AATags == RHS.AATags; } }; Index: include/llvm/Analysis/AliasSetTracker.h =================================================================== --- include/llvm/Analysis/AliasSetTracker.h +++ include/llvm/Analysis/AliasSetTracker.h @@ -20,6 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" #include @@ -40,11 +41,11 @@ PointerRec **PrevInList, *NextInList; AliasSet *AS; uint64_t Size; - const MDNode *TBAAInfo; + AAMDNodes AAInfo; public: PointerRec(Value *V) : Val(V), PrevInList(nullptr), NextInList(nullptr), AS(nullptr), Size(0), - TBAAInfo(DenseMapInfo::getEmptyKey()) {} + AAInfo(DenseMapInfo::getEmptyKey()) {} Value *getValue() const { return Val; } @@ -56,27 +57,27 @@ return &NextInList; } - void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) { + void updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) { if (NewSize > Size) Size = NewSize; - if (TBAAInfo == DenseMapInfo::getEmptyKey()) - // We don't have a TBAAInfo yet. Set it to NewTBAAInfo. - TBAAInfo = NewTBAAInfo; - else if (TBAAInfo != NewTBAAInfo) - // NewTBAAInfo conflicts with TBAAInfo. - TBAAInfo = DenseMapInfo::getTombstoneKey(); + if (AAInfo == DenseMapInfo::getEmptyKey()) + // We don't have a AAInfo yet. Set it to NewAAInfo. + AAInfo = NewAAInfo; + else if (AAInfo != NewAAInfo) + // NewAAInfo conflicts with AAInfo. + AAInfo = DenseMapInfo::getTombstoneKey(); } uint64_t getSize() const { return Size; } - /// getTBAAInfo - Return the TBAAInfo, or null if there is no + /// getAAInfo - Return the AAInfo, or null if there is no /// information or conflicting information. - const MDNode *getTBAAInfo() const { - // If we have missing or conflicting TBAAInfo, return null. - if (TBAAInfo == DenseMapInfo::getEmptyKey() || - TBAAInfo == DenseMapInfo::getTombstoneKey()) - return nullptr; - return TBAAInfo; + AAMDNodes getAAInfo() const { + // If we have missing or conflicting AAInfo, return null. + if (AAInfo == DenseMapInfo::getEmptyKey() || + AAInfo == DenseMapInfo::getTombstoneKey()) + return AAMDNodes(); + return AAInfo; } AliasSet *getAliasSet(AliasSetTracker &AST) { @@ -204,7 +205,7 @@ Value *getPointer() const { return CurNode->getValue(); } uint64_t getSize() const { return CurNode->getSize(); } - const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); } + AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); } iterator& operator++() { // Preincrement assert(CurNode && "Advancing past AliasSet.end()!"); @@ -250,7 +251,7 @@ void removeFromTracker(AliasSetTracker &AST); void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool KnownMustAlias = false); void addUnknownInst(Instruction *I, AliasAnalysis &AA); void removeUnknownInst(Instruction *I) { @@ -267,7 +268,7 @@ /// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// - bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, + bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const; bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; }; @@ -322,7 +323,7 @@ /// These methods return true if inserting the instruction resulted in the /// addition of a new alias set (i.e., the pointer did not alias anything). /// - bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location + bool add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); // Add a loc. bool add(LoadInst *LI); bool add(StoreInst *SI); bool add(VAArgInst *VAAI); @@ -335,7 +336,7 @@ /// be aliased by the specified instruction. These methods return true if any /// alias sets were eliminated. // Remove a location - bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); + bool remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); bool remove(LoadInst *LI); bool remove(StoreInst *SI); bool remove(VAArgInst *VAAI); @@ -354,20 +355,20 @@ /// true if a new alias set is created to contain the pointer (because the /// pointer didn't alias anything). AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool *New = nullptr); /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, - const MDNode *TBAAInfo) { - return findAliasSetForPointer(P, Size, TBAAInfo); + const AAMDNodes &AAInfo) { + return findAliasSetForPointer(P, Size, AAInfo); } /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const; + bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. @@ -414,16 +415,16 @@ return *Entry; } - AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo, + AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo, AliasSet::AccessType E, bool &NewSet) { NewSet = false; - AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet); + AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet); AS.AccessTy |= E; return AS; } AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, - const MDNode *TBAAInfo); + const AAMDNodes &AAInfo); AliasSet *findAliasSetForUnknownInst(Instruction *Inst); }; Index: include/llvm/Analysis/Loads.h =================================================================== --- include/llvm/Analysis/Loads.h +++ include/llvm/Analysis/Loads.h @@ -44,14 +44,14 @@ /// If it is set to 0, it will scan the whole block. You can also optionally /// specify an alias analysis implementation, which makes this more precise. /// -/// If TBAATag is non-null and a load or store is found, the TBAA tag from the -/// load or store is recorded there. If there is no TBAA tag or if no access +/// If AATags is non-null and a load or store is found, the AA tags from the +/// load or store are recorded there. If there are no AA tags or if no access /// is found, it is left unmodified. Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan = 6, AliasAnalysis *AA = nullptr, - MDNode **TBAATag = nullptr); + AAMDNodes *AATags = nullptr); } Index: include/llvm/Analysis/MemoryDependenceAnalysis.h =================================================================== --- include/llvm/Analysis/MemoryDependenceAnalysis.h +++ include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -281,12 +281,12 @@ /// Size - The maximum size of the dereferences of the /// pointer. May be UnknownSize if the sizes are unknown. uint64_t Size; - /// TBAATag - The TBAA tag associated with dereferences of the - /// pointer. May be null if there are no tags or conflicting tags. - const MDNode *TBAATag; + /// AATags - The AA tags associated with dereferences of the + /// pointer. The members may be null if there are no tags or + /// conflicting tags. + AAMDNodes AATags; - NonLocalPointerInfo() - : Size(AliasAnalysis::UnknownSize), TBAATag(nullptr) {} + NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {} }; /// CachedNonLocalPointerInfo - This map stores the cached results of doing Index: include/llvm/Analysis/Passes.h =================================================================== --- include/llvm/Analysis/Passes.h +++ include/llvm/Analysis/Passes.h @@ -88,6 +88,13 @@ //===--------------------------------------------------------------------===// // + // createScopedNoAliasAAPass - This pass implements metadata-based + // scoped noalias analysis. + // + ImmutablePass *createScopedNoAliasAAPass(); + + //===--------------------------------------------------------------------===// + // // createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based // alias analysis. // Index: include/llvm/CodeGen/MachineFunction.h =================================================================== --- include/llvm/CodeGen/MachineFunction.h +++ include/llvm/CodeGen/MachineFunction.h @@ -21,6 +21,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/Recycler.h" @@ -399,7 +400,7 @@ MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo, unsigned f, uint64_t s, unsigned base_alignment, - const MDNode *TBAAInfo = nullptr, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); /// getMachineMemOperand - Allocate a new MachineMemOperand by copying Index: include/llvm/CodeGen/MachineMemOperand.h =================================================================== --- include/llvm/CodeGen/MachineMemOperand.h +++ include/llvm/CodeGen/MachineMemOperand.h @@ -18,6 +18,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" // PointerLikeTypeTraits #include "llvm/Support/DataTypes.h" @@ -91,7 +92,7 @@ MachinePointerInfo PtrInfo; uint64_t Size; unsigned Flags; - const MDNode *TBAAInfo; + AAMDNodes AAInfo; const MDNode *Ranges; public: @@ -117,7 +118,8 @@ /// MachineMemOperand - Construct an MachineMemOperand object with the /// specified PtrInfo, flags, size, and base alignment. MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s, - unsigned base_alignment, const MDNode *TBAAInfo = nullptr, + unsigned base_alignment, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } @@ -161,8 +163,8 @@ /// base address, without the offset. uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; } - /// getTBAAInfo - Return the TBAA tag for the memory reference. - const MDNode *getTBAAInfo() const { return TBAAInfo; } + /// getAAInfo - Return the AA tags for the memory reference. + AAMDNodes getAAInfo() const { return AAInfo; } /// getRanges - Return the range tag for the memory reference. const MDNode *getRanges() const { return Ranges; } Index: include/llvm/CodeGen/SelectionDAG.h =================================================================== --- include/llvm/CodeGen/SelectionDAG.h +++ include/llvm/CodeGen/SelectionDAG.h @@ -787,7 +787,7 @@ SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, - const MDNode *TBAAInfo = nullptr, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO); @@ -795,7 +795,7 @@ SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO); @@ -806,7 +806,7 @@ SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, - unsigned Alignment, const MDNode *TBAAInfo = nullptr, + unsigned Alignment, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, SDLoc dl, @@ -818,14 +818,14 @@ SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT TVT, bool isNonTemporal, bool isVolatile, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, Index: include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- include/llvm/CodeGen/SelectionDAGNodes.h +++ include/llvm/CodeGen/SelectionDAGNodes.h @@ -1088,8 +1088,8 @@ // Returns the offset from the location of the access. int64_t getSrcValueOffset() const { return MMO->getOffset(); } - /// Returns the TBAAInfo that describes the dereference. - const MDNode *getTBAAInfo() const { return MMO->getTBAAInfo(); } + /// Returns the AA info that describes the dereference. + AAMDNodes getAAInfo() const { return MMO->getAAInfo(); } /// Returns the Ranges that describes the dereference. const MDNode *getRanges() const { return MMO->getRanges(); } Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -364,43 +364,60 @@ /// \brief Create and insert a memset to the specified pointer and the /// specified value. /// - /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr) { - return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memcpy between the specified pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr) { + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, - TBAAStructTag); + TBAAStructTag, ScopeTag, NoAliasTag); } CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr); + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memmove between the specified /// pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr) { - return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create a lifetime.start intrinsic. /// Index: include/llvm/IR/Instruction.h =================================================================== --- include/llvm/IR/Instruction.h +++ include/llvm/IR/Instruction.h @@ -25,6 +25,7 @@ class FastMathFlags; class LLVMContext; class MDNode; +struct AAMDNodes; template class SymbolTableListTraits; @@ -168,6 +169,11 @@ getAllMetadataOtherThanDebugLocImpl(MDs); } + /// getAAMetadata - Fills the AAMDNodes structure with AA metadata from + /// this instruction. When Merge is true, the existing AA metadata is + /// merged with that from this instruction providing the most-general result. + void getAAMetadata(AAMDNodes &N, bool Merge = false) const; + /// setMetadata - Set the metadata of the specified kind to the specified /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. @@ -189,6 +195,10 @@ return dropUnknownMetadata(IDs); } + /// setAAMetadata - Sets the metadata on this instruction from the + /// AAMDNodes structure. + void setAAMetadata(const AAMDNodes &N); + /// setDebugLoc - Set the debug location information for this instruction. void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -52,7 +52,9 @@ MD_fpmath = 3, // "fpmath" MD_range = 4, // "range" MD_tbaa_struct = 5, // "tbaa.struct" - MD_invariant_load = 6 // "invariant.load" + MD_invariant_load = 6, // "invariant.load" + MD_alias_scope = 7, // "alias.scope" + MD_noalias = 8 // "noalias" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. Index: include/llvm/IR/MDBuilder.h =================================================================== --- include/llvm/IR/MDBuilder.h +++ include/llvm/IR/MDBuilder.h @@ -15,6 +15,7 @@ #ifndef LLVM_IR_MDBUILDER_H #define LLVM_IR_MDBUILDER_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include @@ -25,7 +26,6 @@ class LLVMContext; class MDNode; class MDString; -class StringRef; class MDBuilder { LLVMContext &Context; @@ -63,24 +63,49 @@ MDNode *createRange(const APInt &Lo, const APInt &Hi); //===------------------------------------------------------------------===// - // TBAA metadata. + // AA metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata appropriate for a TBAA root node. Each returned +protected: + /// \brief Return metadata appropriate for a AA root node (scope or TBAA). + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAARoot(StringRef Name = StringRef()); + +public: + /// \brief Return metadata appropriate for a TBAA root node. Each returned /// node is distinct from all other metadata and will never be identified /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot(); + MDNode *createAnonymousTBAARoot() { + return createAnonymousAARoot(); + } + + /// \brief Return metadata appropriate for an alias scope root node. + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAliasScopeRoot(StringRef Name = StringRef()) { + return createAnonymousAARoot(Name); + } /// \brief Return metadata appropriate for a TBAA root node with the given /// name. This may be identified (uniqued) with other roots with the same /// name. MDNode *createTBAARoot(StringRef Name); + /// \brief Return metadata appropriate for an alias scope root node with + /// the given name. This may be identified (uniqued) with other roots with + /// the same name. + MDNode *createAliasScopeRoot(StringRef Name); + /// \brief Return metadata for a non-root TBAA node with the given name, /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. MDNode *createTBAANode(StringRef Name, MDNode *Parent, bool isConstant = false); + /// \brief Return metadata for a non-root alias scope node with the given + /// name and parent in the scope tree. + MDNode *createAliasScopeNode(StringRef Name, MDNode *Parent); + struct TBAAStructField { uint64_t Offset; uint64_t Size; Index: include/llvm/IR/Metadata.h =================================================================== --- include/llvm/IR/Metadata.h +++ include/llvm/IR/Metadata.h @@ -17,6 +17,7 @@ #define LLVM_IR_METADATA_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" @@ -66,6 +67,57 @@ } }; +/// AAMDNodes - A collection of metadata nodes that might be associated with a +/// memory access used by the alias-analysis infrastructure. +struct AAMDNodes { + AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr, MDNode *N = nullptr) + : TBAA(T), Scope(S), NoAlias(S) {} + + bool operator == (const AAMDNodes &A) const { + return equals(A); + } + + bool operator != (const AAMDNodes &A) const { + return !equals(A); + } + + operator bool() const { + return TBAA || Scope || NoAlias; + } + + /// TBAA - The tag for type-based alias analysis. + MDNode *TBAA; + + /// Scope - The tag for alias scope specification (used with noalias). + MDNode *Scope; + + /// NoAlias - The tag specifying the noalias scope. + MDNode *NoAlias; + +protected: + bool equals(const AAMDNodes &A) const { + return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias; + } +}; + +// Specialize DenseMapInfo for AAMDNodes. +template<> +struct DenseMapInfo { + static inline AAMDNodes getEmptyKey() { + return AAMDNodes(DenseMapInfo::getEmptyKey(), 0, 0); + } + static inline AAMDNodes getTombstoneKey() { + return AAMDNodes(DenseMapInfo::getTombstoneKey(), 0, 0); + } + static unsigned getHashValue(const AAMDNodes &Val) { + return DenseMapInfo::getHashValue(Val.TBAA) ^ + DenseMapInfo::getHashValue(Val.Scope) ^ + DenseMapInfo::getHashValue(Val.NoAlias); + } + static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) { + return LHS == RHS; + } +}; class MDNodeOperand; @@ -170,7 +222,10 @@ bool isTBAAVtableAccess() const; /// Methods for metadata merging. + static MDNode *concatenate(MDNode *A, MDNode *B); + static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); + static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); private: Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -262,6 +262,7 @@ void initializeTargetLibraryInfoPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); +void initializeScopedNoAliasAAPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -56,6 +56,7 @@ (void) llvm::createLibCallAliasAnalysisPass(nullptr); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); + (void) llvm::createScopedNoAliasAAPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); Index: lib/Analysis/AliasAnalysis.cpp =================================================================== --- lib/Analysis/AliasAnalysis.cpp +++ lib/Analysis/AliasAnalysis.cpp @@ -252,35 +252,45 @@ //===----------------------------------------------------------------------===// AliasAnalysis::Location AliasAnalysis::getLocation(const LoadInst *LI) { + AAMDNodes AATags; + LI->getAAMetadata(AATags); + return Location(LI->getPointerOperand(), - getTypeStoreSize(LI->getType()), - LI->getMetadata(LLVMContext::MD_tbaa)); + getTypeStoreSize(LI->getType()), AATags); } AliasAnalysis::Location AliasAnalysis::getLocation(const StoreInst *SI) { + AAMDNodes AATags; + SI->getAAMetadata(AATags); + return Location(SI->getPointerOperand(), - getTypeStoreSize(SI->getValueOperand()->getType()), - SI->getMetadata(LLVMContext::MD_tbaa)); + getTypeStoreSize(SI->getValueOperand()->getType()), AATags); } AliasAnalysis::Location AliasAnalysis::getLocation(const VAArgInst *VI) { - return Location(VI->getPointerOperand(), - UnknownSize, - VI->getMetadata(LLVMContext::MD_tbaa)); + AAMDNodes AATags; + VI->getAAMetadata(AATags); + + return Location(VI->getPointerOperand(), UnknownSize, AATags); } AliasAnalysis::Location AliasAnalysis::getLocation(const AtomicCmpXchgInst *CXI) { + AAMDNodes AATags; + CXI->getAAMetadata(AATags); + return Location(CXI->getPointerOperand(), getTypeStoreSize(CXI->getCompareOperand()->getType()), - CXI->getMetadata(LLVMContext::MD_tbaa)); + AATags); } AliasAnalysis::Location AliasAnalysis::getLocation(const AtomicRMWInst *RMWI) { + AAMDNodes AATags; + RMWI->getAAMetadata(AATags); + return Location(RMWI->getPointerOperand(), - getTypeStoreSize(RMWI->getValOperand()->getType()), - RMWI->getMetadata(LLVMContext::MD_tbaa)); + getTypeStoreSize(RMWI->getValOperand()->getType()), AATags); } AliasAnalysis::Location @@ -289,11 +299,12 @@ if (ConstantInt *C = dyn_cast(MTI->getLength())) Size = C->getValue().getZExtValue(); - // memcpy/memmove can have TBAA tags. For memcpy, they apply + // memcpy/memmove can have AA tags. For memcpy, they apply // to both the source and the destination. - MDNode *TBAATag = MTI->getMetadata(LLVMContext::MD_tbaa); - - return Location(MTI->getRawSource(), Size, TBAATag); + AAMDNodes AATags; + MTI->getAAMetadata(AATags); + + return Location(MTI->getRawSource(), Size, AATags); } AliasAnalysis::Location @@ -302,11 +313,12 @@ if (ConstantInt *C = dyn_cast(MTI->getLength())) Size = C->getValue().getZExtValue(); - // memcpy/memmove can have TBAA tags. For memcpy, they apply + // memcpy/memmove can have AA tags. For memcpy, they apply // to both the source and the destination. - MDNode *TBAATag = MTI->getMetadata(LLVMContext::MD_tbaa); - - return Location(MTI->getRawDest(), Size, TBAATag); + AAMDNodes AATags; + MTI->getMetadata(AATags); + + return Location(MTI->getRawDest(), Size, AATags); } Index: lib/Analysis/AliasAnalysisEvaluator.cpp =================================================================== --- lib/Analysis/AliasAnalysisEvaluator.cpp +++ lib/Analysis/AliasAnalysisEvaluator.cpp @@ -43,7 +43,7 @@ static cl::opt PrintRef("print-ref", cl::ReallyHidden); static cl::opt PrintModRef("print-modref", cl::ReallyHidden); -static cl::opt EvalTBAA("evaluate-tbaa", cl::ReallyHidden); +static cl::opt EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden); namespace { class AAEval : public FunctionPass { @@ -153,9 +153,9 @@ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { if (I->getType()->isPointerTy()) // Add all pointer instructions. Pointers.insert(&*I); - if (EvalTBAA && isa(&*I)) + if (EvalAAMD && isa(&*I)) Loads.insert(&*I); - if (EvalTBAA && isa(&*I)) + if (EvalAAMD && isa(&*I)) Stores.insert(&*I); Instruction &Inst = *I; if (CallSite CS = cast(&Inst)) { @@ -213,7 +213,7 @@ } } - if (EvalTBAA) { + if (EvalAAMD) { // iterate over all pairs of load, store for (SetVector::iterator I1 = Loads.begin(), E = Loads.end(); I1 != E; ++I1) { Index: lib/Analysis/AliasSetTracker.cpp =================================================================== --- lib/Analysis/AliasSetTracker.cpp +++ lib/Analysis/AliasSetTracker.cpp @@ -47,10 +47,10 @@ // If the pointers are not a must-alias pair, this set becomes a may alias. if (AA.alias(AliasAnalysis::Location(L->getValue(), L->getSize(), - L->getTBAAInfo()), + L->getAAInfo()), AliasAnalysis::Location(R->getValue(), R->getSize(), - R->getTBAAInfo())) + R->getAAInfo())) != AliasAnalysis::MustAlias) AliasTy = MayAlias; } @@ -92,7 +92,7 @@ } void AliasSet::addPointer(AliasSetTracker &AST, PointerRec &Entry, - uint64_t Size, const MDNode *TBAAInfo, + uint64_t Size, const AAMDNodes &AAInfo, bool KnownMustAlias) { assert(!Entry.hasAliasSet() && "Entry already in set!"); @@ -102,17 +102,17 @@ AliasAnalysis &AA = AST.getAliasAnalysis(); AliasAnalysis::AliasResult Result = AA.alias(AliasAnalysis::Location(P->getValue(), P->getSize(), - P->getTBAAInfo()), - AliasAnalysis::Location(Entry.getValue(), Size, TBAAInfo)); + P->getAAInfo()), + AliasAnalysis::Location(Entry.getValue(), Size, AAInfo)); if (Result != AliasAnalysis::MustAlias) AliasTy = MayAlias; else // First entry of must alias must have maximum size! - P->updateSizeAndTBAAInfo(Size, TBAAInfo); + P->updateSizeAndAAInfo(Size, AAInfo); assert(Result != AliasAnalysis::NoAlias && "Cannot be part of must set!"); } Entry.setAliasSet(this); - Entry.updateSizeAndTBAAInfo(Size, TBAAInfo); + Entry.updateSizeAndAAInfo(Size, AAInfo); // Add it to the end of the list... assert(*PtrListEnd == nullptr && "End of list is not null?"); @@ -140,7 +140,7 @@ /// alias one of the members in the set. /// bool AliasSet::aliasesPointer(const Value *Ptr, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, AliasAnalysis &AA) const { if (AliasTy == MustAlias) { assert(UnknownInsts.empty() && "Illegal must alias set!"); @@ -151,23 +151,23 @@ assert(SomePtr && "Empty must-alias set??"); return AA.alias(AliasAnalysis::Location(SomePtr->getValue(), SomePtr->getSize(), - SomePtr->getTBAAInfo()), - AliasAnalysis::Location(Ptr, Size, TBAAInfo)); + SomePtr->getAAInfo()), + AliasAnalysis::Location(Ptr, Size, AAInfo)); } // If this is a may-alias set, we have to check all of the pointers in the set // to be sure it doesn't alias the set... for (iterator I = begin(), E = end(); I != E; ++I) - if (AA.alias(AliasAnalysis::Location(Ptr, Size, TBAAInfo), + if (AA.alias(AliasAnalysis::Location(Ptr, Size, AAInfo), AliasAnalysis::Location(I.getPointer(), I.getSize(), - I.getTBAAInfo()))) + I.getAAInfo()))) return true; // Check the unknown instructions... if (!UnknownInsts.empty()) { for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) if (AA.getModRefInfo(UnknownInsts[i], - AliasAnalysis::Location(Ptr, Size, TBAAInfo)) != + AliasAnalysis::Location(Ptr, Size, AAInfo)) != AliasAnalysis::NoModRef) return true; } @@ -190,7 +190,7 @@ for (iterator I = begin(), E = end(); I != E; ++I) if (AA.getModRefInfo(Inst, AliasAnalysis::Location(I.getPointer(), I.getSize(), - I.getTBAAInfo())) != + I.getAAInfo())) != AliasAnalysis::NoModRef) return true; @@ -216,10 +216,10 @@ /// AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr, uint64_t Size, - const MDNode *TBAAInfo) { + const AAMDNodes &AAInfo) { AliasSet *FoundSet = nullptr; for (iterator I = begin(), E = end(); I != E; ++I) { - if (I->Forward || !I->aliasesPointer(Ptr, Size, TBAAInfo, AA)) continue; + if (I->Forward || !I->aliasesPointer(Ptr, Size, AAInfo, AA)) continue; if (!FoundSet) { // If this is the first alias set ptr can go into. FoundSet = I; // Remember it. @@ -235,9 +235,9 @@ /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. bool AliasSetTracker::containsPointer(Value *Ptr, uint64_t Size, - const MDNode *TBAAInfo) const { + const AAMDNodes &AAInfo) const { for (const_iterator I = begin(), E = end(); I != E; ++I) - if (!I->Forward && I->aliasesPointer(Ptr, Size, TBAAInfo, AA)) + if (!I->Forward && I->aliasesPointer(Ptr, Size, AAInfo, AA)) return true; return false; } @@ -264,67 +264,75 @@ /// getAliasSetForPointer - Return the alias set that the specified pointer /// lives in. AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool *New) { AliasSet::PointerRec &Entry = getEntryFor(Pointer); // Check to see if the pointer is already known. if (Entry.hasAliasSet()) { - Entry.updateSizeAndTBAAInfo(Size, TBAAInfo); + Entry.updateSizeAndAAInfo(Size, AAInfo); // Return the set! return *Entry.getAliasSet(*this)->getForwardedTarget(*this); } - if (AliasSet *AS = findAliasSetForPointer(Pointer, Size, TBAAInfo)) { + if (AliasSet *AS = findAliasSetForPointer(Pointer, Size, AAInfo)) { // Add it to the alias set it aliases. - AS->addPointer(*this, Entry, Size, TBAAInfo); + AS->addPointer(*this, Entry, Size, AAInfo); return *AS; } if (New) *New = true; // Otherwise create a new alias set to hold the loaded pointer. AliasSets.push_back(new AliasSet()); - AliasSets.back().addPointer(*this, Entry, Size, TBAAInfo); + AliasSets.back().addPointer(*this, Entry, Size, AAInfo); return AliasSets.back(); } -bool AliasSetTracker::add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo) { +bool AliasSetTracker::add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo) { bool NewPtr; - addPointer(Ptr, Size, TBAAInfo, AliasSet::NoModRef, NewPtr); + addPointer(Ptr, Size, AAInfo, AliasSet::NoModRef, NewPtr); return NewPtr; } bool AliasSetTracker::add(LoadInst *LI) { if (LI->getOrdering() > Monotonic) return addUnknown(LI); + + AAMDNodes AAInfo; + LI->getAAMetadata(AAInfo); + AliasSet::AccessType ATy = AliasSet::Refs; bool NewPtr; AliasSet &AS = addPointer(LI->getOperand(0), AA.getTypeStoreSize(LI->getType()), - LI->getMetadata(LLVMContext::MD_tbaa), - ATy, NewPtr); + AAInfo, ATy, NewPtr); if (LI->isVolatile()) AS.setVolatile(); return NewPtr; } bool AliasSetTracker::add(StoreInst *SI) { if (SI->getOrdering() > Monotonic) return addUnknown(SI); + + AAMDNodes AAInfo; + SI->getAAMetadata(AAInfo); + AliasSet::AccessType ATy = AliasSet::Mods; bool NewPtr; Value *Val = SI->getOperand(0); AliasSet &AS = addPointer(SI->getOperand(1), AA.getTypeStoreSize(Val->getType()), - SI->getMetadata(LLVMContext::MD_tbaa), - ATy, NewPtr); + AAInfo, ATy, NewPtr); if (SI->isVolatile()) AS.setVolatile(); return NewPtr; } bool AliasSetTracker::add(VAArgInst *VAAI) { + AAMDNodes AAInfo; + VAAI->getAAMetadata(AAInfo); + bool NewPtr; addPointer(VAAI->getOperand(0), AliasAnalysis::UnknownSize, - VAAI->getMetadata(LLVMContext::MD_tbaa), - AliasSet::ModRef, NewPtr); + AAInfo, AliasSet::ModRef, NewPtr); return NewPtr; } @@ -382,7 +390,7 @@ bool X; for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) { AliasSet &NewAS = addPointer(ASI.getPointer(), ASI.getSize(), - ASI.getTBAAInfo(), + ASI.getAAInfo(), (AliasSet::AccessType)AS.AccessTy, X); if (AS.isVolatile()) NewAS.setVolatile(); } @@ -419,8 +427,8 @@ } bool -AliasSetTracker::remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo) { - AliasSet *AS = findAliasSetForPointer(Ptr, Size, TBAAInfo); +AliasSetTracker::remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo) { + AliasSet *AS = findAliasSetForPointer(Ptr, Size, AAInfo); if (!AS) return false; remove(*AS); return true; @@ -428,8 +436,11 @@ bool AliasSetTracker::remove(LoadInst *LI) { uint64_t Size = AA.getTypeStoreSize(LI->getType()); - const MDNode *TBAAInfo = LI->getMetadata(LLVMContext::MD_tbaa); - AliasSet *AS = findAliasSetForPointer(LI->getOperand(0), Size, TBAAInfo); + + AAMDNodes AAInfo; + LI->getAAMetadata(AAInfo); + + AliasSet *AS = findAliasSetForPointer(LI->getOperand(0), Size, AAInfo); if (!AS) return false; remove(*AS); return true; @@ -437,17 +448,22 @@ bool AliasSetTracker::remove(StoreInst *SI) { uint64_t Size = AA.getTypeStoreSize(SI->getOperand(0)->getType()); - const MDNode *TBAAInfo = SI->getMetadata(LLVMContext::MD_tbaa); - AliasSet *AS = findAliasSetForPointer(SI->getOperand(1), Size, TBAAInfo); + + AAMDNodes AAInfo; + SI->getAAMetadata(AAInfo); + + AliasSet *AS = findAliasSetForPointer(SI->getOperand(1), Size, AAInfo); if (!AS) return false; remove(*AS); return true; } bool AliasSetTracker::remove(VAArgInst *VAAI) { + AAMDNodes AAInfo; + VAAI->getAAMetadata(AAInfo); + AliasSet *AS = findAliasSetForPointer(VAAI->getOperand(0), - AliasAnalysis::UnknownSize, - VAAI->getMetadata(LLVMContext::MD_tbaa)); + AliasAnalysis::UnknownSize, AAInfo); if (!AS) return false; remove(*AS); return true; @@ -536,7 +552,7 @@ I = PointerMap.find_as(From); AliasSet *AS = I->second->getAliasSet(*this); AS->addPointer(*this, Entry, I->second->getSize(), - I->second->getTBAAInfo(), + I->second->getAAInfo(), true); } Index: lib/Analysis/Analysis.cpp =================================================================== --- lib/Analysis/Analysis.cpp +++ lib/Analysis/Analysis.cpp @@ -66,6 +66,7 @@ initializeScalarEvolutionAliasAnalysisPass(Registry); initializeTargetTransformInfoAnalysisGroup(Registry); initializeTypeBasedAliasAnalysisPass(Registry); + initializeScopedNoAliasAAPass(Registry); } void LLVMInitializeAnalysis(LLVMPassRegistryRef R) { Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -467,8 +467,8 @@ assert(AliasCache.empty() && "AliasCache must be cleared after use!"); assert(notDifferentParent(LocA.Ptr, LocB.Ptr) && "BasicAliasAnalysis doesn't support interprocedural queries."); - AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.TBAATag, - LocB.Ptr, LocB.Size, LocB.TBAATag); + AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.AATags, + LocB.Ptr, LocB.Size, LocB.AATags); // AliasCache rarely has more than 1 or 2 elements, always use // shrink_and_clear so it quickly returns to the inline capacity of the // SmallDenseMap if it ever grows larger. @@ -555,28 +555,28 @@ // aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP // instruction against another. AliasResult aliasGEP(const GEPOperator *V1, uint64_t V1Size, - const MDNode *V1TBAAInfo, + const AAMDNodes &V1AAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo, + const AAMDNodes &V2AAInfo, const Value *UnderlyingV1, const Value *UnderlyingV2); // aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI // instruction against another. AliasResult aliasPHI(const PHINode *PN, uint64_t PNSize, - const MDNode *PNTBAAInfo, + const AAMDNodes &PNAAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo); + const AAMDNodes &V2AAInfo); /// aliasSelect - Disambiguate a Select instruction against another value. AliasResult aliasSelect(const SelectInst *SI, uint64_t SISize, - const MDNode *SITBAAInfo, + const AAMDNodes &SIAAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo); + const AAMDNodes &V2AAInfo); AliasResult aliasCheck(const Value *V1, uint64_t V1Size, - const MDNode *V1TBAATag, + AAMDNodes V1AATag, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAATag); + AAMDNodes V2AATag); }; } // End of anonymous namespace @@ -862,9 +862,9 @@ /// AliasAnalysis::AliasResult BasicAliasAnalysis::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size, - const MDNode *V1TBAAInfo, + const AAMDNodes &V1AAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo, + const AAMDNodes &V2AAInfo, const Value *UnderlyingV1, const Value *UnderlyingV2) { int64_t GEP1BaseOffset; @@ -884,8 +884,8 @@ if ((BaseAlias == MayAlias) && V1Size == V2Size) { // Do the base pointers alias assuming type and size. AliasResult PreciseBaseAlias = aliasCheck(UnderlyingV1, V1Size, - V1TBAAInfo, UnderlyingV2, - V2Size, V2TBAAInfo); + V1AAInfo, UnderlyingV2, + V2Size, V2AAInfo); if (PreciseBaseAlias == NoAlias) { // See if the computed offset from the common pointer tells us about the // relation of the resulting pointer. @@ -961,7 +961,7 @@ return MayAlias; AliasResult R = aliasCheck(UnderlyingV1, UnknownSize, nullptr, - V2, V2Size, V2TBAAInfo); + V2, V2Size, V2AAInfo); if (R != MustAlias) // If V2 may alias GEP base pointer, conservatively returns MayAlias. // If V2 is known not to alias GEP base pointer, then the two values @@ -1067,33 +1067,33 @@ /// instruction against another. AliasAnalysis::AliasResult BasicAliasAnalysis::aliasSelect(const SelectInst *SI, uint64_t SISize, - const MDNode *SITBAAInfo, + const AAMDNodes &SIAAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo) { + const AAMDNodes &V2AAInfo) { // If the values are Selects with the same condition, we can do a more precise // check: just check for aliases between the values on corresponding arms. if (const SelectInst *SI2 = dyn_cast(V2)) if (SI->getCondition() == SI2->getCondition()) { AliasResult Alias = - aliasCheck(SI->getTrueValue(), SISize, SITBAAInfo, - SI2->getTrueValue(), V2Size, V2TBAAInfo); + aliasCheck(SI->getTrueValue(), SISize, SIAAInfo, + SI2->getTrueValue(), V2Size, V2AAInfo); if (Alias == MayAlias) return MayAlias; AliasResult ThisAlias = - aliasCheck(SI->getFalseValue(), SISize, SITBAAInfo, - SI2->getFalseValue(), V2Size, V2TBAAInfo); + aliasCheck(SI->getFalseValue(), SISize, SIAAInfo, + SI2->getFalseValue(), V2Size, V2AAInfo); return MergeAliasResults(ThisAlias, Alias); } // If both arms of the Select node NoAlias or MustAlias V2, then returns // NoAlias / MustAlias. Otherwise, returns MayAlias. AliasResult Alias = - aliasCheck(V2, V2Size, V2TBAAInfo, SI->getTrueValue(), SISize, SITBAAInfo); + aliasCheck(V2, V2Size, V2AAInfo, SI->getTrueValue(), SISize, SIAAInfo); if (Alias == MayAlias) return MayAlias; AliasResult ThisAlias = - aliasCheck(V2, V2Size, V2TBAAInfo, SI->getFalseValue(), SISize, SITBAAInfo); + aliasCheck(V2, V2Size, V2AAInfo, SI->getFalseValue(), SISize, SIAAInfo); return MergeAliasResults(ThisAlias, Alias); } @@ -1101,9 +1101,9 @@ // against another. AliasAnalysis::AliasResult BasicAliasAnalysis::aliasPHI(const PHINode *PN, uint64_t PNSize, - const MDNode *PNTBAAInfo, + const AAMDNodes &PNAAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo) { + const AAMDNodes &V2AAInfo) { // Track phi nodes we have visited. We use this information when we determine // value equivalence. VisitedPhiBBs.insert(PN->getParent()); @@ -1113,8 +1113,8 @@ // on corresponding edges. if (const PHINode *PN2 = dyn_cast(V2)) if (PN2->getParent() == PN->getParent()) { - LocPair Locs(Location(PN, PNSize, PNTBAAInfo), - Location(V2, V2Size, V2TBAAInfo)); + LocPair Locs(Location(PN, PNSize, PNAAInfo), + Location(V2, V2Size, V2AAInfo)); if (PN > V2) std::swap(Locs.first, Locs.second); // Analyse the PHIs' inputs under the assumption that the PHIs are @@ -1132,9 +1132,9 @@ for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { AliasResult ThisAlias = - aliasCheck(PN->getIncomingValue(i), PNSize, PNTBAAInfo, + aliasCheck(PN->getIncomingValue(i), PNSize, PNAAInfo, PN2->getIncomingValueForBlock(PN->getIncomingBlock(i)), - V2Size, V2TBAAInfo); + V2Size, V2AAInfo); Alias = MergeAliasResults(ThisAlias, Alias); if (Alias == MayAlias) break; @@ -1161,8 +1161,8 @@ V1Srcs.push_back(PV1); } - AliasResult Alias = aliasCheck(V2, V2Size, V2TBAAInfo, - V1Srcs[0], PNSize, PNTBAAInfo); + AliasResult Alias = aliasCheck(V2, V2Size, V2AAInfo, + V1Srcs[0], PNSize, PNAAInfo); // Early exit if the check of the first PHI source against V2 is MayAlias. // Other results are not possible. if (Alias == MayAlias) @@ -1173,8 +1173,8 @@ for (unsigned i = 1, e = V1Srcs.size(); i != e; ++i) { Value *V = V1Srcs[i]; - AliasResult ThisAlias = aliasCheck(V2, V2Size, V2TBAAInfo, - V, PNSize, PNTBAAInfo); + AliasResult ThisAlias = aliasCheck(V2, V2Size, V2AAInfo, + V, PNSize, PNAAInfo); Alias = MergeAliasResults(ThisAlias, Alias); if (Alias == MayAlias) break; @@ -1188,9 +1188,9 @@ // AliasAnalysis::AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size, - const MDNode *V1TBAAInfo, + AAMDNodes V1AAInfo, const Value *V2, uint64_t V2Size, - const MDNode *V2TBAAInfo) { + AAMDNodes V2AAInfo) { // If either of the memory references is empty, it doesn't matter what the // pointer values are. if (V1Size == 0 || V2Size == 0) @@ -1270,8 +1270,8 @@ // Check the cache before climbing up use-def chains. This also terminates // otherwise infinitely recursive queries. - LocPair Locs(Location(V1, V1Size, V1TBAAInfo), - Location(V2, V2Size, V2TBAAInfo)); + LocPair Locs(Location(V1, V1Size, V1AAInfo), + Location(V2, V2Size, V2AAInfo)); if (V1 > V2) std::swap(Locs.first, Locs.second); std::pair Pair = @@ -1285,32 +1285,32 @@ std::swap(V1, V2); std::swap(V1Size, V2Size); std::swap(O1, O2); - std::swap(V1TBAAInfo, V2TBAAInfo); + std::swap(V1AAInfo, V2AAInfo); } if (const GEPOperator *GV1 = dyn_cast(V1)) { - AliasResult Result = aliasGEP(GV1, V1Size, V1TBAAInfo, V2, V2Size, V2TBAAInfo, O1, O2); + AliasResult Result = aliasGEP(GV1, V1Size, V1AAInfo, V2, V2Size, V2AAInfo, O1, O2); if (Result != MayAlias) return AliasCache[Locs] = Result; } if (isa(V2) && !isa(V1)) { std::swap(V1, V2); std::swap(V1Size, V2Size); - std::swap(V1TBAAInfo, V2TBAAInfo); + std::swap(V1AAInfo, V2AAInfo); } if (const PHINode *PN = dyn_cast(V1)) { - AliasResult Result = aliasPHI(PN, V1Size, V1TBAAInfo, - V2, V2Size, V2TBAAInfo); + AliasResult Result = aliasPHI(PN, V1Size, V1AAInfo, + V2, V2Size, V2AAInfo); if (Result != MayAlias) return AliasCache[Locs] = Result; } if (isa(V2) && !isa(V1)) { std::swap(V1, V2); std::swap(V1Size, V2Size); - std::swap(V1TBAAInfo, V2TBAAInfo); + std::swap(V1AAInfo, V2AAInfo); } if (const SelectInst *S1 = dyn_cast(V1)) { - AliasResult Result = aliasSelect(S1, V1Size, V1TBAAInfo, - V2, V2Size, V2TBAAInfo); + AliasResult Result = aliasSelect(S1, V1Size, V1AAInfo, + V2, V2Size, V2AAInfo); if (Result != MayAlias) return AliasCache[Locs] = Result; } @@ -1323,8 +1323,8 @@ return AliasCache[Locs] = PartialAlias; AliasResult Result = - AliasAnalysis::alias(Location(V1, V1Size, V1TBAAInfo), - Location(V2, V2Size, V2TBAAInfo)); + AliasAnalysis::alias(Location(V1, V1Size, V1AAInfo), + Location(V2, V2Size, V2AAInfo)); return AliasCache[Locs] = Result; } Index: lib/Analysis/CMakeLists.txt =================================================================== --- lib/Analysis/CMakeLists.txt +++ lib/Analysis/CMakeLists.txt @@ -53,6 +53,7 @@ TargetTransformInfo.cpp Trace.cpp TypeBasedAliasAnalysis.cpp + ScopedNoAliasAA.cpp ValueTracking.cpp ) Index: lib/Analysis/Loads.cpp =================================================================== --- lib/Analysis/Loads.cpp +++ lib/Analysis/Loads.cpp @@ -133,14 +133,14 @@ /// it is set to 0, it will scan the whole block. You can also optionally /// specify an alias analysis implementation, which makes this more precise. /// -/// If TBAATag is non-null and a load or store is found, the TBAA tag from the -/// load or store is recorded there. If there is no TBAA tag or if no access +/// If AATags is non-null and a load or store is found, the AA tags from the +/// load or store are recorded there. If there are no AA tags or if no access /// is found, it is left unmodified. Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan, AliasAnalysis *AA, - MDNode **TBAATag) { + AAMDNodes *AATags) { if (MaxInstsToScan == 0) MaxInstsToScan = ~0U; // If we're using alias analysis to disambiguate get the size of *Ptr. @@ -169,7 +169,7 @@ // those cases are unlikely.) if (LoadInst *LI = dyn_cast(Inst)) if (AreEquivalentAddressValues(LI->getOperand(0), Ptr)) { - if (TBAATag) *TBAATag = LI->getMetadata(LLVMContext::MD_tbaa); + if (AATags) LI->getAAMetadata(*AATags); return LI; } @@ -178,7 +178,7 @@ // (This is true even if the store is volatile or atomic, although // those cases are unlikely.) if (AreEquivalentAddressValues(SI->getOperand(1), Ptr)) { - if (TBAATag) *TBAATag = SI->getMetadata(LLVMContext::MD_tbaa); + if (AATags) SI->getAAMetadata(*AATags); return SI->getOperand(0); } Index: lib/Analysis/MemoryDependenceAnalysis.cpp =================================================================== --- lib/Analysis/MemoryDependenceAnalysis.cpp +++ lib/Analysis/MemoryDependenceAnalysis.cpp @@ -158,29 +158,32 @@ return AliasAnalysis::Mod; } - if (const IntrinsicInst *II = dyn_cast(Inst)) + if (const IntrinsicInst *II = dyn_cast(Inst)) { + AAMDNodes AAInfo; + switch (II->getIntrinsicID()) { case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: case Intrinsic::invariant_start: + II->getAAMetadata(AAInfo); Loc = AliasAnalysis::Location(II->getArgOperand(1), cast(II->getArgOperand(0)) - ->getZExtValue(), - II->getMetadata(LLVMContext::MD_tbaa)); + ->getZExtValue(), AAInfo); // These intrinsics don't really modify the memory, but returning Mod // will allow them to be handled conservatively. return AliasAnalysis::Mod; case Intrinsic::invariant_end: + II->getAAMetadata(AAInfo); Loc = AliasAnalysis::Location(II->getArgOperand(2), cast(II->getArgOperand(1)) - ->getZExtValue(), - II->getMetadata(LLVMContext::MD_tbaa)); + ->getZExtValue(), AAInfo); // These intrinsics don't really modify the memory, but returning Mod // will allow them to be handled conservatively. return AliasAnalysis::Mod; default: break; } + } // Otherwise, just do the coarse-grained thing that always works. if (Inst->mayWriteToMemory()) @@ -922,10 +925,10 @@ // Set up a temporary NLPI value. If the map doesn't yet have an entry for // CacheKey, this value will be inserted as the associated value. Otherwise, // it'll be ignored, and we'll have to check to see if the cached size and - // tbaa tag are consistent with the current query. + // aa tags are consistent with the current query. NonLocalPointerInfo InitialNLPI; InitialNLPI.Size = Loc.Size; - InitialNLPI.TBAATag = Loc.TBAATag; + InitialNLPI.AATags = Loc.AATags; // Get the NLPI for CacheKey, inserting one into the map if it doesn't // already have one. @@ -955,21 +958,21 @@ SkipFirstBlock); } - // If the query's TBAATag is inconsistent with the cached one, + // If the query's AATags are inconsistent with the cached one, // conservatively throw out the cached data and restart the query with // no tag if needed. - if (CacheInfo->TBAATag != Loc.TBAATag) { - if (CacheInfo->TBAATag) { + if (CacheInfo->AATags != Loc.AATags) { + if (CacheInfo->AATags) { CacheInfo->Pair = BBSkipFirstBlockPair(); - CacheInfo->TBAATag = nullptr; + CacheInfo->AATags = AAMDNodes(); for (NonLocalDepInfo::iterator DI = CacheInfo->NonLocalDeps.begin(), DE = CacheInfo->NonLocalDeps.end(); DI != DE; ++DI) if (Instruction *Inst = DI->getResult().getInst()) RemoveFromReverseMap(ReverseNonLocalPtrDeps, Inst, CacheKey); CacheInfo->NonLocalDeps.clear(); } - if (Loc.TBAATag) - return getNonLocalPointerDepFromBB(Pointer, Loc.getWithoutTBAATag(), + if (Loc.AATags) + return getNonLocalPointerDepFromBB(Pointer, Loc.getWithoutAATags(), isLoad, StartBB, Result, Visited, SkipFirstBlock); } Index: lib/Analysis/ScalarEvolutionAliasAnalysis.cpp =================================================================== --- lib/Analysis/ScalarEvolutionAliasAnalysis.cpp +++ lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -162,10 +162,10 @@ if ((AO && AO != LocA.Ptr) || (BO && BO != LocB.Ptr)) if (alias(Location(AO ? AO : LocA.Ptr, AO ? +UnknownSize : LocA.Size, - AO ? nullptr : LocA.TBAATag), + AO ? AAMDNodes() : LocA.AATags), Location(BO ? BO : LocB.Ptr, BO ? +UnknownSize : LocB.Size, - BO ? nullptr : LocB.TBAATag)) == NoAlias) + BO ? AAMDNodes() : LocB.AATags)) == NoAlias) return NoAlias; // Forward the query to the next analysis. Index: lib/Analysis/ScopedNoAliasAA.cpp =================================================================== --- /dev/null +++ lib/Analysis/ScopedNoAliasAA.cpp @@ -0,0 +1,243 @@ +//===- ScopedNoAliasAA.cpp - Scoped No-Alias Alias Analysis ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ScopedNoAlias alias-analysis pass, which implements +// metadata-based scoped no-alias support. +// +// Alias-analysis scopes are defined similar to TBAA nodes: +// +// !scope0 = metadata !{ metadata !"scope of foo()" } +// !scope1 = metadata !{ metadata !"scope 1", metadata !scope0 } +// !scope2 = metadata !{ metadata !"scope 2", metadata !scope0 } +// !scope3 = metadata !{ metadata !"scope 2.1", metadata !scope2 } +// !scope4 = metadata !{ metadata !"scope 2.2", metadata !scope2 } +// +// Loads and stores can be tagged with an alias-analysis scope, and also, with +// a noalias tag for a specific scope: +// +// ... = load %ptr1, !alias.scope !{ !scope1 } +// ... = load %ptr2, !alias.scope !{ !scope1, !scope2 }, !noalias !{ !scope1 } +// +// When evaluating an aliasing query, if one of the instructions is associated +// with an alias.scope id that is identical to the noalias scope associated +// with the other instruction, or is a descendant (in the scope hierarchy) of +// the noalias scope associated with the other instruction, then the two memory +// accesses are assumed not to alias. +// +// Note that if the first element of the scope metadata is a string, then it +// can be combined accross functions and translation units. The string can be +// replaced by a self-reference to create globally unqiue scope identifiers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +// A handy option for disabling scoped no-alias functionality. The same effect +// can also be achieved by stripping the associated metadata tags from IR, but +// this option is sometimes more convenient. +static cl::opt +EnableScopedNoAlias("enable-scoped-noalias", cl::init(true)); + +namespace { +/// AliasScopeNode - This is a simple wrapper around an MDNode which provides +/// a higher-level interface by hiding the details of how alias analysis +/// information is encoded in its operands. +class AliasScopeNode { + const MDNode *Node; + +public: + AliasScopeNode() : Node(0) {} + explicit AliasScopeNode(const MDNode *N) : Node(N) {} + + /// getNode - Get the MDNode for this AliasScopeNode. + const MDNode *getNode() const { return Node; } + + /// getParent - Get this AliasScopeNode's Alias tree parent. + AliasScopeNode getParent() const { + if (Node->getNumOperands() < 2) + return AliasScopeNode(); + MDNode *P = dyn_cast_or_null(Node->getOperand(1)); + if (!P) + return AliasScopeNode(); + // Ok, this node has a valid parent. Return it. + return AliasScopeNode(P); + } +}; + +/// ScopedNoAliasAA - This is a simple alias analysis +/// implementation that uses scoped-noalias metadata to answer queries. +class ScopedNoAliasAA : public ImmutablePass, public AliasAnalysis { +public: + static char ID; // Class identification, replacement for typeinfo + ScopedNoAliasAA() : ImmutablePass(ID) { + initializeScopedNoAliasAAPass(*PassRegistry::getPassRegistry()); + } + + virtual void initializePass() { + InitializeAliasAnalysis(this); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const void *PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + +protected: + bool mayAlias(const MDNode *A, const MDNode *B) const; + bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const; + +private: + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual AliasResult alias(const Location &LocA, const Location &LocB); + virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal); + virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); + virtual ModRefBehavior getModRefBehavior(const Function *F); + virtual ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2); +}; +} // End of anonymous namespace + +// Register this pass... +char ScopedNoAliasAA::ID = 0; +INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias", + "Scoped NoAlias Alias Analysis", false, true, false) + +ImmutablePass *llvm::createScopedNoAliasAAPass() { + return new ScopedNoAliasAA(); +} + +void +ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AliasAnalysis::getAnalysisUsage(AU); +} + +/// mayAlias - Test whether the scope represented by A may alias the +/// scope represented by B. Specifically, A is the target scope, and B is the +/// noalias scope. +bool +ScopedNoAliasAA::mayAlias(const MDNode *A, + const MDNode *B) const { + // Climb the tree from A to see if we reach B. + for (AliasScopeNode T(A); ; ) { + if (T.getNode() == B) + // B is an ancestor of A. + return false; + + T = T.getParent(); + if (!T.getNode()) + break; + } + + return true; +} + +bool +ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes, + const MDNode *NoAlias) const { + if (!Scopes || !NoAlias) + return true; + + for (unsigned i = 0, ie = Scopes->getNumOperands(); i != ie; ++i) + if (const MDNode *SMD = dyn_cast(Scopes->getOperand(i))) + for (unsigned j = 0, je = NoAlias->getNumOperands(); j != je; ++j) + if (const MDNode *NAMD = dyn_cast(NoAlias->getOperand(j))) + if (!mayAlias(SMD, NAMD)) + return false; + + return true; +} + +AliasAnalysis::AliasResult +ScopedNoAliasAA::alias(const Location &LocA, const Location &LocB) { + if (!EnableScopedNoAlias) + return AliasAnalysis::alias(LocA, LocB); + + // Get the attached MDNodes. + const MDNode *AScopes = LocA.AATags.Scope, + *BScopes = LocB.AATags.Scope; + + const MDNode *ANoAlias = LocA.AATags.NoAlias, + *BNoAlias = LocB.AATags.NoAlias; + + if (!mayAliasInScopes(AScopes, BNoAlias)) + return NoAlias; + + if (!mayAliasInScopes(BScopes, ANoAlias)) + return NoAlias; + + // If they may alias, chain to the next AliasAnalysis. + return AliasAnalysis::alias(LocA, LocB); +} + +bool ScopedNoAliasAA::pointsToConstantMemory(const Location &Loc, + bool OrLocal) { + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); +} + +AliasAnalysis::ModRefBehavior +ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) { + return AliasAnalysis::getModRefBehavior(CS); +} + +AliasAnalysis::ModRefBehavior +ScopedNoAliasAA::getModRefBehavior(const Function *F) { + return AliasAnalysis::getModRefBehavior(F); +} + +AliasAnalysis::ModRefResult +ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS, const Location &Loc) { + if (!EnableScopedNoAlias) + return AliasAnalysis::getModRefInfo(CS, Loc); + + if (!mayAliasInScopes(Loc.AATags.Scope, + CS.getInstruction()->getMetadata(LLVMContext::MD_noalias))) + return NoModRef; + + if (!mayAliasInScopes( + CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), + Loc.AATags.NoAlias)) + return NoModRef; + + return AliasAnalysis::getModRefInfo(CS, Loc); +} + +AliasAnalysis::ModRefResult +ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { + if (!EnableScopedNoAlias) + return AliasAnalysis::getModRefInfo(CS1, CS2); + + if (!mayAliasInScopes( + CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), + CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias))) + return NoModRef; + + if (!mayAliasInScopes( + CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope), + CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias))) + return NoModRef; + + return AliasAnalysis::getModRefInfo(CS1, CS2); +} + Index: lib/Analysis/TypeBasedAliasAnalysis.cpp =================================================================== --- lib/Analysis/TypeBasedAliasAnalysis.cpp +++ lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -454,9 +454,9 @@ // Get the attached MDNodes. If either value lacks a tbaa MDNode, we must // be conservative. - const MDNode *AM = LocA.TBAATag; + const MDNode *AM = LocA.AATags.TBAA; if (!AM) return AliasAnalysis::alias(LocA, LocB); - const MDNode *BM = LocB.TBAATag; + const MDNode *BM = LocB.AATags.TBAA; if (!BM) return AliasAnalysis::alias(LocA, LocB); // If they may alias, chain to the next AliasAnalysis. @@ -472,7 +472,7 @@ if (!EnableTBAA) return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); - const MDNode *M = Loc.TBAATag; + const MDNode *M = Loc.AATags.TBAA; if (!M) return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); // If this is an "immutable" type, we can assume the pointer is pointing @@ -513,7 +513,7 @@ if (!EnableTBAA) return AliasAnalysis::getModRefInfo(CS, Loc); - if (const MDNode *L = Loc.TBAATag) + if (const MDNode *L = Loc.AATags.TBAA) if (const MDNode *M = CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) if (!Aliases(L, M)) @@ -611,3 +611,24 @@ Value *Ops[3] = { Ret, Ret, ConstantInt::get(Int64, 0) }; return MDNode::get(A->getContext(), Ops); } + +void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const { + if (Merge) + N.TBAA = MDNode::getMostGenericTBAA(N.TBAA, + getMetadata(LLVMContext::MD_tbaa)); + else + N.TBAA = getMetadata(LLVMContext::MD_tbaa); + + if (Merge) + N.Scope = MDNode::intersect(N.Scope, + getMetadata(LLVMContext::MD_alias_scope)); + else + N.Scope = getMetadata(LLVMContext::MD_alias_scope); + + if (Merge) + N.NoAlias = MDNode::intersect(N.NoAlias, + getMetadata(LLVMContext::MD_noalias)); + else + N.NoAlias = getMetadata(LLVMContext::MD_noalias); +} + Index: lib/CodeGen/MachineFunction.cpp =================================================================== --- lib/CodeGen/MachineFunction.cpp +++ lib/CodeGen/MachineFunction.cpp @@ -229,10 +229,10 @@ MachineMemOperand * MachineFunction::getMachineMemOperand(MachinePointerInfo PtrInfo, unsigned f, uint64_t s, unsigned base_alignment, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, const MDNode *Ranges) { return new (Allocator) MachineMemOperand(PtrInfo, f, s, base_alignment, - TBAAInfo, Ranges); + AAInfo, Ranges); } MachineMemOperand * @@ -279,7 +279,7 @@ getMachineMemOperand((*I)->getPointerInfo(), (*I)->getFlags() & ~MachineMemOperand::MOStore, (*I)->getSize(), (*I)->getBaseAlignment(), - (*I)->getTBAAInfo()); + (*I)->getAAInfo()); Result[Index] = JustLoad; } ++Index; @@ -311,7 +311,7 @@ getMachineMemOperand((*I)->getPointerInfo(), (*I)->getFlags() & ~MachineMemOperand::MOLoad, (*I)->getSize(), (*I)->getBaseAlignment(), - (*I)->getTBAAInfo()); + (*I)->getAAInfo()); Result[Index] = JustStore; } ++Index; Index: lib/CodeGen/MachineInstr.cpp =================================================================== --- lib/CodeGen/MachineInstr.cpp +++ lib/CodeGen/MachineInstr.cpp @@ -429,11 +429,11 @@ MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, unsigned f, uint64_t s, unsigned int a, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, const MDNode *Ranges) : PtrInfo(ptrinfo), Size(s), Flags((f & ((1 << MOMaxBits) - 1)) | ((Log2_32(a) + 1) << MOMaxBits)), - TBAAInfo(TBAAInfo), Ranges(Ranges) { + AAInfo(AAInfo), Ranges(Ranges) { assert((PtrInfo.V.isNull() || PtrInfo.V.is() || isa(PtrInfo.V.get()->getType())) && "invalid pointer value"); @@ -514,7 +514,7 @@ OS << "(align=" << MMO.getAlignment() << ")"; // Print TBAA info. - if (const MDNode *TBAAInfo = MMO.getTBAAInfo()) { + if (const MDNode *TBAAInfo = MMO.getAAInfo().TBAA) { OS << "(tbaa="; if (TBAAInfo->getNumOperands() > 0) TBAAInfo->getOperand(0)->printAsOperand(OS, /*PrintType=*/false); @@ -523,6 +523,34 @@ OS << ")"; } + // Print AA scope info. + if (const MDNode *ScopeInfo = MMO.getAAInfo().Scope) { + OS << "(alias.scope="; + if (ScopeInfo->getNumOperands() > 0) + for (unsigned i = 0, ie = ScopeInfo->getNumOperands(); i != ie; ++i) { + ScopeInfo->getOperand(i)->printAsOperand(OS, /*PrintType=*/false); + if (i != ie-1) + OS << ","; + } + else + OS << ""; + OS << ")"; + } + + // Print AA noalias scope info. + if (const MDNode *NoAliasInfo = MMO.getAAInfo().NoAlias) { + OS << "(noalias="; + if (NoAliasInfo->getNumOperands() > 0) + for (unsigned i = 0, ie = NoAliasInfo->getNumOperands(); i != ie; ++i) { + NoAliasInfo->getOperand(i)->printAsOperand(OS, /*PrintType=*/false); + if (i != ie-1) + OS << ","; + } + else + OS << ""; + OS << ")"; + } + // Print nontemporal info. if (MMO.isNonTemporal()) OS << "(nontemporal)"; @@ -1379,7 +1407,7 @@ // If we have an AliasAnalysis, ask it whether the memory is constant. if (AA && AA->pointsToConstantMemory( AliasAnalysis::Location(V, (*I)->getSize(), - (*I)->getTBAAInfo()))) + (*I)->getAAInfo()))) continue; } Index: lib/CodeGen/Passes.cpp =================================================================== --- lib/CodeGen/Passes.cpp +++ lib/CodeGen/Passes.cpp @@ -375,6 +375,7 @@ // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. addPass(createTypeBasedAliasAnalysisPass()); + addPass(createScopedNoAliasAAPass()); addPass(createBasicAliasAnalysisPass()); // Before running any passes, run the verifier to determine if the input Index: lib/CodeGen/ScheduleDAGInstrs.cpp =================================================================== --- lib/CodeGen/ScheduleDAGInstrs.cpp +++ lib/CodeGen/ScheduleDAGInstrs.cpp @@ -563,9 +563,9 @@ AliasAnalysis::AliasResult AAResult = AA->alias( AliasAnalysis::Location(MMOa->getValue(), Overlapa, - UseTBAA ? MMOa->getTBAAInfo() : nullptr), + UseTBAA ? MMOa->getAAInfo() : AAMDNodes()), AliasAnalysis::Location(MMOb->getValue(), Overlapb, - UseTBAA ? MMOb->getTBAAInfo() : nullptr)); + UseTBAA ? MMOb->getAAInfo() : AAMDNodes())); return (AAResult != AliasAnalysis::NoAlias); } Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2919,7 +2919,7 @@ LN0->getChain(), NewPtr, LN0->getPointerInfo(), ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), - Alignment, LN0->getTBAAInfo()); + Alignment, LN0->getAAInfo()); AddToWorkList(N); CombineTo(LN0, Load, Load.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -5784,12 +5784,12 @@ Load = DAG.getLoad(VT, SDLoc(N0), LN0->getChain(), NewPtr, LN0->getPointerInfo().getWithOffset(PtrOff), LN0->isVolatile(), LN0->isNonTemporal(), - LN0->isInvariant(), NewAlign, LN0->getTBAAInfo()); + LN0->isInvariant(), NewAlign, LN0->getAAInfo()); else Load = DAG.getExtLoad(ExtType, SDLoc(N0), VT, LN0->getChain(),NewPtr, LN0->getPointerInfo().getWithOffset(PtrOff), ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), - NewAlign, LN0->getTBAAInfo()); + NewAlign, LN0->getAAInfo()); // Replace the old load's chain with the new load's chain. WorkListRemover DeadNodes(*this); @@ -6242,7 +6242,7 @@ LN0->getBasePtr(), LN0->getPointerInfo(), LN0->isVolatile(), LN0->isNonTemporal(), LN0->isInvariant(), OrigAlign, - LN0->getTBAAInfo()); + LN0->getAAInfo()); AddToWorkList(N); CombineTo(N0.getNode(), DAG.getNode(ISD::BITCAST, SDLoc(N0), @@ -8008,7 +8008,7 @@ Chain, Ptr, LD->getPointerInfo(), LD->getMemoryVT(), LD->isVolatile(), LD->isNonTemporal(), Align, - LD->getTBAAInfo()); + LD->getAAInfo()); return CombineTo(N, NewLoad, SDValue(NewLoad.getNode(), 1), true); } } @@ -8844,7 +8844,7 @@ LD->getPointerInfo().getWithOffset(PtrOff), LD->isVolatile(), LD->isNonTemporal(), LD->isInvariant(), NewAlign, - LD->getTBAAInfo()); + LD->getAAInfo()); SDValue NewVal = DAG.getNode(Opc, SDLoc(Value), NewVT, NewLD, DAG.getConstant(NewImm, NewVT)); SDValue NewST = DAG.getStore(Chain, SDLoc(N), @@ -9506,7 +9506,7 @@ return DAG.getStore(Chain, SDLoc(N), Value.getOperand(0), Ptr, ST->getPointerInfo(), ST->isVolatile(), ST->isNonTemporal(), OrigAlign, - ST->getTBAAInfo()); + ST->getAAInfo()); } // Turn 'store undef, Ptr' -> nothing. @@ -9560,19 +9560,19 @@ unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); bool isNonTemporal = ST->isNonTemporal(); - const MDNode *TBAAInfo = ST->getTBAAInfo(); + AAMDNodes AAInfo = ST->getAAInfo(); SDValue St0 = DAG.getStore(Chain, SDLoc(ST), Lo, Ptr, ST->getPointerInfo(), isVolatile, isNonTemporal, - ST->getAlignment(), TBAAInfo); + ST->getAlignment(), AAInfo); Ptr = DAG.getNode(ISD::ADD, SDLoc(N), Ptr.getValueType(), Ptr, DAG.getConstant(4, Ptr.getValueType())); Alignment = MinAlign(Alignment, 4U); SDValue St1 = DAG.getStore(Chain, SDLoc(ST), Hi, Ptr, ST->getPointerInfo().getWithOffset(4), isVolatile, isNonTemporal, - Alignment, TBAAInfo); + Alignment, AAInfo); return DAG.getNode(ISD::TokenFactor, SDLoc(N), MVT::Other, St0, St1); } @@ -9589,7 +9589,7 @@ return DAG.getTruncStore(Chain, SDLoc(N), Value, Ptr, ST->getPointerInfo(), ST->getMemoryVT(), ST->isVolatile(), ST->isNonTemporal(), Align, - ST->getTBAAInfo()); + ST->getAAInfo()); } } @@ -9980,13 +9980,13 @@ Load = DAG.getExtLoad(ExtType, SDLoc(N), NVT, LN0->getChain(), NewPtr, LN0->getPointerInfo().getWithOffset(PtrOff), LVT, LN0->isVolatile(), LN0->isNonTemporal(), - Align, LN0->getTBAAInfo()); + Align, LN0->getAAInfo()); Chain = Load.getValue(1); } else { Load = DAG.getLoad(LVT, SDLoc(N), LN0->getChain(), NewPtr, LN0->getPointerInfo().getWithOffset(PtrOff), LN0->isVolatile(), LN0->isNonTemporal(), - LN0->isInvariant(), Align, LN0->getTBAAInfo()); + LN0->isInvariant(), Align, LN0->getAAInfo()); Chain = Load.getValue(1); if (NVT.bitsLT(LVT)) Load = DAG.getNode(ISD::TRUNCATE, SDLoc(N), NVT, Load); @@ -11107,7 +11107,7 @@ if (LLD->getExtensionType() == ISD::NON_EXTLOAD) { Load = DAG.getLoad(TheSelect->getValueType(0), SDLoc(TheSelect), - // FIXME: Discards pointer and TBAA info. + // FIXME: Discards pointer and AA info. LLD->getChain(), Addr, MachinePointerInfo(), LLD->isVolatile(), LLD->isNonTemporal(), LLD->isInvariant(), LLD->getAlignment()); @@ -11116,7 +11116,7 @@ RLD->getExtensionType() : LLD->getExtensionType(), SDLoc(TheSelect), TheSelect->getValueType(0), - // FIXME: Discards pointer and TBAA info. + // FIXME: Discards pointer and AA info. LLD->getChain(), Addr, MachinePointerInfo(), LLD->getMemoryVT(), LLD->isVolatile(), LLD->isNonTemporal(), LLD->getAlignment()); @@ -11597,10 +11597,10 @@ AliasAnalysis::AliasResult AAResult = AA.alias(AliasAnalysis::Location(Op0->getMemOperand()->getValue(), Overlap1, - UseTBAA ? Op0->getTBAAInfo() : nullptr), + UseTBAA ? Op0->getAAInfo() : AAMDNodes()), AliasAnalysis::Location(Op1->getMemOperand()->getValue(), Overlap2, - UseTBAA ? Op1->getTBAAInfo() : nullptr)); + UseTBAA ? Op1->getAAInfo() : AAMDNodes())); if (AAResult == AliasAnalysis::NoAlias) return false; } Index: lib/CodeGen/SelectionDAG/FastISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/FastISel.cpp +++ lib/CodeGen/SelectionDAG/FastISel.cpp @@ -2158,9 +2158,11 @@ bool IsNonTemporal = I->getMetadata("nontemporal") != nullptr; bool IsInvariant = I->getMetadata("invariant.load") != nullptr; - const MDNode *TBAAInfo = I->getMetadata(LLVMContext::MD_tbaa); const MDNode *Ranges = I->getMetadata(LLVMContext::MD_range); + AAMDNodes AAInfo; + I->getAAMetadata(AAInfo); + if (Alignment == 0) // Ensure that codegen never sees alignment 0. Alignment = DL.getABITypeAlignment(ValTy); @@ -2174,5 +2176,5 @@ Flags |= MachineMemOperand::MOInvariant; return FuncInfo.MF->getMachineMemOperand(MachinePointerInfo(Ptr), Flags, Size, - Alignment, TBAAInfo, Ranges); + Alignment, AAInfo, Ranges); } Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -385,7 +385,7 @@ MemVT, ST->isVolatile(), ST->isNonTemporal(), MinAlign(ST->getAlignment(), Offset), - ST->getTBAAInfo())); + ST->getAAInfo())); // The order of the stores doesn't matter - say it with a TokenFactor. SDValue Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Stores); DAGLegalize->ReplaceNode(SDValue(ST, 0), Result); @@ -417,7 +417,7 @@ Store2 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Hi:Lo, Ptr, ST->getPointerInfo().getWithOffset(IncrementSize), NewStoredVT, ST->isVolatile(), ST->isNonTemporal(), - Alignment, ST->getTBAAInfo()); + Alignment, ST->getAAInfo()); SDValue Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2); @@ -476,7 +476,7 @@ LD->isVolatile(), LD->isNonTemporal(), LD->isInvariant(), MinAlign(LD->getAlignment(), Offset), - LD->getTBAAInfo()); + LD->getAAInfo()); // Follow the load with a store to the stack slot. Remember the store. Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, StackPtr, MachinePointerInfo(), false, false, 0)); @@ -495,7 +495,7 @@ MemVT, LD->isVolatile(), LD->isNonTemporal(), MinAlign(LD->getAlignment(), Offset), - LD->getTBAAInfo()); + LD->getAAInfo()); // Follow the load with a store to the stack slot. Remember the store. // On big-endian machines this requires a truncating store to ensure // that the bits end up in the right place. @@ -538,25 +538,25 @@ if (TLI.isLittleEndian()) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getPointerInfo(), NewLoadedVT, LD->isVolatile(), - LD->isNonTemporal(), Alignment, LD->getTBAAInfo()); + LD->isNonTemporal(), Alignment, LD->getAAInfo()); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, Ptr.getValueType())); Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getPointerInfo().getWithOffset(IncrementSize), NewLoadedVT, LD->isVolatile(), LD->isNonTemporal(), MinAlign(Alignment, IncrementSize), - LD->getTBAAInfo()); + LD->getAAInfo()); } else { Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getPointerInfo(), NewLoadedVT, LD->isVolatile(), - LD->isNonTemporal(), Alignment, LD->getTBAAInfo()); + LD->isNonTemporal(), Alignment, LD->getAAInfo()); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, Ptr.getValueType())); Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getPointerInfo().getWithOffset(IncrementSize), NewLoadedVT, LD->isVolatile(), LD->isNonTemporal(), MinAlign(Alignment, IncrementSize), - LD->getTBAAInfo()); + LD->getAAInfo()); } // aggregate the two parts @@ -659,7 +659,7 @@ unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); bool isNonTemporal = ST->isNonTemporal(); - const MDNode *TBAAInfo = ST->getTBAAInfo(); + AAMDNodes AAInfo = ST->getAAInfo(); SDLoc dl(ST); if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { if (CFP->getValueType(0) == MVT::f32 && @@ -668,7 +668,7 @@ bitcastToAPInt().zextOrTrunc(32), MVT::i32); return DAG.getStore(Chain, dl, Con, Ptr, ST->getPointerInfo(), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); } if (CFP->getValueType(0) == MVT::f64) { @@ -677,7 +677,7 @@ SDValue Con = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). zextOrTrunc(64), MVT::i64); return DAG.getStore(Chain, dl, Con, Ptr, ST->getPointerInfo(), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); } if (TLI.isTypeLegal(MVT::i32) && !ST->isVolatile()) { @@ -690,13 +690,13 @@ if (TLI.isBigEndian()) std::swap(Lo, Hi); Lo = DAG.getStore(Chain, dl, Lo, Ptr, ST->getPointerInfo(), isVolatile, - isNonTemporal, Alignment, TBAAInfo); + isNonTemporal, Alignment, AAInfo); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(4, Ptr.getValueType())); Hi = DAG.getStore(Chain, dl, Hi, Ptr, ST->getPointerInfo().getWithOffset(4), isVolatile, isNonTemporal, MinAlign(Alignment, 4U), - TBAAInfo); + AAInfo); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } @@ -714,7 +714,7 @@ unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); bool isNonTemporal = ST->isNonTemporal(); - const MDNode *TBAAInfo = ST->getTBAAInfo(); + AAMDNodes AAInfo = ST->getAAInfo(); if (!ST->isTruncatingStore()) { if (SDNode *OptStore = OptimizeFloatStore(ST).getNode()) { @@ -754,7 +754,7 @@ SDValue Result = DAG.getStore(Chain, dl, Value, Ptr, ST->getPointerInfo(), isVolatile, - isNonTemporal, Alignment, TBAAInfo); + isNonTemporal, Alignment, AAInfo); ReplaceNode(SDValue(Node, 0), Result); break; } @@ -777,7 +777,7 @@ SDValue Result = DAG.getTruncStore(Chain, dl, Value, Ptr, ST->getPointerInfo(), NVT, isVolatile, isNonTemporal, Alignment, - TBAAInfo); + AAInfo); ReplaceNode(SDValue(Node, 0), Result); } else if (StWidth & (StWidth - 1)) { // If not storing a power-of-2 number of bits, expand as two stores. @@ -799,7 +799,7 @@ Lo = DAG.getTruncStore(Chain, dl, Value, Ptr, ST->getPointerInfo(), RoundVT, isVolatile, isNonTemporal, Alignment, - TBAAInfo); + AAInfo); // Store the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -811,7 +811,7 @@ Hi = DAG.getTruncStore(Chain, dl, Hi, Ptr, ST->getPointerInfo().getWithOffset(IncrementSize), ExtraVT, isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); } else { // Big endian - avoid unaligned stores. // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X @@ -821,7 +821,7 @@ TLI.getShiftAmountTy(Value.getValueType()))); Hi = DAG.getTruncStore(Chain, dl, Hi, Ptr, ST->getPointerInfo(), RoundVT, isVolatile, isNonTemporal, Alignment, - TBAAInfo); + AAInfo); // Store the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -830,7 +830,7 @@ Lo = DAG.getTruncStore(Chain, dl, Value, Ptr, ST->getPointerInfo().getWithOffset(IncrementSize), ExtraVT, isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); } // The order of the stores doesn't matter. @@ -868,7 +868,7 @@ Value = DAG.getNode(ISD::TRUNCATE, dl, StVT, Value); SDValue Result = DAG.getStore(Chain, dl, Value, Ptr, ST->getPointerInfo(), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); ReplaceNode(SDValue(Node, 0), Result); break; } @@ -938,7 +938,7 @@ unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); bool isNonTemporal = LD->isNonTemporal(); - const MDNode *TBAAInfo = LD->getTBAAInfo(); + AAMDNodes AAInfo = LD->getAAInfo(); if (SrcWidth != SrcVT.getStoreSizeInBits() && // Some targets pretend to have an i1 loading operation, and actually @@ -965,7 +965,7 @@ SDValue Result = DAG.getExtLoad(NewExtType, dl, Node->getValueType(0), Chain, Ptr, LD->getPointerInfo(), - NVT, isVolatile, isNonTemporal, Alignment, TBAAInfo); + NVT, isVolatile, isNonTemporal, Alignment, AAInfo); Ch = Result.getValue(1); // The chain. @@ -1002,7 +1002,7 @@ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, Node->getValueType(0), Chain, Ptr, LD->getPointerInfo(), RoundVT, isVolatile, - isNonTemporal, Alignment, TBAAInfo); + isNonTemporal, Alignment, AAInfo); // Load the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1011,7 +1011,7 @@ Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Chain, Ptr, LD->getPointerInfo().getWithOffset(IncrementSize), ExtraVT, isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); // Build a factor node to remember that this load is independent of // the other one. @@ -1031,7 +1031,7 @@ // Load the top RoundWidth bits. Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Chain, Ptr, LD->getPointerInfo(), RoundVT, isVolatile, - isNonTemporal, Alignment, TBAAInfo); + isNonTemporal, Alignment, AAInfo); // Load the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1041,7 +1041,7 @@ dl, Node->getValueType(0), Chain, Ptr, LD->getPointerInfo().getWithOffset(IncrementSize), ExtraVT, isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); // Build a factor node to remember that this load is independent of // the other one. Index: lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -533,7 +533,7 @@ NVT, dl, L->getChain(), L->getBasePtr(), L->getOffset(), L->getPointerInfo(), NVT, L->isVolatile(), L->isNonTemporal(), false, L->getAlignment(), - L->getTBAAInfo()); + L->getAAInfo()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); @@ -546,7 +546,7 @@ L->getBasePtr(), L->getOffset(), L->getPointerInfo(), L->getMemoryVT(), L->isVolatile(), L->isNonTemporal(), false, L->getAlignment(), - L->getTBAAInfo()); + L->getAAInfo()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); Index: lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1860,7 +1860,7 @@ bool isVolatile = N->isVolatile(); bool isNonTemporal = N->isNonTemporal(); bool isInvariant = N->isInvariant(); - const MDNode *TBAAInfo = N->getTBAAInfo(); + AAMDNodes AAInfo = N->getAAInfo(); SDLoc dl(N); assert(NVT.isByteSized() && "Expanded type not byte sized!"); @@ -1869,7 +1869,7 @@ EVT MemVT = N->getMemoryVT(); Lo = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getPointerInfo(), - MemVT, isVolatile, isNonTemporal, Alignment, TBAAInfo); + MemVT, isVolatile, isNonTemporal, Alignment, AAInfo); // Remember the chain. Ch = Lo.getValue(1); @@ -1892,7 +1892,7 @@ // Little-endian - low bits are at low addresses. Lo = DAG.getLoad(NVT, dl, Ch, Ptr, N->getPointerInfo(), isVolatile, isNonTemporal, isInvariant, Alignment, - TBAAInfo); + AAInfo); unsigned ExcessBits = N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); @@ -1905,7 +1905,7 @@ Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getPointerInfo().getWithOffset(IncrementSize), NEVT, isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); // Build a factor node to remember that this load is independent of the // other one. @@ -1923,7 +1923,7 @@ Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getPointerInfo(), EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits() - ExcessBits), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -1933,7 +1933,7 @@ N->getPointerInfo().getWithOffset(IncrementSize), EVT::getIntegerVT(*DAG.getContext(), ExcessBits), isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); // Build a factor node to remember that this load is independent of the // other one. @@ -2710,7 +2710,7 @@ unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); bool isNonTemporal = N->isNonTemporal(); - const MDNode *TBAAInfo = N->getTBAAInfo(); + AAMDNodes AAInfo = N->getAAInfo(); SDLoc dl(N); SDValue Lo, Hi; @@ -2720,7 +2720,7 @@ GetExpandedInteger(N->getValue(), Lo, Hi); return DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getPointerInfo(), N->getMemoryVT(), isVolatile, isNonTemporal, - Alignment, TBAAInfo); + Alignment, AAInfo); } if (TLI.isLittleEndian()) { @@ -2728,7 +2728,7 @@ GetExpandedInteger(N->getValue(), Lo, Hi); Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getPointerInfo(), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); unsigned ExcessBits = N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); @@ -2741,7 +2741,7 @@ Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getPointerInfo().getWithOffset(IncrementSize), NEVT, isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } @@ -2769,7 +2769,7 @@ // Store both the high bits and maybe some of the low bits. Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getPointerInfo(), - HiVT, isVolatile, isNonTemporal, Alignment, TBAAInfo); + HiVT, isVolatile, isNonTemporal, Alignment, AAInfo); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -2779,7 +2779,7 @@ N->getPointerInfo().getWithOffset(IncrementSize), EVT::getIntegerVT(*DAG.getContext(), ExcessBits), isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } Index: lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -256,13 +256,13 @@ bool isVolatile = LD->isVolatile(); bool isNonTemporal = LD->isNonTemporal(); bool isInvariant = LD->isInvariant(); - const MDNode *TBAAInfo = LD->getTBAAInfo(); + AAMDNodes AAInfo = LD->getAAInfo(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); Lo = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getPointerInfo(), isVolatile, isNonTemporal, isInvariant, Alignment, - TBAAInfo); + AAInfo); // Increment the pointer to the other half. unsigned IncrementSize = NVT.getSizeInBits() / 8; @@ -271,7 +271,7 @@ Hi = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getPointerInfo().getWithOffset(IncrementSize), isVolatile, isNonTemporal, isInvariant, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); // Build a factor node to remember that this load is independent of the // other one. @@ -470,7 +470,7 @@ unsigned Alignment = St->getAlignment(); bool isVolatile = St->isVolatile(); bool isNonTemporal = St->isNonTemporal(); - const MDNode *TBAAInfo = St->getTBAAInfo(); + AAMDNodes AAInfo = St->getAAInfo(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); unsigned IncrementSize = NVT.getSizeInBits() / 8; @@ -482,14 +482,14 @@ std::swap(Lo, Hi); Lo = DAG.getStore(Chain, dl, Lo, Ptr, St->getPointerInfo(), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, Ptr.getValueType())); Hi = DAG.getStore(Chain, dl, Hi, Ptr, St->getPointerInfo().getWithOffset(IncrementSize), isVolatile, isNonTemporal, - MinAlign(Alignment, IncrementSize), TBAAInfo); + MinAlign(Alignment, IncrementSize), AAInfo); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } Index: lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp +++ lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -480,7 +480,7 @@ LD->getPointerInfo().getWithOffset(Offset), LD->isVolatile(), LD->isNonTemporal(), LD->isInvariant(), LD->getAlignment(), - LD->getTBAAInfo()); + LD->getAAInfo()); } else { EVT LoadVT = WideVT; while (RemainingBytes < LoadBytes) { @@ -491,7 +491,7 @@ LD->getPointerInfo().getWithOffset(Offset), LoadVT, LD->isVolatile(), LD->isNonTemporal(), LD->getAlignment(), - LD->getTBAAInfo()); + LD->getAAInfo()); } RemainingBytes -= LoadBytes; @@ -562,7 +562,7 @@ Chain, BasePTR, LD->getPointerInfo().getWithOffset(Idx * Stride), SrcVT.getScalarType(), LD->isVolatile(), LD->isNonTemporal(), - LD->getAlignment(), LD->getTBAAInfo()); + LD->getAlignment(), LD->getAAInfo()); BasePTR = DAG.getNode(ISD::ADD, dl, BasePTR.getValueType(), BasePTR, DAG.getConstant(Stride, BasePTR.getValueType())); @@ -593,7 +593,7 @@ unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); bool isNonTemporal = ST->isNonTemporal(); - const MDNode *TBAAInfo = ST->getTBAAInfo(); + AAMDNodes AAInfo = ST->getAAInfo(); unsigned NumElem = StVT.getVectorNumElements(); // The type of the data we want to save @@ -621,7 +621,7 @@ // This scalar TruncStore may be illegal, but we legalize it later. SDValue Store = DAG.getTruncStore(Chain, dl, Ex, BasePTR, ST->getPointerInfo().getWithOffset(Idx*Stride), MemSclVT, - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); BasePTR = DAG.getNode(ISD::ADD, dl, BasePTR.getValueType(), BasePTR, DAG.getConstant(Stride, BasePTR.getValueType())); Index: lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -221,7 +221,7 @@ N->getMemoryVT().getVectorElementType(), N->isVolatile(), N->isNonTemporal(), N->isInvariant(), N->getOriginalAlignment(), - N->getTBAAInfo()); + N->getAAInfo()); // Legalized the chain result - switch anything that used the old chain to // use the new one. @@ -507,12 +507,12 @@ N->getBasePtr(), N->getPointerInfo(), N->getMemoryVT().getVectorElementType(), N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getTBAAInfo()); + N->getAlignment(), N->getAAInfo()); return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)), N->getBasePtr(), N->getPointerInfo(), N->isVolatile(), N->isNonTemporal(), - N->getOriginalAlignment(), N->getTBAAInfo()); + N->getOriginalAlignment(), N->getAAInfo()); } /// ScalarizeVecOp_FP_ROUND - If the value to round is a vector that needs @@ -921,14 +921,14 @@ bool isVolatile = LD->isVolatile(); bool isNonTemporal = LD->isNonTemporal(); bool isInvariant = LD->isInvariant(); - const MDNode *TBAAInfo = LD->getTBAAInfo(); + AAMDNodes AAInfo = LD->getAAInfo(); EVT LoMemVT, HiMemVT; std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT); Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset, LD->getPointerInfo(), LoMemVT, isVolatile, isNonTemporal, - isInvariant, Alignment, TBAAInfo); + isInvariant, Alignment, AAInfo); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -936,7 +936,7 @@ Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, LD->getPointerInfo().getWithOffset(IncrementSize), HiMemVT, isVolatile, isNonTemporal, isInvariant, Alignment, - TBAAInfo); + AAInfo); // Build a factor node to remember that this load is independent of the // other one. @@ -1372,7 +1372,7 @@ unsigned Alignment = N->getOriginalAlignment(); bool isVol = N->isVolatile(); bool isNT = N->isNonTemporal(); - const MDNode *TBAAInfo = N->getTBAAInfo(); + AAMDNodes AAInfo = N->getAAInfo(); SDValue Lo, Hi; GetSplitVector(N->getOperand(1), Lo, Hi); @@ -1383,10 +1383,10 @@ if (isTruncating) Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), - LoMemVT, isVol, isNT, Alignment, TBAAInfo); + LoMemVT, isVol, isNT, Alignment, AAInfo); else Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), - isVol, isNT, Alignment, TBAAInfo); + isVol, isNT, Alignment, AAInfo); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, @@ -1395,11 +1395,11 @@ if (isTruncating) Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, N->getPointerInfo().getWithOffset(IncrementSize), - HiMemVT, isVol, isNT, Alignment, TBAAInfo); + HiMemVT, isVol, isNT, Alignment, AAInfo); else Hi = DAG.getStore(Ch, DL, Hi, Ptr, N->getPointerInfo().getWithOffset(IncrementSize), - isVol, isNT, Alignment, TBAAInfo); + isVol, isNT, Alignment, AAInfo); return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi); } @@ -2735,7 +2735,7 @@ bool isVolatile = LD->isVolatile(); bool isNonTemporal = LD->isNonTemporal(); bool isInvariant = LD->isInvariant(); - const MDNode *TBAAInfo = LD->getTBAAInfo(); + AAMDNodes AAInfo = LD->getAAInfo(); int LdWidth = LdVT.getSizeInBits(); int WidthDiff = WidenWidth - LdWidth; // Difference @@ -2746,7 +2746,7 @@ int NewVTWidth = NewVT.getSizeInBits(); SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, LD->getPointerInfo(), isVolatile, isNonTemporal, isInvariant, Align, - TBAAInfo); + AAInfo); LdChain.push_back(LdOp.getValue(1)); // Check if we can load the element with one instruction @@ -2791,7 +2791,7 @@ L = DAG.getLoad(NewVT, dl, Chain, BasePtr, LD->getPointerInfo().getWithOffset(Offset), isVolatile, isNonTemporal, isInvariant, MinAlign(Align, Increment), - TBAAInfo); + AAInfo); LdChain.push_back(L.getValue(1)); if (L->getValueType(0).isVector()) { SmallVector Loads; @@ -2807,7 +2807,7 @@ L = DAG.getLoad(NewVT, dl, Chain, BasePtr, LD->getPointerInfo().getWithOffset(Offset), isVolatile, isNonTemporal, isInvariant, MinAlign(Align, Increment), - TBAAInfo); + AAInfo); LdChain.push_back(L.getValue(1)); } @@ -2887,7 +2887,7 @@ unsigned Align = LD->getAlignment(); bool isVolatile = LD->isVolatile(); bool isNonTemporal = LD->isNonTemporal(); - const MDNode *TBAAInfo = LD->getTBAAInfo(); + AAMDNodes AAInfo = LD->getAAInfo(); EVT EltVT = WidenVT.getVectorElementType(); EVT LdEltVT = LdVT.getVectorElementType(); @@ -2899,7 +2899,7 @@ unsigned Increment = LdEltVT.getSizeInBits() / 8; Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(), - LdEltVT, isVolatile, isNonTemporal, Align, TBAAInfo); + LdEltVT, isVolatile, isNonTemporal, Align, AAInfo); LdChain.push_back(Ops[0].getValue(1)); unsigned i = 0, Offset = Increment; for (i=1; i < NumElts; ++i, Offset += Increment) { @@ -2909,7 +2909,7 @@ BasePtr.getValueType())); Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr, LD->getPointerInfo().getWithOffset(Offset), LdEltVT, - isVolatile, isNonTemporal, Align, TBAAInfo); + isVolatile, isNonTemporal, Align, AAInfo); LdChain.push_back(Ops[i].getValue(1)); } @@ -2932,7 +2932,7 @@ unsigned Align = ST->getAlignment(); bool isVolatile = ST->isVolatile(); bool isNonTemporal = ST->isNonTemporal(); - const MDNode *TBAAInfo = ST->getTBAAInfo(); + AAMDNodes AAInfo = ST->getAAInfo(); SDValue ValOp = GetWidenedVector(ST->getValue()); SDLoc dl(ST); @@ -2959,7 +2959,7 @@ StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, ST->getPointerInfo().getWithOffset(Offset), isVolatile, isNonTemporal, - MinAlign(Align, Offset), TBAAInfo)); + MinAlign(Align, Offset), AAInfo)); StWidth -= NewVTWidth; Offset += Increment; Idx += NumVTElts; @@ -2979,7 +2979,7 @@ StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, ST->getPointerInfo().getWithOffset(Offset), isVolatile, isNonTemporal, - MinAlign(Align, Offset), TBAAInfo)); + MinAlign(Align, Offset), AAInfo)); StWidth -= NewVTWidth; Offset += Increment; BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, @@ -3001,7 +3001,7 @@ unsigned Align = ST->getAlignment(); bool isVolatile = ST->isVolatile(); bool isNonTemporal = ST->isNonTemporal(); - const MDNode *TBAAInfo = ST->getTBAAInfo(); + AAMDNodes AAInfo = ST->getAAInfo(); SDValue ValOp = GetWidenedVector(ST->getValue()); SDLoc dl(ST); @@ -3025,7 +3025,7 @@ StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr, ST->getPointerInfo(), StEltVT, isVolatile, isNonTemporal, Align, - TBAAInfo)); + AAInfo)); unsigned Offset = Increment; for (unsigned i=1; i < NumElts; ++i, Offset += Increment) { SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), @@ -3036,7 +3036,7 @@ StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr, ST->getPointerInfo().getWithOffset(Offset), StEltVT, isVolatile, isNonTemporal, - MinAlign(Align, Offset), TBAAInfo)); + MinAlign(Align, Offset), AAInfo)); } } Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4663,7 +4663,7 @@ SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, - unsigned Alignment, const MDNode *TBAAInfo, + unsigned Alignment, const AAMDNodes &AAInfo, const MDNode *Ranges) { assert(Chain.getValueType() == MVT::Other && "Invalid chain type"); @@ -4686,7 +4686,7 @@ MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, Flags, MemVT.getStoreSize(), Alignment, - TBAAInfo, Ranges); + AAInfo, Ranges); return getLoad(AM, ExtType, VT, dl, Chain, Ptr, Offset, MemVT, MMO); } @@ -4744,12 +4744,12 @@ MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, const MDNode *Ranges) { SDValue Undef = getUNDEF(Ptr.getValueType()); return getLoad(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, dl, Chain, Ptr, Undef, PtrInfo, VT, isVolatile, isNonTemporal, isInvariant, Alignment, - TBAAInfo, Ranges); + AAInfo, Ranges); } SDValue SelectionDAG::getLoad(EVT VT, SDLoc dl, @@ -4764,11 +4764,11 @@ SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, - unsigned Alignment, const MDNode *TBAAInfo) { + unsigned Alignment, const AAMDNodes &AAInfo) { SDValue Undef = getUNDEF(Ptr.getValueType()); return getLoad(ISD::UNINDEXED, ExtType, VT, dl, Chain, Ptr, Undef, PtrInfo, MemVT, isVolatile, isNonTemporal, false, Alignment, - TBAAInfo); + AAInfo); } @@ -4795,7 +4795,7 @@ SDValue SelectionDAG::getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, - unsigned Alignment, const MDNode *TBAAInfo) { + unsigned Alignment, const AAMDNodes &AAInfo) { assert(Chain.getValueType() == MVT::Other && "Invalid chain type"); if (Alignment == 0) // Ensure that codegen never sees alignment 0 @@ -4814,7 +4814,7 @@ MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, Flags, Val.getValueType().getStoreSize(), Alignment, - TBAAInfo); + AAInfo); return getStore(Chain, dl, Val, Ptr, MMO); } @@ -4850,7 +4850,7 @@ SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT,bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo) { + const AAMDNodes &AAInfo) { assert(Chain.getValueType() == MVT::Other && "Invalid chain type"); if (Alignment == 0) // Ensure that codegen never sees alignment 0 @@ -4868,7 +4868,7 @@ MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, Flags, SVT.getStoreSize(), Alignment, - TBAAInfo); + AAInfo); return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO); } Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -3467,7 +3467,9 @@ bool isNonTemporal = I.getMetadata("nontemporal") != nullptr; bool isInvariant = I.getMetadata("invariant.load") != nullptr; unsigned Alignment = I.getAlignment(); - const MDNode *TBAAInfo = I.getMetadata(LLVMContext::MD_tbaa); + + AAMDNodes AAInfo; + I.getAAMetadata(AAInfo); const MDNode *Ranges = I.getMetadata(LLVMContext::MD_range); SmallVector ValueVTs; @@ -3483,7 +3485,7 @@ // Serialize volatile loads with other side effects. Root = getRoot(); else if (AA->pointsToConstantMemory( - AliasAnalysis::Location(SV, AA->getTypeStoreSize(Ty), TBAAInfo))) { + AliasAnalysis::Location(SV, AA->getTypeStoreSize(Ty), AAInfo))) { // Do not serialize (non-volatile) loads of constant memory with anything. Root = DAG.getEntryNode(); ConstantMemory = true; @@ -3520,7 +3522,7 @@ DAG.getConstant(Offsets[i], PtrVT)); SDValue L = DAG.getLoad(ValueVTs[i], getCurSDLoc(), Root, A, MachinePointerInfo(SV, Offsets[i]), isVolatile, - isNonTemporal, isInvariant, Alignment, TBAAInfo, + isNonTemporal, isInvariant, Alignment, AAInfo, Ranges); Values[i] = L; @@ -3567,7 +3569,9 @@ bool isVolatile = I.isVolatile(); bool isNonTemporal = I.getMetadata("nontemporal") != nullptr; unsigned Alignment = I.getAlignment(); - const MDNode *TBAAInfo = I.getMetadata(LLVMContext::MD_tbaa); + + AAMDNodes AAInfo; + I.getAAMetadata(AAInfo); unsigned ChainI = 0; for (unsigned i = 0; i != NumValues; ++i, ++ChainI) { @@ -3583,7 +3587,7 @@ SDValue St = DAG.getStore(Root, getCurSDLoc(), SDValue(Src.getNode(), Src.getResNo() + i), Add, MachinePointerInfo(PtrV, Offsets[i]), - isVolatile, isNonTemporal, Alignment, TBAAInfo); + isVolatile, isNonTemporal, Alignment, AAInfo); Chains[ChainI] = St; } Index: lib/IR/IRBuilder.cpp =================================================================== --- lib/IR/IRBuilder.cpp +++ lib/IR/IRBuilder.cpp @@ -62,7 +62,8 @@ CallInst *IRBuilderBase:: CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag) { + bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, + MDNode *NoAliasTag) { Ptr = getCastedInt8PtrValue(Ptr); Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) }; Type *Tys[] = { Ptr->getType(), Size->getType() }; @@ -74,13 +75,20 @@ // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } CallInst *IRBuilderBase:: CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag) { + bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag, + MDNode *ScopeTag, MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); @@ -98,13 +106,20 @@ // Set the TBAA Struct info if present. if (TBAAStructTag) CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } CallInst *IRBuilderBase:: CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag) { + bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, + MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); @@ -118,7 +133,13 @@ // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -66,6 +66,16 @@ unsigned InvariantLdId = getMDKindID("invariant.load"); assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted"); (void)InvariantLdId; + + // Create the 'alias.scope' metadata kind. + unsigned AliasScopeID = getMDKindID("alias.scope"); + assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted"); + (void)AliasScopeID; + + // Create the 'noalias' metadata kind. + unsigned NoAliasID = getMDKindID("noalias"); + assert(NoAliasID == MD_noalias && "noalias kind id drifted"); + (void)NoAliasID; } LLVMContext::~LLVMContext() { delete pImpl; } Index: lib/IR/MDBuilder.cpp =================================================================== --- lib/IR/MDBuilder.cpp +++ lib/IR/MDBuilder.cpp @@ -60,10 +60,15 @@ return MDNode::get(Context, Range); } -MDNode *MDBuilder::createAnonymousTBAARoot() { +MDNode *MDBuilder::createAnonymousAARoot(StringRef Name) { // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef()); - MDNode *Root = MDNode::get(Context, Dummy); + MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef()); + + SmallVector Args(1, Dummy); + if (!Name.empty()) + Args.push_back(createString(Name)); + MDNode *Root = MDNode::get(Context, Args); + // At this point we have // !0 = metadata !{} <- dummy // !1 = metadata !{metadata !0} <- root @@ -93,6 +98,15 @@ } } +MDNode *MDBuilder::createAliasScopeRoot(StringRef Name) { + return MDNode::get(Context, createString(Name)); +} + +MDNode *MDBuilder::createAliasScopeNode(StringRef Name, MDNode *Parent) { + Value *Ops[2] = { createString(Name), Parent }; + return MDNode::get(Context, Ops); +} + /// \brief Return metadata for a tbaa.struct node with the given /// struct field descriptions. MDNode *MDBuilder::createTBAAStructNode(ArrayRef Fields) { Index: lib/IR/Metadata.cpp =================================================================== --- lib/IR/Metadata.cpp +++ lib/IR/Metadata.cpp @@ -406,6 +406,41 @@ } } +MDNode *MDNode::concatenate(MDNode *A, MDNode *B) { + if (!A) + return B; + if (!B) + return A; + + SmallVector Vals(A->getNumOperands() + + B->getNumOperands()); + + unsigned j = 0; + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) + Vals[j++] = A->getOperand(i); + for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i) + Vals[j++] = B->getOperand(i); + + return MDNode::get(A->getContext(), Vals); +} + +MDNode *MDNode::intersect(MDNode *A, MDNode *B) { + if (!A || !B) + return nullptr; + + SmallVector Vals; + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) { + Value *V = A->getOperand(i); + for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j) + if (V == B->getOperand(j)) { + Vals.push_back(V); + break; + } + } + + return MDNode::get(A->getContext(), Vals); +} + MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) { if (!A || !B) return nullptr; @@ -687,6 +722,12 @@ // Otherwise, removing an entry that doesn't exist on the instruction. } +void Instruction::setAAMetadata(const AAMDNodes &N) { + setMetadata(LLVMContext::MD_tbaa, N.TBAA); + setMetadata(LLVMContext::MD_alias_scope, N.Scope); + setMetadata(LLVMContext::MD_noalias, N.NoAlias); +} + MDNode *Instruction::getMetadataImpl(unsigned KindID) const { // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -8606,7 +8606,7 @@ return DAG.getStore(St->getChain(), dl, V, St->getBasePtr(), St->getPointerInfo(), St->isVolatile(), St->isNonTemporal(), St->getAlignment(), - St->getTBAAInfo()); + St->getAAInfo()); } /// hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node Index: lib/Target/Mips/MipsSEISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEISelLowering.cpp +++ lib/Target/Mips/MipsSEISelLowering.cpp @@ -1246,13 +1246,13 @@ // i32 store to lower address. Chain = DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.isVolatile(), Nd.isNonTemporal(), Nd.getAlignment(), - Nd.getTBAAInfo()); + Nd.getAAInfo()); // i32 store to higher address. Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, PtrVT)); return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(), Nd.isVolatile(), Nd.isNonTemporal(), - std::min(Nd.getAlignment(), 4U), Nd.getTBAAInfo()); + std::min(Nd.getAlignment(), 4U), Nd.getAAInfo()); } SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, Index: lib/Target/SystemZ/SystemZISelDAGToDAG.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -1000,8 +1000,8 @@ if (V1 == V2 && End1 == End2) return false; - return !AA->alias(AliasAnalysis::Location(V1, End1, Load->getTBAAInfo()), - AliasAnalysis::Location(V2, End2, Store->getTBAAInfo())); + return !AA->alias(AliasAnalysis::Location(V1, End1, Load->getAAInfo()), + AliasAnalysis::Location(V2, End2, Store->getAAInfo())); } bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const { Index: lib/Target/XCore/XCoreISelLowering.cpp =================================================================== --- lib/Target/XCore/XCoreISelLowering.cpp +++ lib/Target/XCore/XCoreISelLowering.cpp @@ -969,7 +969,7 @@ N->getBasePtr(), N->getPointerInfo(), N->isVolatile(), N->isNonTemporal(), N->isInvariant(), N->getAlignment(), - N->getTBAAInfo(), N->getRanges()); + N->getAAInfo(), N->getRanges()); } if (N->getMemoryVT() == MVT::i16) { if (N->getAlignment() < 2) @@ -977,13 +977,13 @@ return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), N->getBasePtr(), N->getPointerInfo(), MVT::i16, N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getTBAAInfo()); + N->getAlignment(), N->getAAInfo()); } if (N->getMemoryVT() == MVT::i8) return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), N->getBasePtr(), N->getPointerInfo(), MVT::i8, N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getTBAAInfo()); + N->getAlignment(), N->getAAInfo()); return SDValue(); } @@ -999,7 +999,7 @@ return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), N->getPointerInfo(), N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getTBAAInfo()); + N->getAlignment(), N->getAAInfo()); } if (N->getMemoryVT() == MVT::i16) { if (N->getAlignment() < 2) @@ -1007,13 +1007,13 @@ return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), N->getPointerInfo(), MVT::i16, N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getTBAAInfo()); + N->getAlignment(), N->getAAInfo()); } if (N->getMemoryVT() == MVT::i8) return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), N->getPointerInfo(), MVT::i8, N->isVolatile(), N->isNonTemporal(), - N->getAlignment(), N->getTBAAInfo()); + N->getAlignment(), N->getAAInfo()); return SDValue(); } Index: lib/Transforms/IPO/ArgumentPromotion.cpp =================================================================== --- lib/Transforms/IPO/ArgumentPromotion.cpp +++ lib/Transforms/IPO/ArgumentPromotion.cpp @@ -716,9 +716,11 @@ // of the previous load. LoadInst *newLoad = new LoadInst(V, V->getName()+".val", Call); newLoad->setAlignment(OrigLoad->getAlignment()); - // Transfer the TBAA info too. - newLoad->setMetadata(LLVMContext::MD_tbaa, - OrigLoad->getMetadata(LLVMContext::MD_tbaa)); + // Transfer the AA info too. + AAMDNodes AAInfo; + OrigLoad->getAAMetadata(AAInfo); + newLoad->setAAMetadata(AAInfo); + Args.push_back(newLoad); AA.copyValue(OrigLoad, Args.back()); } Index: lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- lib/Transforms/IPO/FunctionAttrs.cpp +++ lib/Transforms/IPO/FunctionAttrs.cpp @@ -204,9 +204,11 @@ CI != CE; ++CI) { Value *Arg = *CI; if (Arg->getType()->isPointerTy()) { + AAMDNodes AAInfo; + I->getAAMetadata(AAInfo); + AliasAnalysis::Location Loc(Arg, - AliasAnalysis::UnknownSize, - I->getMetadata(LLVMContext::MD_tbaa)); + AliasAnalysis::UnknownSize, AAInfo); if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) { if (MRB & AliasAnalysis::Mod) // Writes non-local memory. Give up. Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -107,6 +107,7 @@ // BasicAliasAnalysis wins if they disagree. This is intended to help // support "obvious" type-punning idioms. PM.add(createTypeBasedAliasAnalysisPass()); + PM.add(createScopedNoAliasAAPass()); PM.add(createBasicAliasAnalysisPass()); } Index: lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -836,12 +836,13 @@ InsertNewInstBefore(NewSI, *BBI); NewSI->setDebugLoc(OtherStore->getDebugLoc()); - // If the two stores had the same TBAA tag, preserve it. - if (MDNode *TBAATag = SI.getMetadata(LLVMContext::MD_tbaa)) - if ((TBAATag = MDNode::getMostGenericTBAA(TBAATag, - OtherStore->getMetadata(LLVMContext::MD_tbaa)))) - NewSI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + // If the two stores had AA tags, merge them. + AAMDNodes AATags; + SI.getAAMetadata(AATags); + if (AATags) { + OtherStore->getAAMetadata(AATags, /* Merge = */ true); + NewSI->setAAMetadata(AATags); + } // Nuke the old stores. EraseInstFromFunction(SI); Index: lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp =================================================================== --- lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp +++ lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp @@ -62,8 +62,8 @@ const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr); const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr); AliasResult Result = - AliasAnalysis::alias(Location(SA, LocA.Size, LocA.TBAATag), - Location(SB, LocB.Size, LocB.TBAATag)); + AliasAnalysis::alias(Location(SA, LocA.Size, LocA.AATags), + Location(SB, LocB.Size, LocB.AATags)); if (Result != MayAlias) return Result; @@ -93,7 +93,7 @@ // First, strip off no-ops, including ObjC-specific no-ops, and try making // a precise alias query. const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr); - if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.TBAATag), + if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.AATags), OrLocal)) return true; Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -1669,9 +1669,11 @@ LI->getAlignment(), UnavailablePred->getTerminator()); - // Transfer the old load's TBAA tag to the new load. - if (MDNode *Tag = LI->getMetadata(LLVMContext::MD_tbaa)) - NewLoad->setMetadata(LLVMContext::MD_tbaa, Tag); + // Transfer the old load's AA tags to the new load. + AAMDNodes Tags; + LI->getAAMetadata(Tags); + if (Tags) + NewLoad->setAAMetadata(Tags); // Transfer DebugLoc. NewLoad->setDebugLoc(LI->getDebugLoc()); @@ -1789,6 +1791,19 @@ case LLVMContext::MD_tbaa: ReplInst->setMetadata(Kind, MDNode::getMostGenericTBAA(IMD, ReplMD)); break; + case LLVMContext::MD_alias_scope: + case LLVMContext::MD_noalias: + // FIXME: If both the original and replacement value are part of the + // same control-flow region (meaning that the execution of one + // guarentees the executation of the other), then we can combine the + // noalias scopes here and do better than the general conservative + // answer. + + // In general, GVN unifies expressions over different control-flow + // regions, and so we need a conservative combination of the noalias + // scopes. + ReplInst->setMetadata(Kind, MDNode::intersect(IMD, ReplMD)); + break; case LLVMContext::MD_range: ReplInst->setMetadata(Kind, MDNode::getMostGenericRange(IMD, ReplMD)); break; Index: lib/Transforms/Scalar/JumpThreading.cpp =================================================================== --- lib/Transforms/Scalar/JumpThreading.cpp +++ lib/Transforms/Scalar/JumpThreading.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" @@ -888,9 +889,10 @@ if (BBIt != LoadBB->begin()) return false; - // If all of the loads and stores that feed the value have the same TBAA tag, - // then we can propagate it onto any newly inserted loads. - MDNode *TBAATag = LI->getMetadata(LLVMContext::MD_tbaa); + // If all of the loads and stores that feed the value have the same AA tags, + // then we can propagate them onto any newly inserted loads. + AAMDNodes AATags; + LI->getAAMetadata(AATags); SmallPtrSet PredsScanned; typedef SmallVector, 8> AvailablePredsTy; @@ -909,16 +911,16 @@ // Scan the predecessor to see if the value is available in the pred. BBIt = PredBB->end(); - MDNode *ThisTBAATag = nullptr; + AAMDNodes ThisAATags; Value *PredAvailable = FindAvailableLoadedValue(LoadedPtr, PredBB, BBIt, 6, - nullptr, &ThisTBAATag); + nullptr, &ThisAATags); if (!PredAvailable) { OneUnavailablePred = PredBB; continue; } - // If tbaa tags disagree or are not present, forget about them. - if (TBAATag != ThisTBAATag) TBAATag = nullptr; + // If AA tags disagree or are not present, forget about them. + if (AATags != ThisAATags) AATags = AAMDNodes(); // If so, this load is partially redundant. Remember this info so that we // can create a PHI node. @@ -978,8 +980,8 @@ LI->getAlignment(), UnavailablePred->getTerminator()); NewVal->setDebugLoc(LI->getDebugLoc()); - if (TBAATag) - NewVal->setMetadata(LLVMContext::MD_tbaa, TBAATag); + if (AATags) + NewVal->setAAMetadata(AATags); AvailablePreds.push_back(std::make_pair(UnavailablePred, NewVal)); } Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -180,9 +180,9 @@ /// store into the memory location pointed to by V. /// bool pointerInvalidatedByLoop(Value *V, uint64_t Size, - const MDNode *TBAAInfo) { + const AAMDNodes &AAInfo) { // Check to see if any of the basic blocks in CurLoop invalidate *V. - return CurAST->getAliasSetForPointer(V, Size, TBAAInfo).isMod(); + return CurAST->getAliasSetForPointer(V, Size, AAInfo).isMod(); } bool canSinkOrHoistInst(Instruction &I); @@ -448,8 +448,11 @@ uint64_t Size = 0; if (LI->getType()->isSized()) Size = AA->getTypeStoreSize(LI->getType()); - return !pointerInvalidatedByLoop(LI->getOperand(0), Size, - LI->getMetadata(LLVMContext::MD_tbaa)); + + AAMDNodes AAInfo; + LI->getAAMetadata(AAInfo); + + return !pointerInvalidatedByLoop(LI->getOperand(0), Size, AAInfo); } else if (CallInst *CI = dyn_cast(&I)) { // Don't sink or hoist dbg info; it's legal, but not useful. if (isa(I)) @@ -690,7 +693,7 @@ LoopInfo &LI; DebugLoc DL; int Alignment; - MDNode *TBAATag; + AAMDNodes AATags; Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const { if (Instruction *I = dyn_cast(V)) @@ -714,10 +717,10 @@ SmallVectorImpl &LEB, SmallVectorImpl &LIP, PredIteratorCache &PIC, AliasSetTracker &ast, LoopInfo &li, DebugLoc dl, int alignment, - MDNode *TBAATag) + const AAMDNodes &AATags) : LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA), LoopExitBlocks(LEB), LoopInsertPts(LIP), PredCache(PIC), AST(ast), - LI(li), DL(dl), Alignment(alignment), TBAATag(TBAATag) {} + LI(li), DL(dl), Alignment(alignment), AATags(AATags) {} bool isInstInList(Instruction *I, const SmallVectorImpl &) const override { @@ -743,7 +746,7 @@ StoreInst *NewSI = new StoreInst(LiveInValue, Ptr, InsertPos); NewSI->setAlignment(Alignment); NewSI->setDebugLoc(DL); - if (TBAATag) NewSI->setMetadata(LLVMContext::MD_tbaa, TBAATag); + if (AATags) NewSI->setAAMetadata(AATags); } } @@ -798,11 +801,11 @@ // We start with an alignment of one and try to find instructions that allow // us to prove better alignment. unsigned Alignment = 1; - MDNode *TBAATag = nullptr; + AAMDNodes AATags; // Check that all of the pointers in the alias set have the same type. We // cannot (yet) promote a memory location that is loaded and stored in - // different sizes. While we are at it, collect alignment and TBAA info. + // different sizes. While we are at it, collect alignment and AA info. for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) { Value *ASIV = ASI->getValue(); PointerMustAliases.insert(ASIV); @@ -855,13 +858,12 @@ } else return; // Not a load or store. - // Merge the TBAA tags. + // Merge the AA tags. if (LoopUses.empty()) { - // On the first load/store, just take its TBAA tag. - TBAATag = UI->getMetadata(LLVMContext::MD_tbaa); - } else if (TBAATag) { - TBAATag = MDNode::getMostGenericTBAA(TBAATag, - UI->getMetadata(LLVMContext::MD_tbaa)); + // On the first load/store, just take its AA tags. + UI->getAAMetadata(AATags); + } else if (AATags) { + UI->getAAMetadata(AATags, /* Merge = */ true); } LoopUses.push_back(UI); @@ -896,7 +898,7 @@ SmallVector NewPHIs; SSAUpdater SSA(&NewPHIs); LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks, - InsertPts, PIC, *CurAST, *LI, DL, Alignment, TBAATag); + InsertPts, PIC, *CurAST, *LI, DL, Alignment, AATags); // Set up the preheader to have a definition of the value. It is the live-out // value from the preheader that uses in the loop will use. @@ -905,7 +907,7 @@ Preheader->getTerminator()); PreheaderLoad->setAlignment(Alignment); PreheaderLoad->setDebugLoc(DL); - if (TBAATag) PreheaderLoad->setMetadata(LLVMContext::MD_tbaa, TBAATag); + if (AATags) PreheaderLoad->setAAMetadata(AATags); SSA.AddAvailableValue(Preheader, PreheaderLoad); // Rewrite all the loads in the loop and remember all the definitions from Index: lib/Transforms/Scalar/SROA.cpp =================================================================== --- lib/Transforms/Scalar/SROA.cpp +++ lib/Transforms/Scalar/SROA.cpp @@ -1148,10 +1148,12 @@ PHINode *NewPN = PHIBuilder.CreatePHI(LoadTy, PN.getNumIncomingValues(), PN.getName() + ".sroa.speculated"); - // Get the TBAA tag and alignment to use from one of the loads. It doesn't + // Get the AA tags and alignment to use from one of the loads. It doesn't // matter which one we get and if any differ. LoadInst *SomeLoad = cast(PN.user_back()); - MDNode *TBAATag = SomeLoad->getMetadata(LLVMContext::MD_tbaa); + + AAMDNodes AATags; + SomeLoad->getAAMetadata(AATags); unsigned Align = SomeLoad->getAlignment(); // Rewrite all loads of the PN to use the new PHI. @@ -1172,8 +1174,8 @@ InVal, (PN.getName() + ".sroa.speculate.load." + Pred->getName())); ++NumLoadsSpeculated; Load->setAlignment(Align); - if (TBAATag) - Load->setMetadata(LLVMContext::MD_tbaa, TBAATag); + if (AATags) + Load->setAAMetadata(AATags); NewPN->addIncoming(Load, Pred); } @@ -1238,12 +1240,15 @@ IRB.CreateLoad(FV, LI->getName() + ".sroa.speculate.load.false"); NumLoadsSpeculated += 2; - // Transfer alignment and TBAA info if present. + // Transfer alignment and AA info if present. TL->setAlignment(LI->getAlignment()); FL->setAlignment(LI->getAlignment()); - if (MDNode *Tag = LI->getMetadata(LLVMContext::MD_tbaa)) { - TL->setMetadata(LLVMContext::MD_tbaa, Tag); - FL->setMetadata(LLVMContext::MD_tbaa, Tag); + + AAMDNodes Tags; + LI->getAAMetadata(Tags); + if (Tags) { + TL->setAAMetadata(Tags); + FL->setAAMetadata(Tags); } Value *V = IRB.CreateSelect(SI.getCondition(), TL, FL, Index: lib/Transforms/Scalar/Scalar.cpp =================================================================== --- lib/Transforms/Scalar/Scalar.cpp +++ lib/Transforms/Scalar/Scalar.cpp @@ -203,6 +203,10 @@ unwrap(PM)->add(createTypeBasedAliasAnalysisPass()); } +void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createScopedNoAliasAAPass()); +} + void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createBasicAliasAnalysisPass()); } Index: lib/Transforms/Scalar/ScalarReplAggregates.cpp =================================================================== --- lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -1333,12 +1333,15 @@ LoadInst *FalseLoad = Builder.CreateLoad(SI->getFalseValue(), LI->getName()+".f"); - // Transfer alignment and TBAA info if present. + // Transfer alignment and AA info if present. TrueLoad->setAlignment(LI->getAlignment()); FalseLoad->setAlignment(LI->getAlignment()); - if (MDNode *Tag = LI->getMetadata(LLVMContext::MD_tbaa)) { - TrueLoad->setMetadata(LLVMContext::MD_tbaa, Tag); - FalseLoad->setMetadata(LLVMContext::MD_tbaa, Tag); + + AAMDNodes Tags; + LI->getAAMetadata(Tags); + if (Tags) { + TrueLoad->setAAMetadata(Tags); + FalseLoad->setAAMetadata(Tags); } Value *V = Builder.CreateSelect(SI->getCondition(), TrueLoad, FalseLoad); @@ -1364,10 +1367,12 @@ PHINode *NewPN = PHINode::Create(LoadTy, PN->getNumIncomingValues(), PN->getName()+".ld", PN); - // Get the TBAA tag and alignment to use from one of the loads. It doesn't + // Get the AA tags and alignment to use from one of the loads. It doesn't // matter which one we get and if any differ, it doesn't matter. LoadInst *SomeLoad = cast(PN->user_back()); - MDNode *TBAATag = SomeLoad->getMetadata(LLVMContext::MD_tbaa); + + AAMDNodes AATags; + SomeLoad->getAAMetadata(AATags); unsigned Align = SomeLoad->getAlignment(); // Rewrite all loads of the PN to use the new PHI. @@ -1389,7 +1394,7 @@ PN->getName() + "." + Pred->getName(), Pred->getTerminator()); Load->setAlignment(Align); - if (TBAATag) Load->setMetadata(LLVMContext::MD_tbaa, TBAATag); + if (AATags) Load->setAAMetadata(AATags); } NewPN->addIncoming(Load, Pred); Index: lib/Transforms/Scalar/Scalarizer.cpp =================================================================== --- lib/Transforms/Scalar/Scalarizer.cpp +++ lib/Transforms/Scalar/Scalarizer.cpp @@ -312,6 +312,8 @@ || Tag == LLVMContext::MD_fpmath || Tag == LLVMContext::MD_tbaa_struct || Tag == LLVMContext::MD_invariant_load + || Tag == LLVMContext::MD_alias_scope + || Tag == LLVMContext::MD_noalias || Tag == ParallelLoopAccessMDKind); } Index: lib/Transforms/Utils/InlineFunction.cpp =================================================================== --- lib/Transforms/Utils/InlineFunction.cpp +++ lib/Transforms/Utils/InlineFunction.cpp @@ -13,10 +13,13 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CFG.h" @@ -28,6 +31,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -260,6 +264,224 @@ InvokeDest->removePredecessor(II->getParent()); } +/// CloneAliasScopeMetadata - When inlining a function that contains noalias +/// scope metadata, this metadata needs to be cloned so that the inlined blocks +/// have different "unqiue scopes" at every call site. Were this not done, then +/// aliasing scopes from a function inlined into a caller multiple times could +/// not be differentiated (and this would lead to miscompiles because the +/// non-aliasing property communicated by the metadata could have +/// call-site-specific control dependencies). +static void CloneAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap) { + const Function *CalledFunc = CS.getCalledFunction(); + SetVector MD; + + // Note: We could only clone the metadata if it is already used in the + // callee. I'm omitting that check here because it might confuse + // inter-procedural alias analysis passes. We can revisit this if it becomes + // an efficiency or overhead problem. + + for (Function::const_iterator I = CalledFunc->begin(), IE = CalledFunc->end(); + I != IE; ++I) + for (BasicBlock::const_iterator J = I->begin(), JE = I->end(); J != JE; ++J) { + if (const MDNode *M = J->getMetadata(LLVMContext::MD_alias_scope)) + MD.insert(M); + if (const MDNode *M = J->getMetadata(LLVMContext::MD_noalias)) + MD.insert(M); + } + + if (MD.empty()) + return; + + // Walk the existing metadata, adding the complete (perhaps cyclic) chain to + // the set. + SmallVector Queue(MD.begin(), MD.end()); + while (!Queue.empty()) { + const MDNode *M = cast(Queue.pop_back_val()); + for (unsigned i = 0, ie = M->getNumOperands(); i != ie; ++i) + if (const MDNode *M1 = dyn_cast(M->getOperand(i))) + if (MD.insert(M1)) + Queue.push_back(M1); + } + + // Now we have a complete set of all metadata in the chains used to specify + // the noalias scopes and the lists of those scopes. + SmallVector DummyNodes; + DenseMap > MDMap; + for (SetVector::iterator I = MD.begin(), IE = MD.end(); + I != IE; ++I) { + MDNode *Dummy = MDNode::getTemporary(CalledFunc->getContext(), + ArrayRef()); + DummyNodes.push_back(Dummy); + MDMap[*I] = Dummy; + } + + // Create new metadata nodes to replace the dummy nodes, replacing old + // metadata references with either a dummy node or an already-created new + // node. + for (SetVector::iterator I = MD.begin(), IE = MD.end(); + I != IE; ++I) { + SmallVector NewOps; + for (unsigned i = 0, ie = (*I)->getNumOperands(); i != ie; ++i) { + const Value *V = (*I)->getOperand(i); + if (const MDNode *M = dyn_cast(V)) + NewOps.push_back(MDMap[M]); + else + NewOps.push_back(const_cast(V)); + } + + MDNode *NewM = MDNode::get(CalledFunc->getContext(), NewOps), + *TempM = MDMap[*I]; + + TempM->replaceAllUsesWith(NewM); + } + + // Now replace the metadata in the new inlined instructions with the + // repacements from the map. + for (ValueToValueMapTy::iterator VMI = VMap.begin(), VMIE = VMap.end(); + VMI != VMIE; ++VMI) { + if (!VMI->second) + continue; + + Instruction *NI = dyn_cast(VMI->second); + if (!NI) + continue; + + if (MDNode *M = NI->getMetadata(LLVMContext::MD_alias_scope)) + NI->setMetadata(LLVMContext::MD_alias_scope, MDMap[M]); + + if (MDNode *M = NI->getMetadata(LLVMContext::MD_noalias)) + NI->setMetadata(LLVMContext::MD_noalias, MDMap[M]); + } + + // Now that everything has been replaced, delete the dummy nodes. + for (unsigned i = 0, ie = DummyNodes.size(); i != ie; ++i) + MDNode::deleteTemporary(DummyNodes[i]); +} + +/// AddAliasScopeMetadata - If the inlined function has noalias arguments, then +/// add new alias scopes for each noalias argument, tag the mapped noalias +/// parameters with noalias metadata specifying the new scope, and tag all +/// non-derived loads, stores and memory intrinsics with the new alias scopes. +static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap, + const DataLayout *DL) { + const Function *CalledFunc = CS.getCalledFunction(); + SmallVector NoAliasArgs; + + for (Function::const_arg_iterator I = CalledFunc->arg_begin(), + E = CalledFunc->arg_end(); I != E; ++I) { + if (I->hasNoAliasAttr() && !I->hasNUses(0)) + NoAliasArgs.push_back(I); + } + + if (NoAliasArgs.empty()) + return; + + // noalias indicates that pointer values based on the argument do not alias + // pointer values which are not based on it. So we add a new "scope" for each + // noalias function argument. Accesses using pointers based on that argument + // become part of that alias scope, accesses using pointers not based on that + // argument are tagged as noalias with that scope. + + DenseMap NewScopes; + MDBuilder MDB(CalledFunc->getContext()); + for (unsigned i = 0, e = NoAliasArgs.size(); i != e; ++i) { + const Argument *A = NoAliasArgs[i]; + + std::string Name = CalledFunc->getName(); + if (A->hasName()) { + Name += ": %"; + Name += A->getName(); + } else { + Name += ": argument "; + Name += utostr(i); + } + + // Note: We always create a new anonymous root here. This is true regardless + // of the linkage of the callee because the aliasing "scope" is not just a + // property of the callee, but also all control dependencies in the caller. + MDNode *NewScope = MDB.createAnonymousAliasScopeRoot(Name); + NewScopes.insert(std::make_pair(A, NewScope)); + } + + // Iterate over all new instructions in the map; for all memory-access + // instructions, add the alias scope metadata. + for (ValueToValueMapTy::iterator VMI = VMap.begin(), VMIE = VMap.end(); + VMI != VMIE; ++VMI) { + if (const Instruction *I = dyn_cast(VMI->first)) { + if (!VMI->second) + continue; + + Instruction *NI = dyn_cast(VMI->second); + if (!NI) + continue; + + SmallVector PtrArgs; + + if (const LoadInst *LI = dyn_cast(I)) + PtrArgs.push_back(LI->getPointerOperand()); + else if (const StoreInst *SI = dyn_cast(I)) + PtrArgs.push_back(SI->getPointerOperand()); + else if (const VAArgInst *VAAI = dyn_cast(I)) + PtrArgs.push_back(VAAI->getPointerOperand()); + else if (const AtomicCmpXchgInst *CXI = dyn_cast(I)) + PtrArgs.push_back(CXI->getPointerOperand()); + else if (const AtomicRMWInst *RMWI = dyn_cast(I)) + PtrArgs.push_back(RMWI->getPointerOperand()); + else if (const MemIntrinsic *MI = dyn_cast(I)) { + PtrArgs.push_back(MI->getRawDest()); + if (const MemTransferInst *MTI = dyn_cast(MI)) + PtrArgs.push_back(MTI->getRawSource()); + } + + // If we found no pointers, then this instruction is not suitable for + // pairing with an instruction to receive aliasing metadata. + // Simplification during cloning could make this happen, and skip these + // cases for now. + if (PtrArgs.empty()) + continue; + + SmallSetVector NAPtrArgs; + for (unsigned i = 0, ie = PtrArgs.size(); i != ie; ++i) { + SmallVector Objects; + GetUnderlyingObjects(const_cast(PtrArgs[i]), Objects, + DL, /* MaxLookup = */ 0); + + for (unsigned j = 0, je = Objects.size(); j != je; ++j) + if (Argument *A = dyn_cast(Objects[j])) + if (A->hasNoAliasAttr()) + NAPtrArgs.insert(A); + } + + SmallVector Scopes, NoAliases; + for (unsigned i = 0, e = NAPtrArgs.size(); i != e; ++i) + NoAliases.push_back(NewScopes[NAPtrArgs[i]]); + + if (!NoAliases.empty()) + NI->setMetadata(LLVMContext::MD_noalias, MDNode::concatenate( + NI->getMetadata(LLVMContext::MD_noalias), + MDNode::get(CalledFunc->getContext(), NoAliases))); + + for (unsigned i = 0, ie = NoAliasArgs.size(); i != ie; ++i) { + bool Found = false; + for (unsigned j = 0, je = NAPtrArgs.size(); j != je; ++j) { + if (NoAliasArgs[i] == NAPtrArgs[j]) { + Found = true; + break; + } + } + + if (!Found) + Scopes.push_back(NewScopes[NoAliasArgs[i]]); + } + + if (!Scopes.empty()) + NI->setMetadata(LLVMContext::MD_alias_scope, MDNode::concatenate( + NI->getMetadata(LLVMContext::MD_alias_scope), + MDNode::get(CalledFunc->getContext(), Scopes))); + } + } +} + /// UpdateCallGraphAfterInlining - Once we have cloned code over from a callee /// into the caller, update the specified callgraph to reflect the changes we /// made. Note that it's possible that not all code was copied over, so only @@ -648,6 +870,12 @@ // Update inlined instructions' line number information. fixupLineNumbers(Caller, FirstNewBlock, TheCall); + + // Clone existing noalias metadata if necessary. + CloneAliasScopeMetadata(CS, VMap); + + // Add noalias metadata if necessary. + AddAliasScopeMetadata(CS, VMap, IFI.DL); } // If there are any alloca instructions in the block that used to be the entry Index: lib/Transforms/Vectorize/BBVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/BBVectorize.cpp +++ lib/Transforms/Vectorize/BBVectorize.cpp @@ -2982,6 +2982,10 @@ case LLVMContext::MD_tbaa: K->setMetadata(Kind, MDNode::getMostGenericTBAA(JMD, KMD)); break; + case LLVMContext::MD_alias_scope: + case LLVMContext::MD_noalias: + K->setMetadata(Kind, MDNode::intersect(JMD, KMD)); + break; case LLVMContext::MD_fpmath: K->setMetadata(Kind, MDNode::getMostGenericFPMath(JMD, KMD)); break; Index: lib/Transforms/Vectorize/SLPVectorizer.cpp =================================================================== --- lib/Transforms/Vectorize/SLPVectorizer.cpp +++ lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -230,6 +230,10 @@ case LLVMContext::MD_tbaa: MD = MDNode::getMostGenericTBAA(MD, IMD); break; + case LLVMContext::MD_alias_scope: + case LLVMContext::MD_noalias: + MD = MDNode::intersect(MD, IMD); + break; case LLVMContext::MD_fpmath: MD = MDNode::getMostGenericFPMath(MD, IMD); break; Index: test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll =================================================================== --- /dev/null +++ test/Analysis/ScopedNoAliasAA/basic-hierarchy.ll @@ -0,0 +1,80 @@ +; RUN: opt < %s -basicaa -scoped-noalias -aa-eval -evaluate-aa-metadata -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo1(float* nocapture %a, float* nocapture readonly %c) #0 { +entry: +; CHECK-LABEL: Function: foo1 + %0 = load float* %c, align 4, !alias.scope !0 + %arrayidx.i = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx.i, align 4, !noalias !0 + + %1 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %1, float* %arrayidx, align 4 + + %2 = load float* %c, align 4, !alias.scope !1 + %arrayidx.i2 = getelementptr inbounds float* %a, i64 15 + store float %2, float* %arrayidx.i2, align 4, !noalias !3 + + %3 = load float* %c, align 4, !alias.scope !3 + %arrayidx.i3 = getelementptr inbounds float* %a, i64 16 + store float %3, float* %arrayidx.i3, align 4, !noalias !0 + + %4 = load float* %c, align 4, !alias.scope !5 + %arrayidx.i4 = getelementptr inbounds float* %a, i64 17 + store float %4, float* %arrayidx.i4, align 4, !noalias !3 + ret void +} + +attributes #0 = { nounwind uwtable } + +; A root scope (which doubles as a list of itself): +!0 = metadata !{metadata !0} + +; Two child scopes (which must be self-referential to avoid being "uniqued"): +!1 = metadata !{metadata !2} +!2 = metadata !{metadata !2, metadata !0} + +!3 = metadata !{metadata !4} +!4 = metadata !{metadata !4, metadata !0} + +; A list of the two children: +!5 = metadata !{metadata !2, metadata !4} + +; CHECK: NoAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %1, float* %arrayidx, align 4 +; CHECK: MayAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: NoAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %3, float* %arrayidx.i3, align 4, !noalias !0 +; CHECK: MayAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %4, float* %arrayidx.i4, align 4, !noalias !3 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %1, float* %arrayidx, align 4 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %3, float* %arrayidx.i3, align 4, !noalias !0 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %4, float* %arrayidx.i4, align 4, !noalias !3 +; CHECK: NoAlias: %2 = load float* %c, align 4, !alias.scope !1 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %2 = load float* %c, align 4, !alias.scope !1 <-> store float %1, float* %arrayidx, align 4 +; CHECK: MayAlias: %2 = load float* %c, align 4, !alias.scope !1 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: NoAlias: %2 = load float* %c, align 4, !alias.scope !1 <-> store float %3, float* %arrayidx.i3, align 4, !noalias !0 +; CHECK: MayAlias: %2 = load float* %c, align 4, !alias.scope !1 <-> store float %4, float* %arrayidx.i4, align 4, !noalias !3 +; CHECK: NoAlias: %3 = load float* %c, align 4, !alias.scope !3 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %3 = load float* %c, align 4, !alias.scope !3 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: %3 = load float* %c, align 4, !alias.scope !3 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: NoAlias: %3 = load float* %c, align 4, !alias.scope !3 <-> store float %3, float* %arrayidx.i3, align 4, !noalias !0 +; CHECK: NoAlias: %3 = load float* %c, align 4, !alias.scope !3 <-> store float %4, float* %arrayidx.i4, align 4, !noalias !3 +; CHECK: NoAlias: %4 = load float* %c, align 4, !alias.scope !5 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %4 = load float* %c, align 4, !alias.scope !5 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: %4 = load float* %c, align 4, !alias.scope !5 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: NoAlias: %4 = load float* %c, align 4, !alias.scope !5 <-> store float %3, float* %arrayidx.i3, align 4, !noalias !0 +; CHECK: NoAlias: %4 = load float* %c, align 4, !alias.scope !5 <-> store float %4, float* %arrayidx.i4, align 4, !noalias !3 +; CHECK: NoAlias: store float %1, float* %arrayidx, align 4 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: NoAlias: store float %2, float* %arrayidx.i2, align 4, !noalias !3 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: NoAlias: store float %2, float* %arrayidx.i2, align 4, !noalias !3 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: store float %3, float* %arrayidx.i3, align 4, !noalias !0 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: NoAlias: store float %3, float* %arrayidx.i3, align 4, !noalias !0 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: store float %3, float* %arrayidx.i3, align 4, !noalias !0 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: NoAlias: store float %4, float* %arrayidx.i4, align 4, !noalias !3 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: NoAlias: store float %4, float* %arrayidx.i4, align 4, !noalias !3 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: store float %4, float* %arrayidx.i4, align 4, !noalias !3 <-> store float %2, float* %arrayidx.i2, align 4, !noalias !3 +; CHECK: NoAlias: store float %4, float* %arrayidx.i4, align 4, !noalias !3 <-> store float %3, float* %arrayidx.i3, align 4, !noalias !0 + Index: test/Analysis/ScopedNoAliasAA/basic.ll =================================================================== --- /dev/null +++ test/Analysis/ScopedNoAliasAA/basic.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -basicaa -scoped-noalias -aa-eval -evaluate-aa-metadata -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo1(float* nocapture %a, float* nocapture readonly %c) #0 { +entry: +; CHECK-LABEL: Function: foo1 + %0 = load float* %c, align 4, !alias.scope !0 + %arrayidx.i = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx.i, align 4, !noalias !0 + %1 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %1, float* %arrayidx, align 4 + ret void + +; CHECK: NoAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %1, float* %arrayidx, align 4 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: store float %1, float* %arrayidx, align 4 <-> store float %0, float* %arrayidx.i, align 4, !noalias !0 +} + +attributes #0 = { nounwind uwtable } + +!0 = metadata !{metadata !0} + Index: test/Analysis/ScopedNoAliasAA/basic2.ll =================================================================== --- /dev/null +++ test/Analysis/ScopedNoAliasAA/basic2.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -basicaa -scoped-noalias -aa-eval -evaluate-aa-metadata -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: +; CHECK-LABEL: Function: foo2 + %0 = load float* %c, align 4, !alias.scope !0 + %arrayidx.i = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx.i, align 4, !alias.scope !2, !noalias !1 + %arrayidx1.i = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1.i, align 4, !alias.scope !1, !noalias !2 + %1 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %1, float* %arrayidx, align 4 + ret void + +; CHECK: NoAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %0, float* %arrayidx.i, align 4, !alias.scope !2, !noalias !1 +; CHECK: NoAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %0, float* %arrayidx1.i, align 4, !alias.scope !1, !noalias !2 +; CHECK: MayAlias: %0 = load float* %c, align 4, !alias.scope !0 <-> store float %1, float* %arrayidx, align 4 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %0, float* %arrayidx.i, align 4, !alias.scope !2, !noalias !1 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %0, float* %arrayidx1.i, align 4, !alias.scope !1, !noalias !2 +; CHECK: MayAlias: %1 = load float* %c, align 4 <-> store float %1, float* %arrayidx, align 4 +; CHECK: NoAlias: store float %0, float* %arrayidx1.i, align 4, !alias.scope !1, !noalias !2 <-> store float %0, float* %arrayidx.i, align 4, !alias.scope !2, !noalias !1 +; CHECK: NoAlias: store float %1, float* %arrayidx, align 4 <-> store float %0, float* %arrayidx.i, align 4, !alias.scope !2, !noalias !1 +; CHECK: MayAlias: store float %1, float* %arrayidx, align 4 <-> store float %0, float* %arrayidx1.i, align 4, !alias.scope !1, !noalias !2 +} + +attributes #0 = { nounwind uwtable } + +!0 = metadata !{metadata !1, metadata !2} +!1 = metadata !{metadata !1} +!2 = metadata !{metadata !2} + Index: test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll =================================================================== --- test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll +++ test/Analysis/TypeBasedAliasAnalysis/placement-tbaa.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-tbaa -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-aa-metadata -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s ; Generated with "clang -cc1 -disable-llvm-optzns -O1 -emit-llvm" ; #include Index: test/Analysis/TypeBasedAliasAnalysis/tbaa-path.ll =================================================================== --- test/Analysis/TypeBasedAliasAnalysis/tbaa-path.ll +++ test/Analysis/TypeBasedAliasAnalysis/tbaa-path.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-tbaa -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s +; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-aa-metadata -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s ; RUN: opt < %s -tbaa -basicaa -gvn -S | FileCheck %s --check-prefix=OPT ; Generated from clang/test/CodeGen/tbaa.cpp with "-O1 -struct-path-tbaa -disable-llvm-optzns". Index: test/Transforms/GVN/noalias.ll =================================================================== --- /dev/null +++ test/Transforms/GVN/noalias.ll @@ -0,0 +1,43 @@ +; RUN: opt -scoped-noalias -basicaa -gvn -S < %s | FileCheck %s + +define i32 @test1(i32* %p, i32* %q) { +; CHECK-LABEL: @test1(i32* %p, i32* %q) +; CHECK: load i32* %p +; CHECK-NOT: noalias +; CHECK: %c = add i32 %a, %a + %a = load i32* %p, !noalias !0 + %b = load i32* %p + %c = add i32 %a, %b + ret i32 %c +} + +define i32 @test2(i32* %p, i32* %q) { +; CHECK-LABEL: @test2(i32* %p, i32* %q) +; CHECK: load i32* %p, !alias.scope !0 +; CHECK: %c = add i32 %a, %a + %a = load i32* %p, !alias.scope !0 + %b = load i32* %p, !alias.scope !0 + %c = add i32 %a, %b + ret i32 %c +} + +; FIXME: In this case we can do better than intersecting the scopes, and can +; concatenate them instead. Both loads are in the same basic block, the first +; makes the second safe to speculatively execute, and there are no calls that may +; throw in between. +define i32 @test3(i32* %p, i32* %q) { +; CHECK-LABEL: @test3(i32* %p, i32* %q) +; CHECK: load i32* %p, !alias.scope !1 +; CHECK: %c = add i32 %a, %a + %a = load i32* %p, !alias.scope !1 + %b = load i32* %p, !alias.scope !2 + %c = add i32 %a, %b + ret i32 %c +} + +declare i32 @foo(i32*) readonly + +!0 = metadata !{metadata !0} +!1 = metadata !{metadata !1} +!2 = metadata !{metadata !0, metadata !1} + Index: test/Transforms/Inline/noalias.ll =================================================================== --- /dev/null +++ test/Transforms/Inline/noalias.ll @@ -0,0 +1,74 @@ +; RUN: opt -inline -S < %s | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @hello(float* noalias nocapture %a, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { +entry: + tail call void @hello(float* %a, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !alias.scope !0 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4, !noalias !0 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1, align 4 + ret void +} + +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + tail call void @hello2(float* %a, float* %b, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !alias.scope !2 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !5, !noalias !6 +; CHECK: %arrayidx1.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %0, float* %arrayidx1.i, align 4, !alias.scope !6, !noalias !5 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +attributes #0 = { nounwind uwtable } + +; CHECK: !0 = metadata !{metadata !1} +; CHECK: !1 = metadata !{metadata !1, metadata !"hello: %a"} +; CHECK: !2 = metadata !{metadata !3, metadata !4} +; CHECK: !3 = metadata !{metadata !3, metadata !"hello2: %a"} +; CHECK: !4 = metadata !{metadata !4, metadata !"hello2: %b"} +; CHECK: !5 = metadata !{metadata !4} +; CHECK: !6 = metadata !{metadata !3} + Index: test/Transforms/Inline/noalias2.ll =================================================================== --- /dev/null +++ test/Transforms/Inline/noalias2.ll @@ -0,0 +1,93 @@ +; RUN: opt -inline -S < %s | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define void @hello(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 5 + store float %0, float* %arrayidx, align 4 + ret void +} + +define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +entry: + tail call void @hello(float* %a, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !alias.scope !0, !noalias !2 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !2, !noalias !0 +; CHECK: %1 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 { +entry: + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 6 + store float %0, float* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds float* %b, i64 8 + store float %0, float* %arrayidx1, align 4 + ret void +} + +; Check that when hello() is inlined into foo(), and then foo() is inlined into +; foo2(), the noalias scopes are properly concatenated. +define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +entry: + tail call void @foo(float* %a, float* %c) + tail call void @hello2(float* %a, float* %b, float* %c) + %0 = load float* %c, align 4 + %arrayidx = getelementptr inbounds float* %a, i64 7 + store float %0, float* %arrayidx, align 4 + ret void +} + +; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 { +; CHECK: entry: +; CHECK: %0 = load float* %c, align 4, !alias.scope !4, !noalias !7 +; CHECK: %arrayidx.i.i = getelementptr inbounds float* %a, i64 5 +; CHECK: store float %0, float* %arrayidx.i.i, align 4, !alias.scope !7, !noalias !4 +; CHECK: %1 = load float* %c, align 4, !alias.scope !10, !noalias !11 +; CHECK: %arrayidx.i = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %1, float* %arrayidx.i, align 4, !alias.scope !11, !noalias !10 +; CHECK: %2 = load float* %c, align 4, !alias.scope !12 +; CHECK: %arrayidx.i1 = getelementptr inbounds float* %a, i64 6 +; CHECK: store float %2, float* %arrayidx.i1, align 4, !alias.scope !15, !noalias !16 +; CHECK: %arrayidx1.i = getelementptr inbounds float* %b, i64 8 +; CHECK: store float %2, float* %arrayidx1.i, align 4, !alias.scope !16, !noalias !15 +; CHECK: %3 = load float* %c, align 4 +; CHECK: %arrayidx = getelementptr inbounds float* %a, i64 7 +; CHECK: store float %3, float* %arrayidx, align 4 +; CHECK: ret void +; CHECK: } + +; CHECK: !0 = metadata !{metadata !1} +; CHECK: !1 = metadata !{metadata !1, metadata !"hello: %a"} +; CHECK: !2 = metadata !{metadata !3} +; CHECK: !3 = metadata !{metadata !3, metadata !"hello: %c"} +; CHECK: !4 = metadata !{metadata !5, metadata !6} +; CHECK: !5 = metadata !{metadata !5, metadata !"hello: %a"} +; CHECK: !6 = metadata !{metadata !6, metadata !"foo: %a"} +; CHECK: !7 = metadata !{metadata !8, metadata !9} +; CHECK: !8 = metadata !{metadata !8, metadata !"hello: %c"} +; CHECK: !9 = metadata !{metadata !9, metadata !"foo: %c"} +; CHECK: !10 = metadata !{metadata !6} +; CHECK: !11 = metadata !{metadata !9} +; CHECK: !12 = metadata !{metadata !13, metadata !14} +; CHECK: !13 = metadata !{metadata !13, metadata !"hello2: %a"} +; CHECK: !14 = metadata !{metadata !14, metadata !"hello2: %b"} +; CHECK: !15 = metadata !{metadata !14} +; CHECK: !16 = metadata !{metadata !13} + +attributes #0 = { nounwind uwtable } + Index: unittests/Analysis/MixedTBAATest.cpp =================================================================== --- unittests/Analysis/MixedTBAATest.cpp +++ unittests/Analysis/MixedTBAATest.cpp @@ -65,7 +65,7 @@ // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA. // The order of the metadata (path-aware vs non-path-aware) is important, // because the AA eval pass only runs one test per store-pair. - const char* args[] = { "MixedTBAATest", "-evaluate-tbaa" }; + const char* args[] = { "MixedTBAATest", "-evaluate-aa-metadata" }; cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args); PM.add(createTypeBasedAliasAnalysisPass()); PM.add(createAAEvalPass());