mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
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
This commit is contained in:
parent
9a7e2ccf57
commit
dd8004dc73
@ -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>
|
||||
<result> = getelementptr <pty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr inbounds <pty>* <ptrval>{, <ty> <idx>}*
|
||||
</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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(); }
|
||||
|
@ -504,6 +504,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(nuw);
|
||||
KEYWORD(nsw);
|
||||
KEYWORD(exact);
|
||||
KEYWORD(inbounds);
|
||||
KEYWORD(align);
|
||||
KEYWORD(addrspace);
|
||||
KEYWORD(section);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ namespace lltok {
|
||||
kw_nuw,
|
||||
kw_nsw,
|
||||
kw_exact,
|
||||
kw_inbounds,
|
||||
kw_align,
|
||||
kw_addrspace,
|
||||
kw_section,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user