ConstantFold: Properly fold GEP indices wider than i64

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229420 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2015-02-16 19:10:02 +00:00
parent 25a35b5639
commit e6e5eaa50d
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)) if (!isa<ConstantInt>(C1) || !isa<ConstantInt>(C2))
return -2; // don't know! 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 // Ok, we have two differing integer indices. Sign extend them to be the same
// type. Long is always big enough, so we use it. // type.
if (!C1->getType()->isIntegerTy(64)) int64_t C1Val = cast<ConstantInt>(C1)->getSExtValue();
C1 = ConstantExpr::getSExt(C1, Type::getInt64Ty(C1->getContext())); int64_t C2Val = cast<ConstantInt>(C2)->getSExtValue();
if (!C2->getType()->isIntegerTy(64)) if (C1Val == C2Val) return 0; // They are equal
C2 = ConstantExpr::getSExt(C2, Type::getInt64Ty(C1->getContext()));
if (C1 == C2) return 0; // They are equal
// If the type being indexed over is really just a zero sized type, there is // If the type being indexed over is really just a zero sized type, there is
// no pointer difference being made here. // 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 // If they are really different, now that they are the same type, then we
// found a difference! // found a difference!
if (cast<ConstantInt>(C1)->getSExtValue() < if (C1Val < C2Val)
cast<ConstantInt>(C2)->getSExtValue())
return -1; return -1;
else else
return 1; return 1;
@ -2088,9 +2089,15 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
if (!Idx0->isNullValue()) { if (!Idx0->isNullValue()) {
Type *IdxTy = Combined->getType(); Type *IdxTy = Combined->getType();
if (IdxTy != Idx0->getType()) { if (IdxTy != Idx0->getType()) {
Type *Int64Ty = Type::getInt64Ty(IdxTy->getContext()); unsigned CommonExtendedWidth =
Constant *C1 = ConstantExpr::getSExtOrBitCast(Idx0, Int64Ty); std::max(IdxTy->getIntegerBitWidth(),
Constant *C2 = ConstantExpr::getSExtOrBitCast(Combined, Int64Ty); 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); Combined = ConstantExpr::get(Instruction::Add, C1, C2);
} else { } else {
Combined = Combined =
@ -2163,14 +2170,20 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
Constant *PrevIdx = cast<Constant>(Idxs[i-1]); Constant *PrevIdx = cast<Constant>(Idxs[i-1]);
Constant *Div = ConstantExpr::getSDiv(CI, Factor); 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 // Before adding, extend both operands to i64 to avoid
// overflow trouble. // overflow trouble.
if (!PrevIdx->getType()->isIntegerTy(64)) if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth))
PrevIdx = ConstantExpr::getSExt(PrevIdx, PrevIdx = ConstantExpr::getSExt(
Type::getInt64Ty(Div->getContext())); PrevIdx,
if (!Div->getType()->isIntegerTy(64)) Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
Div = ConstantExpr::getSExt(Div, if (!Div->getType()->isIntegerTy(CommonExtendedWidth))
Type::getInt64Ty(Div->getContext())); Div = ConstantExpr::getSExt(
Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
NewIdxs[i-1] = ConstantExpr::getAdd(PrevIdx, Div); NewIdxs[i-1] = ConstantExpr::getAdd(PrevIdx, Div);
} else { } 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) @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) ; 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. ; Verify that i16 indices work.
@x = external global {i32, i32} @x = external global {i32, i32}
@y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0) @y = global i32* getelementptr ({ i32, i32 }* @x, i16 42, i32 0)