forked from OSchip/llvm-project
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:
parent
ce2e77c771
commit
016c6b2104
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue