Introducing nocapture, a parameter attribute for pointers to indicate that the
authorNick Lewycky <nicholas@mxc.ca>
Mon, 15 Dec 2008 01:34:58 +0000 (01:34 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Mon, 15 Dec 2008 01:34:58 +0000 (01:34 +0000)
callee will not introduce any new aliases of that pointer.

The attributes had all bits allocated already, so I decided to collapse
alignment. Alignment was previously stored as a 16-bit integer from bits 16 to
32 of the attribute, but it was required to be a power of 2. Now it's stored in
log2 encoded form in five bits from 16 to 21. That gives us 11 more bits of
space.

You may have already noticed that you only need four bits to encode a 16-bit
power of two, so why five bits? Because the AsmParser accepted 32-bit
alignments, even though we couldn't store them (they were silently discarded).
Now we can store them in memory, but not in the bitcode.

The bitcode format was already storing these as 64-bit VBR integers. So, the
bitcode format stays the same, keeping the alignment values stored as 16 bit
raw values. There's some hideous code in the reader and writer that deals with
this, waiting to be ripped out the moment we run out of bits again and have to
replace the parameter attributes table encoding.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61019 91177308-0d34-0410-b5e6-96231b3b80d8

docs/AliasAnalysis.html
docs/LangRef.html
include/llvm/Attributes.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/llvmAsmParser.y
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/VMCore/Attributes.cpp

index 1569fb8e688ca71df0ff5968d4761ea7b3dc0864..97a813344d894dea99fa9489ee2a02136ee82f96 100644 (file)
@@ -192,11 +192,11 @@ and returns MustAlias, MayAlias, or NoAlias as appropriate.
 
 <div class="doc_text">
 <p>The NoAlias response is used when the two pointers refer to distinct objects,
-even regardless of whether the pointers compare equal.  For example, freed
-pointers don't alias any pointers that were allocated afterwards.  As a
-degenerate case, pointers returned by malloc(0) have no bytes for an object,
-and are considered NoAlias even when malloc returns the same pointer.  The same
-rule applies to NULL pointers.</p>
+regardless of whether the pointers compare equal.  For example, freed pointers
+don't alias any pointers that were allocated afterwards.  As a degenerate case,
+pointers returned by malloc(0) have no bytes for an object, and are considered
+NoAlias even when malloc returns the same pointer.  The same rule applies to
+NULL pointers.</p>
 
 <p>The MayAlias response is used whenever the two pointers might refer to the
 same object.  If the two memory objects overlap, but do not start at the same
index 83bd667fac30e2f2356813300b73a9cd47dfaca2..95fb8de319bca7704d55e0d4d916c9fd7f9fbd5c 100644 (file)
@@ -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
index 57f4e17c47fea25ad2615d0f4d7cfeec9d773321..5cb581ae9631eb60e49032217a0f31576134f363 100644 (file)
@@ -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,17 @@ 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.
+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 +66,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 +78,8 @@ 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);
+  assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
+  return Log2_32(i) << 16;
 }
 
 /// The set of Attributes set in Attributes is converted to a
index 20b2b888b1f1f29a3132570c6b569bc3b520efed..b8f497a5e90d22198bf6c5423758e2147a5752e9 100644 (file)
@@ -491,6 +491,7 @@ int LLLexer::LexIdentifier() {
   KEYWORD("nounwind", NOUNWIND);
   KEYWORD("noreturn", NORETURN);
   KEYWORD("noalias", NOALIAS);
+  KEYWORD("nocapture", NOCAPTURE);
   KEYWORD("byval", BYVAL);
   KEYWORD("nest", NEST);
   KEYWORD("readnone", READNONE);
index 8b54251c6589253a20d8350c0321136e7edeefb2..350584f432a1f5855cea3ecb28a1471102ff5be3 100644 (file)
@@ -1136,8 +1136,8 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
 %token <OtherOpVal> EXTRACTVALUE INSERTVALUE
 
 // Function Attributes
-%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
-%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE SSP SSPREQ
+%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS NOCAPTURE BYVAL
+%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE SSP SSPREQ NEST
 
 // Visibility Styles
 %token DEFAULT HIDDEN PROTECTED
@@ -1265,15 +1265,16 @@ OptCallingConv : /*empty*/          { $$ = CallingConv::C; } |
                   CHECK_FOR_ERROR
                  };
 
