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
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index e047002..c9b2821 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -504,6 +504,7 @@
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 f9db409..adcd79f 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -457,7 +457,7 @@
/// Aliasee
/// ::= TypeAndValue
/// ::= 'bitcast' '(' TypeAndValue 'to' Type ')'
-/// ::= 'getelementptr' '(' ... ')'
+/// ::= 'getelementptr' 'inbounds'? '(' ... ')'
///
/// Everything through visibility has already been parsed.
///
@@ -2039,7 +2039,11 @@
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 @@
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 @@
}
/// 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 @@
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 c8cdff6..75cc1db 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -54,6 +54,7 @@
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 687cae9..e1cc1a3 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -997,6 +997,7 @@
}
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 @@
}
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 @@
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 @@
}
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 b312420..fd09ede 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -706,6 +706,8 @@
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 @@
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 11d238e..8242d81 100644
--- a/lib/VMCore/AsmWriter.cpp
+++ b/lib/VMCore/AsmWriter.cpp
@@ -854,6 +854,9 @@
} 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";
}
}