mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-31 09:22:31 +00:00
[ConstantFold] Don't incorrectly infer inbounds on array GEP
The many levels of nesting inside the responsible code made it easy for bugs to sneak in. Flattening the logic makes it easier to see what's going on. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275244 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d232ff08a5
commit
4f80506591
@ -2192,51 +2192,68 @@ static Constant *ConstantFoldGetElementPtrImpl(Type *PointeeTy, Constant *C,
|
||||
bool Unknown = !isa<ConstantInt>(Idxs[0]);
|
||||
for (unsigned i = 1, e = Idxs.size(); i != e;
|
||||
Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) {
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) {
|
||||
if (isa<ArrayType>(Ty) && CI->getSExtValue() > 0 &&
|
||||
!isIndexInRangeOfSequentialType(cast<ArrayType>(Ty), CI)) {
|
||||
if (isa<SequentialType>(Prev)) {
|
||||
// It's out of range, but we can factor it into the prior
|
||||
// dimension.
|
||||
NewIdxs.resize(Idxs.size());
|
||||
uint64_t NumElements = 0;
|
||||
if (auto *ATy = dyn_cast<ArrayType>(Ty))
|
||||
NumElements = ATy->getNumElements();
|
||||
else
|
||||
NumElements = cast<VectorType>(Ty)->getNumElements();
|
||||
|
||||
ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements);
|
||||
NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
|
||||
|
||||
Constant *PrevIdx = cast<Constant>(Idxs[i - 1]);
|
||||
Constant *Div = ConstantExpr::getSDiv(CI, Factor);
|
||||
|
||||
unsigned CommonExtendedWidth =
|
||||
std::max(PrevIdx->getType()->getIntegerBitWidth(),
|
||||
Div->getType()->getIntegerBitWidth());
|
||||
CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);
|
||||
|
||||
// Before adding, extend both operands to i64 to avoid
|
||||
// overflow trouble.
|
||||
if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth))
|
||||
PrevIdx = ConstantExpr::getSExt(
|
||||
PrevIdx,
|
||||
Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
|
||||
if (!Div->getType()->isIntegerTy(CommonExtendedWidth))
|
||||
Div = ConstantExpr::getSExt(
|
||||
Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
|
||||
|
||||
NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);
|
||||
} else {
|
||||
// It's out of range, but the prior dimension is a struct
|
||||
// so we can't do anything about it.
|
||||
Unknown = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto *CI = dyn_cast<ConstantInt>(Idxs[i]);
|
||||
if (!CI) {
|
||||
// We don't know if it's in range or not.
|
||||
Unknown = true;
|
||||
continue;
|
||||
}
|
||||
if (isa<StructType>(Ty)) {
|
||||
// The verify makes sure that GEPs into a struct are in range.
|
||||
continue;
|
||||
}
|
||||
auto *STy = cast<SequentialType>(Ty);
|
||||
if (isa<PointerType>(STy)) {
|
||||
// We don't know if it's in range or not.
|
||||
Unknown = true;
|
||||
continue;
|
||||
}
|
||||
if (isa<VectorType>(STy)) {
|
||||
// There can be awkward padding in after a non-power of two vector.
|
||||
Unknown = true;
|
||||
continue;
|
||||
}
|
||||
if (isIndexInRangeOfSequentialType(STy, CI))
|
||||
// It's in range, skip to the next index.
|
||||
continue;
|
||||
if (!isa<SequentialType>(Prev)) {
|
||||
// It's out of range, but the prior dimension is a struct
|
||||
// so we can't do anything about it.
|
||||
Unknown = true;
|
||||
continue;
|
||||
}
|
||||
if (CI->getSExtValue() < 0) {
|
||||
// It's out of range and negative, don't try to factor it.
|
||||
Unknown = true;
|
||||
continue;
|
||||
}
|
||||
// It's out of range, but we can factor it into the prior
|
||||
// dimension.
|
||||
NewIdxs.resize(Idxs.size());
|
||||
// Determine the number of elements in our sequential type.
|
||||
uint64_t NumElements = STy->getArrayNumElements();
|
||||
|
||||
ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements);
|
||||
NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
|
||||
|
||||
Constant *PrevIdx = cast<Constant>(Idxs[i - 1]);
|
||||
Constant *Div = ConstantExpr::getSDiv(CI, Factor);
|
||||
|
||||
unsigned CommonExtendedWidth =
|
||||
std::max(PrevIdx->getType()->getIntegerBitWidth(),
|
||||
Div->getType()->getIntegerBitWidth());
|
||||
CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);
|
||||
|
||||
// Before adding, extend both operands to i64 to avoid
|
||||
// overflow trouble.
|
||||
if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth))
|
||||
PrevIdx = ConstantExpr::getSExt(
|
||||
PrevIdx, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
|
||||
if (!Div->getType()->isIntegerTy(CommonExtendedWidth))
|
||||
Div = ConstantExpr::getSExt(
|
||||
Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
|
||||
|
||||
NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);
|
||||
}
|
||||
|
||||
// If we did any factoring, start over with the adjusted indices.
|
||||
|
@ -46,3 +46,13 @@ define <2 x i8*> @test8(<2 x [2 x i8]*> %a) {
|
||||
%w = getelementptr [2 x i8], <2 x [2 x i8]*> %a, <2 x i32> <i32 0, i32 0>, <2 x i8> <i8 0, i8 1>
|
||||
ret <2 x i8*> %w
|
||||
}
|
||||
|
||||
@array = internal global [16 x i32] [i32 -200, i32 -199, i32 -198, i32 -197, i32 -196, i32 -195, i32 -194, i32 -193, i32 -192, i32 -191, i32 -190, i32 -189, i32 -188, i32 -187, i32 -186, i32 -185], align 16
|
||||
|
||||
; Verify that array GEP doesn't incorrectly infer inbounds.
|
||||
define i32* @test9() {
|
||||
entry:
|
||||
ret i32* getelementptr ([16 x i32], [16 x i32]* @array, i64 0, i64 -13)
|
||||
; CHECK-LABEL: define i32* @test9(
|
||||
; CHECK: ret i32* getelementptr ([16 x i32], [16 x i32]* @array, i64 0, i64 -13)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user