diff options
author | Hal Finkel <hfinkel@anl.gov> | 2014-07-18 15:51:28 +0000 |
---|---|---|
committer | Hal Finkel <hfinkel@anl.gov> | 2014-07-18 15:51:28 +0000 |
commit | b0407ba0716d940d035f5da73f6d3bfbaffecb44 (patch) | |
tree | 0fb08700ec2601986a9f5195a9d57fb6e0b48444 /llvm/include | |
parent | 9cf7ac75893c9f83099ce59dd4fd5d1ba7ead25a (diff) | |
download | bcm5719-llvm-b0407ba0716d940d035f5da73f6d3bfbaffecb44.tar.gz bcm5719-llvm-b0407ba0716d940d035f5da73f6d3bfbaffecb44.zip |
Add a dereferenceable attribute
This attribute indicates that the parameter or return pointer is
dereferenceable. Practically speaking, loads from such a pointer within the
associated byte range are safe to speculatively execute. Such pointer
parameters are common in source languages (C++ references, for example).
llvm-svn: 213385
Diffstat (limited to 'llvm/include')
-rw-r--r-- | llvm/include/llvm-c/Core.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/Bitcode/LLVMBitCodes.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Argument.h | 8 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Attributes.h | 26 | ||||
-rw-r--r-- | llvm/include/llvm/IR/CallSite.h | 19 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Function.h | 6 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Instructions.h | 12 |
7 files changed, 70 insertions, 5 deletions
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 8693a3020ab..fdff77bc5e5 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -168,6 +168,7 @@ typedef enum { LLVMInAllocaAttribute = 1ULL << 36, LLVMNonNullAttribute = 1ULL << 37, LLVMJumpTableAttribute = 1ULL << 38, + LLVMDereferenceableAttribute = 1ULL << 39, */ } LLVMAttribute; diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 75b26a94c9b..ee2efa2257b 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -374,7 +374,8 @@ namespace bitc { ATTR_KIND_OPTIMIZE_NONE = 37, ATTR_KIND_IN_ALLOCA = 38, ATTR_KIND_NON_NULL = 39, - ATTR_KIND_JUMP_TABLE = 40 + ATTR_KIND_JUMP_TABLE = 40, + ATTR_KIND_DEREFERENCEABLE = 41 }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Argument.h b/llvm/include/llvm/IR/Argument.h index 3a63e1a1eaa..7c398a5e553 100644 --- a/llvm/include/llvm/IR/Argument.h +++ b/llvm/include/llvm/IR/Argument.h @@ -56,9 +56,15 @@ public: unsigned getArgNo() const; /// \brief Return true if this argument has the nonnull attribute on it in - /// its containing function. + /// its containing function. Also returns true if at least one byte is known + /// to be dereferenceable and the pointer is in addrspace(0). bool hasNonNullAttr() const; + /// \brief If this argument has the dereferenceable attribute on it in its + /// containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableBytes() const; + /// \brief Return true if this argument has the byval attribute on it in its /// containing function. bool hasByValAttr() const; diff --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h index 9cdadb3c805..5ff48d68891 100644 --- a/llvm/include/llvm/IR/Attributes.h +++ b/llvm/include/llvm/IR/Attributes.h @@ -88,6 +88,7 @@ public: NonLazyBind, ///< Function is called early and/or ///< often, so lazy binding isn't worthwhile NonNull, ///< Pointer is known to be not null + Dereferenceable, ///< Pointer is known to be dereferenceable NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack @@ -133,6 +134,8 @@ public: /// alignment set. static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); + static Attribute getWithDereferenceableBytes(LLVMContext &Context, + uint64_t Bytes); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -178,6 +181,10 @@ public: /// alignment value. unsigned getStackAlignment() const; + /// \brief Returns the number of dereferenceable bytes from the + /// dereferenceable attribute (or zero if unknown). + uint64_t getDereferenceableBytes() const; + /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -316,6 +323,9 @@ public: /// \brief Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; + /// \brief Get the number of dereferenceable bytes (or zero if unknown). + uint64_t getDereferenceableBytes(unsigned Index) const; + /// \brief Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; @@ -395,13 +405,15 @@ class AttrBuilder { std::map<std::string, std::string> TargetDepAttrs; uint64_t Alignment; uint64_t StackAlignment; + uint64_t DerefBytes; public: - AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0) {} + AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} explicit AttrBuilder(uint64_t Val) - : Attrs(0), Alignment(0), StackAlignment(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { addRawValue(Val); } - AttrBuilder(const Attribute &A) : Attrs(0), Alignment(0), StackAlignment(0) { + AttrBuilder(const Attribute &A) + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { addAttribute(A); } AttrBuilder(AttributeSet AS, unsigned Idx); @@ -455,6 +467,10 @@ public: /// \brief Retrieve the stack alignment attribute, if it exists. uint64_t getStackAlignment() const { return StackAlignment; } + /// \brief Retrieve the number of dereferenceable bytes, if the dereferenceable + /// attribute exists (zero is returned otherwise). + uint64_t getDereferenceableBytes() const { return DerefBytes; } + /// \brief This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); @@ -463,6 +479,10 @@ public: /// the form used internally in Attribute. AttrBuilder &addStackAlignmentAttr(unsigned Align); + /// \brief This turns the number of dereferenceable bytes into the form used + /// internally in Attribute. + AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + /// \brief Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } diff --git a/llvm/include/llvm/IR/CallSite.h b/llvm/include/llvm/IR/CallSite.h index deea4151ddd..df082577a0e 100644 --- a/llvm/include/llvm/IR/CallSite.h +++ b/llvm/include/llvm/IR/CallSite.h @@ -217,6 +217,12 @@ public: CALLSITE_DELEGATE_GETTER(getParamAlignment(i)); } + /// @brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(uint16_t i) const { + CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i)); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -302,6 +308,19 @@ public: paramHasAttr(ArgNo + 1, Attribute::ReadNone); } + /// @brief Return true if the return value is known to be not null. + /// This may be because it has the nonnull attribute, or because at least + /// one byte is dereferenceable and the pointer is in addrspace(0). + bool isReturnNonNull() const { + if (paramHasAttr(0, Attribute::NonNull)) + return true; + else if (getDereferenceableBytes(0) > 0 && + getType()->getPointerAddressSpace() == 0) + return true; + + return false; + } + /// hasArgument - Returns true if this CallSite passes the given Value* as an /// argument to the called function. bool hasArgument(const Value *Arg) const { diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 22444bd3000..ad4b1395f0c 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -233,6 +233,12 @@ public: return AttributeSets.getParamAlignment(i); } + /// @brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeSets.getDereferenceableBytes(i); + } + /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index a590f5ad7b2..308467f7aa1 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -1376,6 +1376,12 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeList.getDereferenceableBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -3051,6 +3057,12 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeList.getDereferenceableBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { |