summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-07-27 21:53:46 +0000
committerDan Gohman <gohman@apple.com>2009-07-27 21:53:46 +0000
commitdd8004dc73d091ccb3927dbbc3b41639a3738ae3 (patch)
tree635ee4ff5a89aefb2eb5ba8394207f65c8771bcf
parent9a7e2ccf574368b60455f8c8975030475a1f3ce0 (diff)
downloadllvm-dd8004dc73d091ccb3927dbbc3b41639a3738ae3.tar.gz
llvm-dd8004dc73d091ccb3927dbbc3b41639a3738ae3.tar.bz2
llvm-dd8004dc73d091ccb3927dbbc3b41639a3738ae3.tar.xz
Add a new keyword 'inbounds' for use with getelementptr. See the
LangRef.html changes for details. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77259 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/LangRef.html16
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h6
-rw-r--r--include/llvm/Operator.h9
-rw-r--r--lib/AsmParser/LLLexer.cpp1
-rw-r--r--lib/AsmParser/LLParser.cpp17
-rw-r--r--lib/AsmParser/LLToken.h1
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp6
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp4
-rw-r--r--lib/VMCore/AsmWriter.cpp3
-rw-r--r--test/Assembler/flags-plain.ll5
-rw-r--r--test/Assembler/flags.ll19
11 files changed, 83 insertions, 4 deletions
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 1f9f80d6d4..adc5d9a143 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -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>
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index 3d8c246914..38f152dcce 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -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
diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h
index 932c2ace8c..c62164bcbc 100644
--- a/include/llvm/Operator.h
+++ b/include/llvm/Operator.h
@@ -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(); }
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index e047002c13..c9b2821243 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -504,6 +504,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(nuw);
KEYWORD(nsw);
KEYWORD(exact);
+ KEYWORD(inbounds);
KEYWORD(align);
KEYWORD(addrspace);
KEYWORD(section);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index f9db40915a..adcd79f40a 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -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;
}
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index c8cdff6bf6..75cc1db8ad 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -54,6 +54,7 @@ namespace lltok {
kw_nuw,
kw_nsw,
kw_exact,
+ kw_inbounds,
kw_align,
kw_addrspace,
kw_section,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 687cae9ecf..e1cc1a3afb 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -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;
}
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index b312420490..fd09edec94 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -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;
diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp
index 11d238eba2..8242d8155b 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -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";
}
}
diff --git a/test/Assembler/flags-plain.ll b/test/Assembler/flags-plain.ll
index 148d02fc06..bf3d5d891f 100644
--- a/test/Assembler/flags-plain.ll
+++ b/test/Assembler/flags-plain.ll
@@ -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)
+}
diff --git a/test/Assembler/flags.ll b/test/Assembler/flags.ll
index 4efb1cdb23..981a4e592c 100644
--- a/test/Assembler/flags.ll
+++ b/test/Assembler/flags.ll
@@ -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)
+}
+
+