mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-27 06:35:30 +00:00
[SROA] Add an off-by-default *strict* inbounds check to SROA. I had SROA
implemented this way a long time ago and due to the overwhelming bugs that surfaced, moved to a much more relaxed variant. Richard Smith would like to understand the magnitude of this problem and it seems fairly harmless to keep some flag-controlled logic to get the extremely strict behavior here. I'll remove it if it doesn't prove useful. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202193 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
15ac7dfb90
commit
495e40121b
@ -85,6 +85,11 @@ ForceSSAUpdater("force-ssa-updater", cl::init(false), cl::Hidden);
|
|||||||
static cl::opt<bool> SROARandomShuffleSlices("sroa-random-shuffle-slices",
|
static cl::opt<bool> SROARandomShuffleSlices("sroa-random-shuffle-slices",
|
||||||
cl::init(false), cl::Hidden);
|
cl::init(false), cl::Hidden);
|
||||||
|
|
||||||
|
/// Hidden option to experiment with completely strict handling of inbounds
|
||||||
|
/// GEPs.
|
||||||
|
static cl::opt<bool> SROAStrictInbounds("sroa-strict-inbounds",
|
||||||
|
cl::init(false), cl::Hidden);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// \brief A custom IRBuilder inserter which prefixes all names if they are
|
/// \brief A custom IRBuilder inserter which prefixes all names if they are
|
||||||
/// preserved.
|
/// preserved.
|
||||||
@ -392,6 +397,43 @@ private:
|
|||||||
if (GEPI.use_empty())
|
if (GEPI.use_empty())
|
||||||
return markAsDead(GEPI);
|
return markAsDead(GEPI);
|
||||||
|
|
||||||
|
if (SROAStrictInbounds && GEPI.isInBounds()) {
|
||||||
|
// FIXME: This is a manually un-factored variant of the basic code inside
|
||||||
|
// of GEPs with checking of the inbounds invariant specified in the
|
||||||
|
// langref in a very strict sense. If we ever want to enable
|
||||||
|
// SROAStrictInbounds, this code should be factored cleanly into
|
||||||
|
// PtrUseVisitor, but it is easier to experiment with SROAStrictInbounds
|
||||||
|
// by writing out the code here where we have tho underlying allocation
|
||||||
|
// size readily available.
|
||||||
|
APInt GEPOffset = Offset;
|
||||||
|
for (gep_type_iterator GTI = gep_type_begin(GEPI),
|
||||||
|
GTE = gep_type_end(GEPI);
|
||||||
|
GTI != GTE; ++GTI) {
|
||||||
|
ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
|
||||||
|
if (!OpC)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Handle a struct index, which adds its field offset to the pointer.
|
||||||
|
if (StructType *STy = dyn_cast<StructType>(*GTI)) {
|
||||||
|
unsigned ElementIdx = OpC->getZExtValue();
|
||||||
|
const StructLayout *SL = DL.getStructLayout(STy);
|
||||||
|
GEPOffset +=
|
||||||
|
APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx));
|
||||||
|
} else {
|
||||||
|
// For array or vector indices, scale the index by the size of the type.
|
||||||
|
APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth());
|
||||||
|
GEPOffset += Index * APInt(Offset.getBitWidth(),
|
||||||
|
DL.getTypeAllocSize(GTI.getIndexedType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this index has computed an intermediate pointer which is not
|
||||||
|
// inbounds, then the result of the GEP is a poison value and we can
|
||||||
|
// delete it and all uses.
|
||||||
|
if (GEPOffset.ugt(AllocSize))
|
||||||
|
return markAsDead(GEPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Base::visitGetElementPtrInst(GEPI);
|
return Base::visitGetElementPtrInst(GEPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user