diff --git a/llvm/include/llvm/IR/TBAA.h b/llvm/include/llvm/IR/TBAA.h --- a/llvm/include/llvm/IR/TBAA.h +++ b/llvm/include/llvm/IR/TBAA.h @@ -14,6 +14,7 @@ #ifndef LLVM_IR_TBAA_H #define LLVM_IR_TBAA_H +#include "llvm/IR/Constants.h" #include "llvm/IR/Metadata.h" #include @@ -35,25 +36,40 @@ /// in its operands. template class TBAANodeImpl { +protected: MDNodeTy *Node = nullptr; public: TBAANodeImpl() = default; explicit TBAANodeImpl(MDNodeTy *N) : Node(N) {} - /// getNode - Get the MDNode for this TBAANode. + /// Get the MDNode for this TBAANode. MDNodeTy *getNode() const { return Node; } - /// isNewFormat - Return true iff the wrapped type node is in the new - /// size-aware format. + /// Return true iff the wrapped type node is in the new size-aware format. bool isNewFormat() const { return isNewFormatTypeNode(Node); } - /// getParent - Get this TBAANode's Alias tree parent. + /// Return true iff the node is the root of a TBAA type tree. + bool isRoot() const { return Node && Node->getNumOperands() < 2; } + + /// Return true iff the node is a scalar type node. + bool isScalar() const { + if (isNewFormat()) + return Node->getNumOperands() == 3; + if (Node->getNumOperands() < 3) + return true; + if (Node->getNumOperands() == 3) { + return mdconst::extract(Node->getOperand(2))->isZero(); + } + return false; + } + + /// Get this TBAANode's Alias tree parent. TBAANodeImpl getParent() const { if (isNewFormat()) return TBAANodeImpl(cast(Node->getOperand(0))); - if (Node->getNumOperands() < 2) + if (isRoot()) return TBAANodeImpl(); MDNodeTy *P = dyn_cast_or_null(Node->getOperand(1)); if (!P) @@ -62,16 +78,20 @@ return TBAANodeImpl(P); } - /// Test if this TBAANode represents a type for objects which are - /// not modified (by any means) in the context where this - /// AliasAnalysis is relevant. - bool isTypeImmutable() const { - if (Node->getNumOperands() < 3) - return false; - ConstantInt *CI = mdconst::dyn_extract(Node->getOperand(2)); - if (!CI) - return false; - return CI->getValue()[0]; + /// Return a string identifying the name of those node. + StringRef getId() const { + if (Node->getNumOperands() == 0) + return StringRef(); + + return cast(Node->getOperand(isNewFormat() ? 2 : 0))->getString(); + } + + /// Return the size of this node, which is only present for new-format TBAA + /// metadata. + uint64_t getSize() const { + if (!isNewFormat()) + return UINT64_MAX; + return mdconst::extract(Node->getOperand(1))->getZExtValue(); } }; @@ -82,9 +102,8 @@ using MutableTBAANode = TBAANodeImpl; /// @} -/// 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. +/// This is a simple wrapper around a MDNode that represents the access tag of +/// TBAA (the metadata node referred to by !tbaa metadata on instructions). template class TBAAStructTagNodeImpl { /// This node should be created with createTBAAAccessTag(). @@ -96,8 +115,7 @@ /// Get the MDNode for this TBAAStructTagNode. MDNodeTy *getNode() const { return Node; } - /// isNewFormat - Return true iff the wrapped access tag is in the new - /// size-aware format. + /// Return true iff the wrapped access tag is in the new size-aware format. bool isNewFormat() const { if (Node->getNumOperands() < 4) return false; @@ -107,27 +125,34 @@ return true; } + /// Get the node that represents the base struct type of the node this access + /// tag points to. MDNodeTy *getBaseType() const { return dyn_cast_or_null(Node->getOperand(0)); } + /// Get the access type of this access tag. + /// For old-format TBAA metadata, this access tag must be a scalar type. MDNodeTy *getAccessType() const { return dyn_cast_or_null(Node->getOperand(1)); } + /// Get the offset within the base struct type that this access tag points to. uint64_t getOffset() const { return mdconst::extract(Node->getOperand(2))->getZExtValue(); } + /// Get the size accessed by this access tag. This is only meaningful for + /// new-format access tags. uint64_t getSize() const { if (!isNewFormat()) return UINT64_MAX; return mdconst::extract(Node->getOperand(3))->getZExtValue(); } - /// Test if this TBAAStructTagNode represents a type for objects - /// which are not modified (by any means) in the context where this - /// AliasAnalysis is relevant. + /// Test if this access tag represents a type for objects which are not + /// modified (by any means) in the context where this AliasAnalysis is + /// relevant. bool isTypeImmutable() const { unsigned OpNo = isNewFormat() ? 4 : 3; if (Node->getNumOperands() < OpNo + 1) @@ -140,45 +165,35 @@ }; /// \name Specializations of \c TBAAStructTagNodeImpl for const and non const -/// qualified \c MDNods. +/// qualified \c MDNodes. /// @{ using TBAAStructTagNode = TBAAStructTagNodeImpl; using MutableTBAAStructTagNode = TBAAStructTagNodeImpl; /// @} -/// 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 TBAAStructTypeNode { - /// This node should be created with createTBAATypeNode(). - const MDNode *Node = nullptr; - +/// This is a simple wrapper around an MDNode that represents a struct type in +/// the TBAA type tree. +class TBAAStructTypeNode : public TBAANode { public: TBAAStructTypeNode() = default; - explicit TBAAStructTypeNode(const MDNode *N) : Node(N) {} - - /// Get the MDNode for this TBAAStructTypeNode. - const MDNode *getNode() const { return Node; } - - /// isNewFormat - Return true iff the wrapped type node is in the new - /// size-aware format. - bool isNewFormat() const { return isNewFormatTypeNode(Node); } + explicit TBAAStructTypeNode(const MDNode *N) : TBAANode(N) {} bool operator==(const TBAAStructTypeNode &Other) const { return getNode() == Other.getNode(); } - /// getId - Return type identifier. - Metadata *getId() const { - return Node->getOperand(isNewFormat() ? 2 : 0); + bool operator!=(const TBAAStructTypeNode &Other) const { + return getNode() != Other.getNode(); } + /// Get the number of fields for this struct type. unsigned getNumFields() const { unsigned FirstFieldOpNo = isNewFormat() ? 3 : 1; unsigned NumOpsPerField = isNewFormat() ? 3 : 2; return (getNode()->getNumOperands() - FirstFieldOpNo) / NumOpsPerField; } + /// Get the type of the appropriate field for this struct type node. TBAAStructTypeNode getFieldType(unsigned FieldIndex) const { unsigned FirstFieldOpNo = isNewFormat() ? 3 : 1; unsigned NumOpsPerField = isNewFormat() ? 3 : 2; @@ -187,6 +202,18 @@ return TBAAStructTypeNode(TypeNode); } + /// Get the offset within the struct of the appropriate field for this + /// struct type node. + uint64_t getFieldOffset(unsigned FieldIndex) const { + unsigned FirstFieldOpNo = isNewFormat() ? 3 : 1; + unsigned NumOpsPerField = isNewFormat() ? 3 : 2; + unsigned OpIndex = FirstFieldOpNo + FieldIndex * NumOpsPerField + 1; + if (OpIndex >= getNode()->getNumOperands()) + return 0; + return mdconst::extract(getNode()->getOperand(OpIndex)) + ->getZExtValue(); + } + /// Get this TBAAStructTypeNode's field in the type DAG with /// given offset. Update the offset to be relative to the field type. TBAAStructTypeNode getField(uint64_t &Offset) const; @@ -195,7 +222,7 @@ /// Check the first operand of the tbaa tag node, if it is a MDNode, we treat /// it as struct-path aware TBAA format, otherwise, we treat it as scalar TBAA /// format. -static bool isStructPathTBAA(const MDNode *MD) { +inline bool isStructPathTBAA(const MDNode *MD) { // Anonymous TBAA root starts with a MDNode and dragonegg uses it as // a TBAA tag. return isa(MD->getOperand(0)) && MD->getNumOperands() >= 3; diff --git a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp --- a/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -210,8 +210,8 @@ // If this is an "immutable" type, we can assume the pointer is pointing // to constant memory. - if ((!isStructPathTBAA(M) && TBAANode(M).isTypeImmutable()) || - (isStructPathTBAA(M) && TBAAStructTagNode(M).isTypeImmutable())) + assert(isStructPathTBAA(M) && "!tbaa must be a struct-path TBAA"); + if (TBAAStructTagNode(M).isTypeImmutable()) return true; return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal); @@ -226,10 +226,11 @@ // If this is an "immutable" type, we can assume the call doesn't write // to memory. - if (const MDNode *M = Call->getMetadata(LLVMContext::MD_tbaa)) - if ((!isStructPathTBAA(M) && TBAANode(M).isTypeImmutable()) || - (isStructPathTBAA(M) && TBAAStructTagNode(M).isTypeImmutable())) + if (const MDNode *M = Call->getMetadata(LLVMContext::MD_tbaa)) { + assert(isStructPathTBAA(M) && "access tags should be struct-path by now"); + if (TBAAStructTagNode(M).isTypeImmutable()) Min = FMRB_OnlyReadsMemory; + } return FunctionModRefBehavior(AAResultBase::getModRefBehavior(Call) & Min); } @@ -281,9 +282,8 @@ // For struct-path aware TBAA, we use the access type of the tag. TBAAStructTagNode Tag(this); TBAAStructTypeNode AccessType(Tag.getAccessType()); - if(auto *Id = dyn_cast(AccessType.getId())) - if (Id->getString() == "vtable pointer") - return true; + if (AccessType.getId() == "vtable pointer") + return true; return false; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -93,6 +93,7 @@ #include "llvm/IR/ModuleSlotTracker.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Statepoint.h" +#include "llvm/IR/TBAA.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/User.h" @@ -6425,15 +6426,6 @@ return cast(BaseNode->getOperand(LastIdx)); } -static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { - if (!Type || Type->getNumOperands() < 3) - return false; - - // In the new format type nodes shall have a reference to the parent type as - // its first operand. - return isa_and_nonnull(Type->getOperand(0)); -} - bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { CheckTBAA(isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || @@ -6443,14 +6435,14 @@ bool IsStructPathTBAA = isa(MD->getOperand(0)) && MD->getNumOperands() >= 3; - CheckTBAA(IsStructPathTBAA, - "Old-style TBAA is no longer allowed, use struct-path TBAA instead", - &I); + CheckTBAA( + IsStructPathTBAA, + "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I); MDNode *BaseNode = dyn_cast_or_null(MD->getOperand(0)); MDNode *AccessType = dyn_cast_or_null(MD->getOperand(1)); - bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); + bool IsNewFormat = AccessType && isNewFormatTypeNode(AccessType); if (IsNewFormat) { CheckTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5,