Add a new keyword 'inbounds' for use with getelementptr. See the
authorDan Gohman <gohman@apple.com>
Mon, 27 Jul 2009 21:53:46 +0000 (21:53 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 27 Jul 2009 21:53:46 +0000 (21:53 +0000)
LangRef.html changes for details.

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

docs/LangRef.html
include/llvm/Bitcode/LLVMBitCodes.h
include/llvm/Operator.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLToken.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/VMCore/AsmWriter.cpp
test/Assembler/flags-plain.ll
test/Assembler/flags.ll

index 1f9f80d6d43468b6d70a8b7294c9bf1bccb62959..adc5d9a143fedec6df73e92ef520ac2eaf12a074 100644 (file)
@@ -2091,6 +2091,7 @@ Classifications</a> </div>
       instruction</a>.</dd>
 
   <dt><b><tt>getelementptr ( CSTPTR, IDX0, IDX1, ... )</tt></b></dt>
+  <dt><b><tt>getelementptr inbounds ( CSTPTR, IDX0, IDX1, ... )</tt></b></dt>
   <dd>Perform the <a href="#i_getelementptr">getelementptr operation</a> on
       constants.  As with the <a href="#i_getelementptr">getelementptr</a>
       instruction, the index list may have zero or more indexes, which are
@@ -3902,6 +3903,7 @@ Instruction</a> </div>
 <h5>Syntax:</h5>
 <pre>
   &lt;result&gt; = getelementptr &lt;pty&gt;* &lt;ptrval&gt;{, &lt;ty&gt; &lt;idx&gt;}*
+  &lt;result&gt; = getelementptr inbounds &lt;pty&gt;* &lt;ptrval&gt;{, &lt;ty&gt; &lt;idx&gt;}*
 </pre>
 
 <h5>Overview:</h5>
@@ -3990,6 +3992,20 @@ entry:
   }
 </pre>
 
+<p>If the <tt>inbounds</tt> keyword is present, the result value of the
+   <tt>getelementptr</tt> is undefined if the base pointer is not pointing
+   into an allocated object, or if any of the addresses formed by successive
+   addition of the offsets implied by the indices to the base address is
+   outside of the allocated object into which the base pointer points.</p>
+
+<p>If the <tt>inbounds</tt> keyword is not present, the offsets are added to
+   the base address with silently-wrapping two's complement arithmetic, and
+   the result value of the <tt>getelementptr</tt> may be outside the object
+   pointed to by the base pointer. The result value may not necessarily be
+   used to access memory though, even if it happens to point into allocated
+   storage. See the <a href="#pointeraliasing">Pointer Aliasing Rules</a>
+   section for more information.</p>
+
 <p>The getelementptr instruction is often confusing.  For some more insight into
    how it works, see <a href="GetElementPtr.html">the getelementptr FAQ</a>.</p>
 
index 3d8c24691473c6813a0f8d4d4cdfc39db661bd87..38f152dcce3eafef1aeb3bd52c26020e41a04d29 100644 (file)
@@ -132,7 +132,8 @@ namespace bitc {
     CST_CODE_CE_SHUFFLEVEC = 16,  // CE_SHUFFLEVEC: [opval, opval, opval]
     CST_CODE_CE_CMP        = 17,  // CE_CMP:        [opty, opval, opval, pred]
     CST_CODE_INLINEASM     = 18,  // INLINEASM:     [sideeffect,asmstr,conststr]
-    CST_CODE_CE_SHUFVEC_EX = 19   // SHUFVEC_EX:    [opty, opval, opval, opval]
+    CST_CODE_CE_SHUFVEC_EX = 19,  // SHUFVEC_EX:    [opty, opval, opval, opval]
+    CST_CODE_CE_INBOUNDS_GEP = 20 // INBOUNDS_GEP:  [n x operands]
   };
 
   /// CastOpcodes - These are values used in the bitcode files to encode which
@@ -229,7 +230,8 @@ namespace bitc {
     // support legacy vicmp/vfcmp instructions.
     FUNC_CODE_INST_CMP2        = 28, // CMP2:       [opty, opval, opval, pred]
     // new select on i1 or [N x i1]
-    FUNC_CODE_INST_VSELECT     = 29  // VSELECT:    [ty,opval,opval,predty,pred]
+    FUNC_CODE_INST_VSELECT     = 29, // VSELECT:    [ty,opval,opval,predty,pred]
+    FUNC_CODE_INST_INBOUNDS_GEP = 30 // INBOUNDS_GEP: [n x operands]
   };
 } // End bitc namespace
 } // End llvm namespace