-Attribute     : ZEROEXT { $$ = Attribute::ZExt;      }
-              | ZEXT    { $$ = Attribute::ZExt;      }
-              | SIGNEXT { $$ = Attribute::SExt;      }
-              | SEXT    { $$ = Attribute::SExt;      }
-              | INREG   { $$ = Attribute::InReg;     }
-              | SRET    { $$ = Attribute::StructRet; }
-              | NOALIAS { $$ = Attribute::NoAlias;   }
-              | BYVAL   { $$ = Attribute::ByVal;     }
-              | NEST    { $$ = Attribute::Nest;      }
+Attribute     : ZEROEXT   { $$ = Attribute::ZExt;      }
+              | ZEXT      { $$ = Attribute::ZExt;      }
+              | SIGNEXT   { $$ = Attribute::SExt;      }
+              | SEXT      { $$ = Attribute::SExt;      }
+              | INREG     { $$ = Attribute::InReg;     }
+              | SRET      { $$ = Attribute::StructRet; }
+              | NOALIAS   { $$ = Attribute::NoAlias;   }
+              | NOCAPTURE { $$ = Attribute::NoCapture; }
+              | BYVAL     { $$ = Attribute::ByVal;     }
+              | NEST      { $$ = Attribute::Nest;      }
               | ALIGN EUINT64VAL { $$ =
                           Attribute::constructAlignmentFromInt($2);    }
               ;
index f06c61de41594bfb1e8cb2142f1c67742f6ea2d9..2d994d4b13d03d71bab25d111a0d0e2bfacec3b5 100644 (file)
@@ -362,6 +362,20 @@ bool BitcodeReader::ParseAttributeBlock() {
       Attributes RetAttribute = Attribute::None;
       Attributes FnAttribute = Attribute::None;
       for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
+        // FIXME: remove in LLVM 3.0
+        // The alignment is stored as a 16-bit raw value from bits 31--16.
+        // We shift the bits above 31 down by 11 bits.
+
+        unsigned Alignment = (Record[i+1] & (0xffffull << 16)) >> 16;
+        if (Alignment && !isPowerOf2_32(Alignment))
+          return Error("Alignment is not a power of two.");
+
+        Attributes ReconstitutedAttr = Record[i+1] & 0xffff;
+        if (Alignment)
+          ReconstitutedAttr |= Attribute::constructAlignmentFromInt(Alignment);
+        ReconstitutedAttr |= (Record[i+1] & (0xffffull << 32)) >> 11;
+        Record[i+1] = ReconstitutedAttr;
+
         if (Record[i] == 0)
           RetAttribute = Record[i+1];
         else if (Record[i] == ~0U)
index 279e447873cab76fc90b4097f95d852e64366816..0555ed90f64279f9f0d5afc61483d02a68c2d55d 100644 (file)
@@ -122,7 +122,16 @@ static void WriteAttributeTable(const ValueEnumerator &VE,
     for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) {
       const AttributeWithIndex &PAWI = A.getSlot(i);
       Record.push_back(PAWI.Index);
-      Record.push_back(PAWI.Attrs);
+
+      // FIXME: remove in LLVM 3.0
+      // Store the alignment in the bitcode as a 16-bit raw value instead of a
+      // 5-bit log2 encoded value. Shift the bits above the alignment up by
+      // 11 bits.
+      uint64_t FauxAttr = PAWI.Attrs & 0xffff;
+      FauxAttr |= (1ull<<16)<<((PAWI.Attrs & Attribute::Alignment) >> 16);
+      FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11;
+
+      Record.push_back(FauxAttr);
     }
     
     Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
index 92acc111be952f21ddcc3b2570c525492ceb7757..0a0d0a842d0dbc36aa39cbe3a301757092511687 100644 (file)
@@ -37,6 +37,8 @@ std::string Attribute::getAsString(Attributes Attrs) {
     Result += "inreg ";
   if (Attrs & Attribute::NoAlias)
     Result += "noalias ";
+  if (Attrs & Attribute::NoCapture)
+    Result += "nocapture ";
   if (Attrs & Attribute::StructRet)
     Result += "sret ";  
   if (Attrs & Attribute::ByVal)
@@ -59,10 +61,11 @@ std::string Attribute::getAsString(Attributes Attrs) {
     Result += "sspreq ";
   if (Attrs & Attribute::Alignment) {
     Result += "align ";
-    Result += utostr((Attrs & Attribute::Alignment) >> 16);
+    Result += utostr(1ull << ((Attrs & Attribute::Alignment)>>16));
     Result += " ";
   }
   // Trim the trailing space.
+  assert(!Result.empty() && "Unknown attribute!");
   Result.erase(Result.end()-1);
   return Result;
 }
@@ -76,7 +79,7 @@ Attributes Attribute::typeIncompatible(const Type *Ty) {
   
   if (!isa<PointerType>(Ty))
     // Attributes that only apply to pointers.
-    Incompatible |= ByVal | Nest | NoAlias | StructRet;
+    Incompatible |= ByVal | Nest | NoAlias | StructRet | NoCapture;
   
   return Incompatible;
 }