summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2014-07-18 15:51:28 +0000
committerHal Finkel <hfinkel@anl.gov>2014-07-18 15:51:28 +0000
commitb0407ba0716d940d035f5da73f6d3bfbaffecb44 (patch)
tree0fb08700ec2601986a9f5195a9d57fb6e0b48444 /llvm/include
parent9cf7ac75893c9f83099ce59dd4fd5d1ba7ead25a (diff)
downloadbcm5719-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.h1
-rw-r--r--llvm/include/llvm/Bitcode/LLVMBitCodes.h3
-rw-r--r--llvm/include/llvm/IR/Argument.h8
-rw-r--r--llvm/include/llvm/IR/Attributes.h26
-rw-r--r--llvm/include/llvm/IR/CallSite.h19
-rw-r--r--llvm/include/llvm/IR/Function.h6
-rw-r--r--llvm/include/llvm/IR/Instructions.h12
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 {
OpenPOWER on IntegriCloud