index 932c2ace8c46729e1c9a4732f78a6c93746fb7f4..c62164bcbcea4bb3af1a033c98a16e4292e594d6 100644 (file)
@@ -181,6 +181,15 @@ public:
 
 class GEPOperator : public Operator {
 public:
+  /// isInBounds - Test whether this is an inbounds GEP, as defined
+  /// by LangRef.html.
+  bool isInBounds() const {
+    return SubclassOptionalData & (1 << 0);
+  }
+  void setIsInBounds(bool B) {
+    SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0);
+  }
+
   inline op_iterator       idx_begin()       { return op_begin()+1; }
   inline const_op_iterator idx_begin() const { return op_begin()+1; }
   inline op_iterator       idx_end()         { return op_end(); }
index e047002c138fda1c88bfb5de6a0b56213dcf02ec..c9b282124353bc9894d673247ba57440bffa0cdc 100644 (file)
@@ -504,6 +504,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(nuw);
   KEYWORD(nsw);
   KEYWORD(exact);
+  KEYWORD(inbounds);
   KEYWORD(align);
   KEYWORD(addrspace);
   KEYWORD(section);
index f9db40915ae07927fef1390eb26e8e43a1324923..adcd79f40a30bf723a1f7c882bb38ae8e295ff97 100644 (file)
@@ -457,7 +457,7 @@ bool LLParser::ParseStandaloneMetadata() {
 /// Aliasee
 ///   ::= TypeAndValue
 ///   ::= 'bitcast' '(' TypeAndValue 'to' Type ')'
-///   ::= 'getelementptr' '(' ... ')'
+///   ::= 'getelementptr' 'inbounds'? '(' ... ')'
 ///
 /// Everything through visibility has already been parsed.
 ///
@@ -2039,7 +2039,11 @@ bool LLParser::ParseValID(ValID &ID) {
   case lltok::kw_select: {
     unsigned Opc = Lex.getUIntVal();
     SmallVector<Constant*, 16> Elts;
+    bool InBounds = false;
     Lex.Lex();
+    if (Opc == Instruction::GetElementPtr)
+      if (EatIfPresent(lltok::kw_inbounds))
+        InBounds = true;
     if (ParseToken(lltok::lparen, "expected '(' in constantexpr") ||
         ParseGlobalValueVector(Elts) ||
         ParseToken(lltok::rparen, "expected ')' in constantexpr"))
@@ -2055,6 +2059,8 @@ bool LLParser::ParseValID(ValID &ID) {
         return Error(ID.Loc, "invalid indices for getelementptr");
       ID.ConstantVal = Context.getConstantExprGetElementPtr(Elts[0],
                                               Elts.data() + 1, Elts.size() - 1);
+      if (InBounds)
+        cast<GEPOperator>(ID.ConstantVal)->setIsInBounds(true);
     } else if (Opc == Instruction::Select) {
       if (Elts.size() != 3)
         return Error(ID.Loc, "expected three operands to select");
@@ -3368,9 +3374,14 @@ bool LLParser::ParseGetResult(Instruction *&Inst, PerFunctionState &PFS) {
 }
 
 /// ParseGetElementPtr
-///   ::= 'getelementptr' TypeAndValue (',' TypeAndValue)*
+///   ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)*
 bool LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
   Value *Ptr, *Val; LocTy Loc, EltLoc;
+  bool InBounds = false;
+
+  if (EatIfPresent(lltok::kw_inbounds))
+    InBounds = true;
+
   if (ParseTypeAndValue(Ptr, Loc, PFS)) return true;
   
   if (!isa<PointerType>(Ptr->getType()))
@@ -3388,6 +3399,8 @@ bool LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) {
                                          Indices.begin(), Indices.end()))
     return Error(Loc, "invalid getelementptr indices");
   Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end());
+  if (InBounds)
+    cast<GEPOperator>(Inst)->setIsInBounds(true);
   return false;
 }
 
index c8cdff6bf618e29d9966af5f8ca62f9969174bc5..75cc1db8ad93acc99fc5a8bf454e8f586640764e 100644 (file)
@@ -54,6 +54,7 @@ namespace lltok {
     kw_nuw,
     kw_nsw,
     kw_exact,
+    kw_inbounds,
     kw_align,
     kw_addrspace,
     kw_section,
index 687cae9ecf6b627457b9a83db400bb4fdf831361..e1cc1a3afba99b33ec663165d315e9a61d66c865 100644 (file)
@@ -997,6 +997,7 @@ bool BitcodeReader::ParseConstants() {
       }
       break;
     }  
