diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
tree | 4def12e759965de927d963ac65840d663ef9d1ea /include/llvm/IR/GlobalValue.h | |
parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) |
Diffstat (limited to 'include/llvm/IR/GlobalValue.h')
-rw-r--r-- | include/llvm/IR/GlobalValue.h | 255 |
1 files changed, 199 insertions, 56 deletions
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index fa6469aa0ade7..09682f7aa349a 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -20,6 +20,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/Support/MD5.h" #include <system_error> namespace llvm { @@ -69,17 +70,18 @@ protected: LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility), - UnnamedAddr(0), DllStorageClass(DefaultStorageClass), - ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) { + UnnamedAddrVal(unsigned(UnnamedAddr::None)), + DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), + IntID((Intrinsic::ID)0U), Parent(nullptr) { setName(Name); } Type *ValueType; - // Note: VC++ treats enums as signed, so an extra bit is required to prevent - // Linkage and Visibility from turning into negative values. - LinkageTypes Linkage : 5; // The linkage of this global + // All bitfields use unsigned as the underlying type so that MSVC will pack + // them. + unsigned Linkage : 4; // The linkage of this global unsigned Visibility : 2; // The visibility style of this global - unsigned UnnamedAddr : 1; // This value's address is not significant + unsigned UnnamedAddrVal : 2; // This value's address is not significant unsigned DllStorageClass : 2; // DLL storage class unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is @@ -88,12 +90,36 @@ protected: private: // Give subclasses access to what otherwise would be wasted padding. - // (19 + 3 + 2 + 1 + 2 + 5) == 32. + // (19 + 4 + 2 + 2 + 2 + 3) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + Value *handleOperandChangeImpl(Value *From, Value *To); + + /// Returns true if the definition of this global may be replaced by a + /// differently optimized variant of the same source level function at link + /// time. + bool mayBeDerefined() const { + switch (getLinkage()) { + case WeakODRLinkage: + case LinkOnceODRLinkage: + case AvailableExternallyLinkage: + return true; + + case WeakAnyLinkage: + case LinkOnceAnyLinkage: + case CommonLinkage: + case ExternalWeakLinkage: + case ExternalLinkage: + case AppendingLinkage: + case InternalLinkage: + case PrivateLinkage: + return isInterposable(); + } + + llvm_unreachable("Fully covered switch above!"); + } protected: /// \brief The intrinsic ID for this subclass (which must be a Function). @@ -128,8 +154,37 @@ public: unsigned getAlignment() const; - bool hasUnnamedAddr() const { return UnnamedAddr; } - void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + enum class UnnamedAddr { + None, + Local, + Global, + }; + + bool hasGlobalUnnamedAddr() const { + return getUnnamedAddr() == UnnamedAddr::Global; + } + + /// Returns true if this value's address is not significant in this module. + /// This attribute is intended to be used only by the code generator and LTO + /// to allow the linker to decide whether the global needs to be in the symbol + /// table. It should probably not be used in optimizations, as the value may + /// have uses outside the module; use hasGlobalUnnamedAddr() instead. + bool hasAtLeastLocalUnnamedAddr() const { + return getUnnamedAddr() != UnnamedAddr::None; + } + + UnnamedAddr getUnnamedAddr() const { + return UnnamedAddr(UnnamedAddrVal); + } + void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); } + + static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { + if (A == UnnamedAddr::None || B == UnnamedAddr::None) + return UnnamedAddr::None; + if (A == UnnamedAddr::Local || B == UnnamedAddr::Local) + return UnnamedAddr::Local; + return UnnamedAddr::Global; + } bool hasComdat() const { return getComdat() != nullptr; } Comdat *getComdat(); @@ -173,14 +228,8 @@ public: } void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } - bool hasSection() const { return !StringRef(getSection()).empty(); } - // It is unfortunate that we have to use "char *" in here since this is - // always non NULL, but: - // * The C API expects a null terminated string, so we cannot use StringRef. - // * The C API expects us to own it, so we cannot use a std:string. - // * For GlobalAliases we can fail to find the section and we have to - // return "", so we cannot use a "const std::string &". - const char *getSection() const; + bool hasSection() const { return !getSection().empty(); } + StringRef getSection() const; /// Global values are always pointers. PointerType *getType() const { return cast<PointerType>(User::getType()); } @@ -233,6 +282,34 @@ public: static bool isCommonLinkage(LinkageTypes Linkage) { return Linkage == CommonLinkage; } + static bool isValidDeclarationLinkage(LinkageTypes Linkage) { + return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage); + } + + /// Whether the definition of this global may be replaced by something + /// non-equivalent at link time. For example, if a function has weak linkage + /// then the code defining it may be replaced by different code. + static bool isInterposableLinkage(LinkageTypes Linkage) { + switch (Linkage) { + case WeakAnyLinkage: + case LinkOnceAnyLinkage: + case CommonLinkage: + case ExternalWeakLinkage: + return true; + + case AvailableExternallyLinkage: + case LinkOnceODRLinkage: + case WeakODRLinkage: + // The above three cannot be overridden but can be de-refined. + + case ExternalLinkage: + case AppendingLinkage: + case InternalLinkage: + case PrivateLinkage: + return false; + } + llvm_unreachable("Fully covered switch above!"); + } /// Whether the definition of this global may be discarded if it is not used /// in its compilation unit. @@ -241,17 +318,9 @@ public: isAvailableExternallyLinkage(Linkage); } - /// Whether the definition of this global may be replaced by something - /// non-equivalent at link time. For example, if a function has weak linkage - /// then the code defining it may be replaced by different code. - static bool mayBeOverridden(LinkageTypes Linkage) { - return Linkage == WeakAnyLinkage || Linkage == LinkOnceAnyLinkage || - Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; - } - /// Whether the definition of this global may be replaced at link time. NB: /// Using this method outside of the code generators is almost always a - /// mistake: when working at the IR level use mayBeOverridden instead as it + /// mistake: when working at the IR level use isInterposable instead as it /// knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || @@ -259,44 +328,87 @@ public: Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; } - bool hasExternalLinkage() const { return isExternalLinkage(Linkage); } + /// Return true if the currently visible definition of this global (if any) is + /// exactly the definition we will see at runtime. + /// + /// Non-exact linkage types inhibits most non-inlining IPO, since a + /// differently optimized variant of the same function can have different + /// observable or undefined behavior than in the variant currently visible. + /// For instance, we could have started with + /// + /// void foo(int *v) { + /// int t = 5 / v[0]; + /// (void) t; + /// } + /// + /// and "refined" it to + /// + /// void foo(int *v) { } + /// + /// However, we cannot infer readnone for `foo`, since that would justify + /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause + /// undefined behavior if the linker replaces the actual call destination with + /// the unoptimized `foo`. + /// + /// Inlining is okay across non-exact linkage types as long as they're not + /// interposable (see \c isInterposable), since in such cases the currently + /// visible variant is *a* correct implementation of the original source + /// function; it just isn't the *only* correct implementation. + bool isDefinitionExact() const { + return !mayBeDerefined(); + } + + /// Return true if this global has an exact defintion. + bool hasExactDefinition() const { + // While this computes exactly the same thing as + // isStrongDefinitionForLinker, the intended uses are different. This + // function is intended to help decide if specific inter-procedural + // transforms are correct, while isStrongDefinitionForLinker's intended use + // is in low level code generation. + return !isDeclaration() && isDefinitionExact(); + } + + /// Return true if this global's definition can be substituted with an + /// *arbitrary* definition at link time. We cannot do any IPO or inlinining + /// across interposable call edges, since the callee can be replaced with + /// something arbitrary at link time. + bool isInterposable() const { return isInterposableLinkage(getLinkage()); } + + bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); } bool hasAvailableExternallyLinkage() const { - return isAvailableExternallyLinkage(Linkage); - } - bool hasLinkOnceLinkage() const { - return isLinkOnceLinkage(Linkage); + return isAvailableExternallyLinkage(getLinkage()); } - bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); } - bool hasWeakLinkage() const { - return isWeakLinkage(Linkage); + bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); } + bool hasLinkOnceODRLinkage() const { + return isLinkOnceODRLinkage(getLinkage()); } - bool hasWeakAnyLinkage() const { - return isWeakAnyLinkage(Linkage); + bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); } + bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); } + bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); } + bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); } + bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); } + bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); } + bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); } + bool hasExternalWeakLinkage() const { + return isExternalWeakLinkage(getLinkage()); } - bool hasWeakODRLinkage() const { - return isWeakODRLinkage(Linkage); + bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); } + bool hasValidDeclarationLinkage() const { + return isValidDeclarationLinkage(getLinkage()); } - bool hasAppendingLinkage() const { return isAppendingLinkage(Linkage); } - bool hasInternalLinkage() const { return isInternalLinkage(Linkage); } - bool hasPrivateLinkage() const { return isPrivateLinkage(Linkage); } - bool hasLocalLinkage() const { return isLocalLinkage(Linkage); } - bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); } - bool hasCommonLinkage() const { return isCommonLinkage(Linkage); } void setLinkage(LinkageTypes LT) { if (isLocalLinkage(LT)) Visibility = DefaultVisibility; Linkage = LT; } - LinkageTypes getLinkage() const { return Linkage; } + LinkageTypes getLinkage() const { return LinkageTypes(Linkage); } bool isDiscardableIfUnused() const { - return isDiscardableIfUnused(Linkage); + return isDiscardableIfUnused(getLinkage()); } - bool mayBeOverridden() const { return mayBeOverridden(Linkage); } - - bool isWeakForLinker() const { return isWeakForLinker(Linkage); } + bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); } /// Copy all additional attributes (those not needed to create a GlobalValue) /// from the GlobalValue Src to this one. @@ -311,11 +423,37 @@ public: return Name; } -/// @name Materialization -/// Materialization is used to construct functions only as they're needed. This -/// is useful to reduce memory usage in LLVM or parsing work done by the -/// BitcodeReader to load the Module. -/// @{ + /// Return the modified name for a global value suitable to be + /// used as the key for a global lookup (e.g. profile or ThinLTO). + /// The value's original name is \c Name and has linkage of type + /// \c Linkage. The value is defined in module \c FileName. + static std::string getGlobalIdentifier(StringRef Name, + GlobalValue::LinkageTypes Linkage, + StringRef FileName); + + /// Return the modified name for this global value suitable to be + /// used as the key for a global lookup (e.g. profile or ThinLTO). + std::string getGlobalIdentifier() const; + + /// Declare a type to represent a global unique identifier for a global value. + /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact + /// unique way to identify a symbol. + using GUID = uint64_t; + + /// Return a 64-bit global unique ID constructed from global value name + /// (i.e. returned by getGlobalIdentifier()). + static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); } + + /// Return a 64-bit global unique ID constructed from global value name + /// (i.e. returned by getGlobalIdentifier()). + GUID getGUID() const { return getGUID(getGlobalIdentifier()); } + + /// @name Materialization + /// Materialization is used to construct functions only as they're needed. + /// This + /// is useful to reduce memory usage in LLVM or parsing work done by the + /// BitcodeReader to load the Module. + /// @{ /// If this function's Module is being lazily streamed in functions from disk /// or some other source, this method can be used to check to see if the @@ -342,6 +480,10 @@ public: /// Returns true if this global's definition will be the one chosen by the /// linker. + /// + /// NB! Ideally this should not be used at the IR level at all. If you're + /// interested in optimization constraints implied by the linker's ability to + /// choose an implementation, prefer using \c hasExactDefinition. bool isStrongDefinitionForLinker() const { return !(isDeclarationForLinker() || isWeakForLinker()); } @@ -365,7 +507,8 @@ public: static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || - V->getValueID() == Value::GlobalAliasVal; + V->getValueID() == Value::GlobalAliasVal || + V->getValueID() == Value::GlobalIFuncVal; } }; |