IR: Introduce inrange attribute on getelementptr indices.

If the inrange keyword is present before any index, loading from or
storing to any pointer derived from the getelementptr has undefined
behavior if the load or store would access memory outside of the bounds of
the element selected by the index marked as inrange.

This can be used, e.g. for alias analysis or to split globals at element
boundaries where beneficial.

As previously proposed on llvm-dev:
http://lists.llvm.org/pipermail/llvm-dev/2016-July/102472.html

Differential Revision: https://reviews.llvm.org/D22793

llvm-svn: 286514
This commit is contained in:
Peter Collingbourne
2016-11-10 22:34:55 +00:00
parent a0dee61df3
commit d93620bf4d
18 changed files with 218 additions and 64 deletions

View File

@@ -3268,12 +3268,25 @@ Error BitcodeReader::parseConstants() {
}
break;
}
case bitc::CST_CODE_CE_INBOUNDS_GEP:
case bitc::CST_CODE_CE_GEP: { // CE_GEP: [n x operands]
case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands]
case bitc::CST_CODE_CE_GEP: // [ty, n x operands]
case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX: { // [ty, flags, n x
// operands]
unsigned OpNum = 0;
Type *PointeeType = nullptr;
if (Record.size() % 2)
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX ||
Record.size() % 2)
PointeeType = getTypeByID(Record[OpNum++]);
bool InBounds = false;
Optional<unsigned> InRangeIndex;
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX) {
uint64_t Op = Record[OpNum++];
InBounds = Op & 1;
InRangeIndex = Op >> 1;
} else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
InBounds = true;
SmallVector<Constant*, 16> Elts;
while (OpNum != Record.size()) {
Type *ElTy = getTypeByID(Record[OpNum++]);
@@ -3294,8 +3307,7 @@ Error BitcodeReader::parseConstants() {
ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
V = ConstantExpr::getGetElementPtr(PointeeType, Elts[0], Indices,
BitCode ==
bitc::CST_CODE_CE_INBOUNDS_GEP);
InBounds, InRangeIndex);
break;
}
case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#]