+    case bitc::CST_CODE_CE_INBOUNDS_GEP:
     case bitc::CST_CODE_CE_GEP: {  // CE_GEP:        [n x operands]
       if (Record.size() & 1) return Error("Invalid CE_GEP record");
       SmallVector<Constant*, 16> Elts;
@@ -1007,6 +1008,8 @@ bool BitcodeReader::ParseConstants() {
       }
       V = Context.getConstantExprGetElementPtr(Elts[0], &Elts[1], 
                                                Elts.size()-1);
+      if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
+        cast<GEPOperator>(V)->setIsInBounds(true);
       break;
     }
     case bitc::CST_CODE_CE_SELECT:  // CE_SELECT: [opval#, opval#, opval#]
@@ -1556,6 +1559,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
       I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy);
       break;
     }
+    case bitc::FUNC_CODE_INST_INBOUNDS_GEP:
     case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands]
       unsigned OpNum = 0;
       Value *BasePtr;
@@ -1571,6 +1575,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
       }
 
       I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end());
+      if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP)
+        cast<GEPOperator>(I)->setIsInBounds(true);
       break;
     }
       
index b3124204903916c6f2f397f1335ef1c802df5e7c..fd09edec942ea3dc1ffdc1531d084c9d207a2e9e 100644 (file)
@@ -706,6 +706,8 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
         break;
       case Instruction::GetElementPtr:
         Code = bitc::CST_CODE_CE_GEP;
+        if (cast<GEPOperator>(C)->isInBounds())
+          Code = bitc::CST_CODE_CE_INBOUNDS_GEP;
         for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
           Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
           Record.push_back(VE.getValueID(C->getOperand(i)));
@@ -829,6 +831,8 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
 
   case Instruction::GetElementPtr:
     Code = bitc::FUNC_CODE_INST_GEP;
+    if (cast<GEPOperator>(&I)->isInBounds())
+      Code = bitc::FUNC_CODE_INST_INBOUNDS_GEP;
     for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
       PushValueAndType(I.getOperand(i), InstID, Vals, VE);
     break;
index 11d238eba25d5a68f14144362075f8378094f15f..8242d8155b14e1d624672dc8e3230b80593856d2 100644 (file)
@@ -854,6 +854,9 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
   } else if (const SDivOperator *Div = dyn_cast<SDivOperator>(U)) {
     if (Div->isExact())
       Out << " exact";
+  } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
+    if (GEP->isInBounds())
+      Out << " inbounds";
   }
 }
 
index 148d02fc062054c1c4d999109ee8f3cd6cd37ba6..bf3d5d891f5083687b116d657dd123b21df69963 100644 (file)
@@ -21,3 +21,8 @@ define i64 @sdiv_plain_ce() {
 ; CHECK: ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91)
        ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91)
 }
+
+define i64* @gep_plain_ce() {
+; CHECK: ret i64* getelementptr (i64* @addr, i64 171)
+        ret i64* getelementptr (i64* @addr, i64 171)
+}
index 4efb1cdb2388c5de756fe56d640ee0a72dca8e8f..981a4e592cef02cf6c2a23f52676cce31c0fb863 100644 (file)
@@ -104,6 +104,18 @@ define i64 @sdiv_plain(i64 %x, i64 %y) {
        ret i64 %z
 }
 
+define i64* @gep_nw(i64* %p, i64 %x) {
+; CHECK: %z = getelementptr inbounds i64* %p, i64 %x
+       %z = getelementptr inbounds i64* %p, i64 %x
+        ret i64* %z
+}
+
+define i64* @gep_plain(i64* %p, i64 %x) {
+; CHECK: %z = getelementptr i64* %p, i64 %x
+       %z = getelementptr i64* %p, i64 %x
+        ret i64* %z
+}
+
 define i64 @add_both_ce() {
 ; CHECK: ret i64 add nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91)
        ret i64 add nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91)
@@ -123,3 +135,10 @@ define i64 @sdiv_exact_ce() {
 ; CHECK: ret i64 sdiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
        ret i64 sdiv exact (i64 ptrtoint (i64* @addr to i64), i64 91)
 }
+
+define i64* @gep_nw_ce() {
+; CHECK: ret i64* getelementptr inbounds (i64* @addr, i64 171)
+        ret i64* getelementptr inbounds (i64* @addr, i64 171)
+}
+
+