Handle big index in getelementptr instruction

CodeGen incorrectly ignores (assert from APInt) constant index bigger
than 2^64 in getelementptr instruction. This is a test and fix for that.

Patch by Paweł Bylica!

Reviewed By: rnk

Subscribers: majnemer, rnk, mcrosier, resistor, llvm-commits

Differential Revision: http://reviews.llvm.org/D8219

llvm-svn: 231984
This commit is contained in:
Reid Kleckner 2015-03-11 23:36:10 +00:00
parent ce2e77c771
commit 016c6b2104
3 changed files with 92 additions and 21 deletions

View File

@ -497,7 +497,7 @@ bool FastISel::selectGetElementPtr(const User *I) {
OI != E; ++OI) {
const Value *Idx = *OI;
if (auto *StTy = dyn_cast<StructType>(Ty)) {
unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
uint64_t Field = cast<ConstantInt>(Idx)->getZExtValue();
if (Field) {
// N = N + Offset
TotalOffs += DL.getStructLayout(StTy)->getElementOffset(Field);
@ -518,8 +518,8 @@ bool FastISel::selectGetElementPtr(const User *I) {
if (CI->isZero())
continue;
// N = N + Offset
TotalOffs +=
DL.getTypeAllocSize(Ty) * cast<ConstantInt>(CI)->getSExtValue();
uint64_t IdxN = CI->getValue().sextOrTrunc(64).getSExtValue();
TotalOffs += DL.getTypeAllocSize(Ty) * IdxN;
if (TotalOffs >= MaxOffs) {
N = fastEmit_ri_(VT, ISD::ADD, N, NIsKill, TotalOffs, VT);
if (!N) // Unhandled operand. Halt "fast" selection and bail.

View File

@ -3448,30 +3448,21 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
Ty = StTy->getElementType(Field);
} else {
Ty = cast<SequentialType>(Ty)->getElementType();
MVT PtrTy = DAG.getTargetLoweringInfo().getPointerTy(AS);
unsigned PtrSize = PtrTy.getSizeInBits();
APInt ElementSize(PtrSize, DL->getTypeAllocSize(Ty));
// If this is a constant subscript, handle it quickly.
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
if (const ConstantInt *CI = dyn_cast<ConstantInt>(Idx)) {
if (CI->isZero()) continue;
uint64_t Offs =
DL->getTypeAllocSize(Ty)*cast<ConstantInt>(CI)->getSExtValue();
SDValue OffsVal;
EVT PTy = TLI.getPointerTy(AS);
unsigned PtrBits = PTy.getSizeInBits();
if (PtrBits < 64)
OffsVal = DAG.getNode(ISD::TRUNCATE, getCurSDLoc(), PTy,
DAG.getConstant(Offs, MVT::i64));
else
OffsVal = DAG.getConstant(Offs, PTy);
N = DAG.getNode(ISD::ADD, getCurSDLoc(), N.getValueType(), N,
OffsVal);
if (const auto *CI = dyn_cast<ConstantInt>(Idx)) {
if (CI->isZero())
continue;
APInt Offs = ElementSize * CI->getValue().sextOrTrunc(PtrSize);
SDValue OffsVal = DAG.getConstant(Offs, PtrTy);
N = DAG.getNode(ISD::ADD, getCurSDLoc(), N.getValueType(), N, OffsVal);
continue;
}
// N = N + Idx * ElementSize;
APInt ElementSize =
APInt(TLI.getPointerSizeInBits(AS), DL->getTypeAllocSize(Ty));
SDValue IdxN = getValue(Idx);
// If the index is smaller or larger than intptr_t, truncate or extend

View File

@ -0,0 +1,80 @@
; RUN: llc < %s -O0 -march=x86
; RUN: llc < %s -O0 -march=x86-64
; RUN: llc < %s -O2 -march=x86
; RUN: llc < %s -O2 -march=x86-64
; Test big index trunc to pointer size:
define i8* @test_trunc65(i8* %ptr) nounwind {
; CHECK-LABEL: test_trunc65
; CHECK: 3
%d = getelementptr i8, i8* %ptr, i65 18446744073709551619 ; 2^64 + 3
ret i8* %d
}
define i8* @test_trunc128(i8* %ptr) nounwind {
; CHECK-LABEL: test_trunc128
; CHECK: 5
%d = getelementptr i8, i8* %ptr, i128 18446744073709551621 ; 2^64 + 5
ret i8* %d
}
define i8* @test_trunc160(i8* %ptr) nounwind {
; CHECK-LABEL: test_trunc160
; CHECK: 8
%d = getelementptr i8, i8* %ptr, i160 18446744073709551624 ; 2^64 + 8
ret i8* %d
}
define i8* @test_trunc256(i8* %ptr) nounwind {
; CHECK-LABEL: test_trunc256
; CHECK: 13
%d = getelementptr i8, i8* %ptr, i256 18446744073709551629 ; 2^64 + 13
ret i8* %d
}
define i8* @test_trunc2048(i8* %ptr) nounwind {
; CHECK-LABEL: test_trunc2048
; CHECK: 21
%d = getelementptr i8, i8* %ptr, i2048 18446744073709551637 ; 2^64 + 21
ret i8* %d
}
; Test small index sext to pointer size
define i8* @test_sext3(i8* %ptr) nounwind {
; CHECK-LABEL: test_sext3
; CHECK: -3
%d = getelementptr i8, i8* %ptr, i3 -3
ret i8* %d
}
define i8* @test_sext5(i8* %ptr) nounwind {
; CHECK-LABEL: test_sext5
; CHECK: -5
%d = getelementptr i8, i8* %ptr, i5 -5
ret i8* %d
}
define i8* @test_sext8(i8* %ptr) nounwind {
; CHECK-LABEL: test_sext8
; CHECK: -8
%d = getelementptr i8, i8* %ptr, i8 -8
ret i8* %d
}
define i8* @test_sext13(i8* %ptr) nounwind {
; CHECK-LABEL: test_sext13
; CHECK: -13
%d = getelementptr i8, i8* %ptr, i8 -13
ret i8* %d
}
define i8* @test_sext16(i8* %ptr) nounwind {
; CHECK-LABEL: test_sext16
; CHECK: -21
%d = getelementptr i8, i8* %ptr, i8 -21
ret i8* %d
}