ConstantFold: Properly fold GEP indices wider than i64

llvm-svn: 229420
This commit is contained in:
David Majnemer 2015-02-16 19:10:02 +00:00
parent 83570247f1
commit 8b77454dff
2 changed files with 37 additions and 18 deletions

View File

@ -1282,15 +1282,17 @@ static int IdxCompare(Constant *C1, Constant *C2, Type *ElTy) {
if (!isa<ConstantInt>(C1) || !isa<ConstantInt>(C2))
return -2; // don't know!
// We cannot compare the indices if they don't fit in an int64_t.
if (cast<ConstantInt>(C1)->getValue().getActiveBits() > 64 ||
cast<ConstantInt>(C2)->getValue().getActiveBits() > 64)
return -2; // don't know!
// Ok, we have two differing integer indices. Sign extend them to be the same
// type. Long is always big enough, so we use it.
if (!C1->getType()->isIntegerTy(64))
C1 = ConstantExpr::getSExt(C1, Type::getInt64Ty(C1->getContext()));
// type.
int64_t C1Val = cast<ConstantInt>(C1)->getSExtValue();
int64_t C2Val = cast<ConstantInt>(C2)->getSExtValue();
if (!C2->getType()->isIntegerTy(64))
C2 = ConstantExpr::getSExt(C2, Type::getInt64Ty(C1->getContext()));
if (C1 == C2) return 0; // They are equal
if (C1Val == C2Val) return 0; // They are equal
// If the type being indexed over is really just a zero sized type, there is
// no pointer difference being made here.
@ -1299,8 +1301,7 @@ static int IdxCompare(Constant *C1, Constant *C2, Type *ElTy) {
// If they are really different, now that they are the same type, then we
// found a difference!
if (cast<ConstantInt>(C1)->getSExtValue() <
cast<ConstantInt>(C2)->getSExtValue())
if (C1Val < C2Val)
return -1;
else
return 1;
@ -2088,9 +2089,15 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
if (!Idx0->isNullValue()) {
Type *IdxTy = Combined->getType();
if (IdxTy != Idx0->getType()) {
Type *Int64Ty = Type::getInt64Ty(IdxTy->getContext());
Constant *C1 = ConstantExpr::getSExtOrBitCast(Idx0, Int64Ty);
Constant *C2 = ConstantExpr::getSExtOrBitCast(Combined, Int64Ty);
unsigned CommonExtendedWidth =
std::max(IdxTy->getIntegerBitWidth(),
Idx0->getType()->getIntegerBitWidth());
CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);
Type *CommonTy =
Type::getIntNTy(IdxTy->getContext(), CommonExtendedWidth);
Constant *C1 = ConstantExpr::getSExtOrBitCast(Idx0, CommonTy);
Constant *C2 = ConstantExpr::getSExtOrBitCast(Combined, CommonTy);
Combined = ConstantExpr::get(Instruction::Add, C1, C2);
} else {
Combined =
@ -2163,14 +2170,20 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
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(64))
PrevIdx = ConstantExpr::getSExt(PrevIdx,
Type::getInt64Ty(Div->getContext()));
if (!Div->getType()->isIntegerTy(64))
Div = ConstantExpr::getSExt(Div,
Type::getInt64Ty(Div->getContext()));
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 {

View File

@ -8,6 +8,12 @@
@C = global i32* getelementptr ([2 x [3 x [5 x [7 x i32]]]]* @A, i64 3, i64 2, i64 0, i64 0, i64 7523)
; CHECK: @C = global i32* getelementptr ([2 x [3 x [5 x [7 x i32]]]]* @A, i64 39, i64 1, i64 1, i64 4, i64 5)
; Verify that constant expression GEPs work with i84 indices.
@D = external global [1 x i32]
@E = global i32* getelementptr inbounds ([1 x i32]* @D, i84 0, i64 1)
; CHECK: @E = global i32* getelementptr inbounds ([1 x i32]* @D, i84 1, i64 0)
; Verify that i16 indices work.
@x = external global {i32, i32}
@y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0)