diff options
-rw-r--r-- | docs/LangRef.html | 12 | ||||
-rw-r--r-- | include/llvm/Attributes.h | 39 | ||||
-rw-r--r-- | lib/Analysis/BasicAliasAnalysis.cpp | 23 | ||||
-rw-r--r-- | test/Analysis/BasicAA/nocapture.ll | 14 |
4 files changed, 66 insertions, 22 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html index 83bd667..95fb8de 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -894,9 +894,15 @@ declare signext i8 @returns_signed_char() parameter. The caller is responsible for ensuring that this is the case. On a function return value, <tt>noalias</tt> additionally indicates that the pointer does not alias any other pointers visible to the - caller. Note that this applies only to pointers that can be used to actually - load/store a value: NULL, unique pointers from malloc(0), and freed pointers - are considered to not alias anything.</dd> + caller. For further details, please see the discussion of the NoAlias + response in + <a href="http://llvm.org/docs/AliasAnalysis.html#MustMayNo">alias + analysis</a>.</dd> + + <dt><tt>nocapture</tt></dt> + <dd>This indicates that the callee does not make any copies of the pointer + that outlive the callee itself. This is not a valid attribute for return + values.</dd> <dt><tt>nest</tt></dt> <dd>This indicates that the pointer parameter can be excised using the diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index 57f4e17..ab09378 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -15,6 +15,7 @@ #ifndef LLVM_ATTRIBUTES_H #define LLVM_ATTRIBUTES_H +#include "llvm/Support/MathExtras.h" #include <cassert> #include <string> @@ -23,7 +24,7 @@ class Type; /// Attributes - A bitset of attributes. typedef unsigned Attributes; - + namespace Attribute { /// Function parameters and results can have attributes to indicate how they @@ -44,16 +45,18 @@ const Attributes ByVal = 1<<7; ///< Pass structure by value const Attributes Nest = 1<<8; ///< Nested function static chain const Attributes ReadNone = 1<<9; ///< Function does not access memory const Attributes ReadOnly = 1<<10; ///< Function only reads from memory -const Attributes NoInline = 1<<11; // inline=never -const Attributes AlwaysInline = 1<<12; // inline=always -const Attributes OptimizeForSize = 1<<13; // opt_size -const Attributes StackProtect = 1<<14; // Stack protection. -const Attributes StackProtectReq = 1<<15; // Stack protection required. -const Attributes Alignment = 0xffff<<16; ///< Alignment of parameter (16 bits) - // 0 = unknown, else in clear (not log) - +const Attributes NoInline = 1<<11; ///< inline=never +const Attributes AlwaysInline = 1<<12; ///< inline=always +const Attributes OptimizeForSize = 1<<13; ///< opt_size +const Attributes StackProtect = 1<<14; ///< Stack protection. +const Attributes StackProtectReq = 1<<15; ///< Stack protection required. +const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits) + // stored as log2 of alignment with +1 bias + // 0 means unaligned different from align 1 +const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer + /// @brief Attributes that only apply to function parameters. -const Attributes ParameterOnly = ByVal | Nest | StructRet; +const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; /// @brief Attributes that only apply to function. const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | @@ -64,7 +67,7 @@ const Attributes VarArgsIncompatible = StructRet; /// @brief Attributes that are mutually incompatible. const Attributes MutuallyIncompatible[4] = { - ByVal | InReg | Nest | StructRet, + ByVal | InReg | Nest | StructRet, ZExt | SExt, ReadNone | ReadOnly, NoInline | AlwaysInline @@ -76,7 +79,13 @@ Attributes typeIncompatible(const Type *Ty); /// This turns an int alignment (a power of 2, normally) into the /// form used internally in Attributes. inline Attributes constructAlignmentFromInt(unsigned i) { - return (i << 16); + // Default alignment, allow the target to define how to align it. + if (i == 0) + return 0; + + assert(isPowerOf2_32(i) && "Alignment must be a power of two."); + assert(i <= 0x40000000 && "Alignment too large."); + return (Log2_32(i)+1) << 16; } /// The set of Attributes set in Attributes is converted to a @@ -175,7 +184,11 @@ public: /// getParamAlignment - Return the alignment for the specified function /// parameter. unsigned getParamAlignment(unsigned Idx) const { - return (getAttributes(Idx) & Attribute::Alignment) >> 16; + Attributes Align = getAttributes(Idx) & Attribute::Alignment; + if (Align == 0) + return 0; + + return 1ull << ((Align >> 16) - 1); } /// hasAttrSomewhere - Return true if the specified attribute is set for at diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 3270f35..57d3209 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -63,12 +63,23 @@ static bool AddressMightEscape(const Value *V) { // callees could modify it. break; // next use case Instruction::Call: - // If the call is to a few known safe intrinsics, we know that it does - // not escape. - // TODO: Eventually just check the 'nocapture' attribute. - if (!isa<MemIntrinsic>(I)) - return true; - break; // next use + // If the argument to the call has the nocapture attribute, then the call + // may store or load to the pointer, but it cannot escape. + if (cast<CallInst>(I)->paramHasAttr(UI.getOperandNo(), + Attribute::NoCapture)) + continue; + + // FIXME: MemIntrinsics should have their operands marked nocapture! + if (isa<MemIntrinsic>(I)) + continue; // next use + return true; + case Instruction::Invoke: + // If the argument to the call has the nocapture attribute, then the call + // may store or load to the pointer, but it cannot escape. + if (cast<InvokeInst>(I)->paramHasAttr(UI.getOperandNo()-2, + Attribute::NoCapture)) + continue; + return true; default: return true; } diff --git a/test/Analysis/BasicAA/nocapture.ll b/test/Analysis/BasicAA/nocapture.ll new file mode 100644 index 0000000..0ca444c --- /dev/null +++ b/test/Analysis/BasicAA/nocapture.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -basicaa -gvn -instcombine | llvm-dis | grep {ret i32 0} + +declare i32* @test(i32* nocapture) + +define i32 @test2() { + %P = alloca i32 + %Q = call i32* @test(i32* %P) + %a = load i32* %P + store i32 4, i32* %Q ;; cannot clobber P since it is nocapture. + %b = load i32* %P + %c = sub i32 %a, %b + ret i32 %c +} + |