// Returns whether (Base + Index * Stride) can be folded to an addressing mode.
static bool isAddFoldable(const SCEV *Base, ConstantInt *Index, Value *Stride,
TargetTransformInfo *TTI) {
- return TTI->isLegalAddressingMode(Base->getType(), nullptr, 0, true,
+ // Index->getSExtValue() may crash if Index is wider than 64-bit.
+ return Index->getBitWidth() <= 64 &&
+ TTI->isLegalAddressingMode(Base->getType(), nullptr, 0, true,
Index->getSExtValue(), UnknownAddressSpace);
}
IndexExprs, GEP->isInBounds());
Value *ArrayIdx = GEP->getOperand(I);
uint64_t ElementSize = DL->getTypeAllocSize(*GTI);
- factorArrayIndex(ArrayIdx, BaseExpr, ElementSize, GEP);
+ if (ArrayIdx->getType()->getIntegerBitWidth() <=
+ DL->getPointerSizeInBits()) {
+ // Skip factoring if ArrayIdx is wider than the pointer size, because
+ // ArrayIdx is implicitly truncated to the pointer size.
+ factorArrayIndex(ArrayIdx, BaseExpr, ElementSize, GEP);
+ }
// When ArrayIdx is the sext of a value, we try to factor that value as
// well. Handling this case is important because array indices are
// typically sign-extended to the pointer size.
Value *TruncatedArrayIdx = nullptr;
- if (match(ArrayIdx, m_SExt(m_Value(TruncatedArrayIdx))))
+ if (match(ArrayIdx, m_SExt(m_Value(TruncatedArrayIdx))) &&
+ TruncatedArrayIdx->getType()->getIntegerBitWidth() <=
+ DL->getPointerSizeInBits()) {
+ // Skip factoring if TruncatedArrayIdx is wider than the pointer size,
+ // because TruncatedArrayIdx is implicitly truncated to the pointer size.
factorArrayIndex(TruncatedArrayIdx, BaseExpr, ElementSize, GEP);
+ }
IndexExprs[I - 1] = OrigIndexExpr;
}
if (Basis.CandidateKind == Candidate::GEP) {
APInt ElementSize(
IndexOffset.getBitWidth(),
- DL->getTypeAllocSize(cast<GetElementPtrInst>(Basis.Ins)->getResultElementType()));
+ DL->getTypeAllocSize(
+ cast<GetElementPtrInst>(Basis.Ins)->getResultElementType()));
APInt Q, R;
APInt::sdivrem(IndexOffset, ElementSize, Q, R);
- if (R.getSExtValue() == 0)
+ if (R == 0)
IndexOffset = Q;
else
BumpWithUglyGEP = true;
// Compute Bump = C - Basis = (i' - i) * S.
// Common case 1: if (i' - i) is 1, Bump = S.
- if (IndexOffset.getSExtValue() == 1)
+ if (IndexOffset == 1)
return C.Stride;
// Common case 2: if (i' - i) is -1, Bump = -S.
- if (IndexOffset.getSExtValue() == -1)
+ if (IndexOffset.isAllOnesValue())
return Builder.CreateNeg(C.Stride);
// Otherwise, Bump = (i' - i) * sext/trunc(S). Note that (i' - i) and S may
; CHECK-LABEL: @slsr_gep(
; v0 = input[0];
%p0 = getelementptr inbounds i32, i32* %input, i64 0
- %v0 = load i32, i32* %p0
- call void @foo(i32 %v0)
+ call void @foo(i32* %p0)
; v1 = input[s];
%p1 = getelementptr inbounds i32, i32* %input, i64 %s
; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %s
- %v1 = load i32, i32* %p1
- call void @foo(i32 %v1)
+ call void @foo(i32* %p1)
; v2 = input[s * 2];
%s2 = shl nsw i64 %s, 1
%p2 = getelementptr inbounds i32, i32* %input, i64 %s2
; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %s
- %v2 = load i32, i32* %p2
- call void @foo(i32 %v2)
+ call void @foo(i32* %p2)
ret void
}
; CHECK-LABEL: @slsr_gep_sext(
; v0 = input[0];
%p0 = getelementptr inbounds i32, i32* %input, i64 0
- %v0 = load i32, i32* %p0
- call void @foo(i32 %v0)
+ call void @foo(i32* %p0)
; v1 = input[s];
%t = sext i32 %s to i64
%p1 = getelementptr inbounds i32, i32* %input, i64 %t
; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %t
- %v1 = load i32, i32* %p1
- call void @foo(i32 %v1)
+ call void @foo(i32* %p1)
; v2 = input[s * 2];
%s2 = shl nsw i32 %s, 1
%t2 = sext i32 %s2 to i64
%p2 = getelementptr inbounds i32, i32* %input, i64 %t2
; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %t
- %v2 = load i32, i32* %p2
- call void @foo(i32 %v2)
+ call void @foo(i32* %p2)
ret void
}
; CHECK-LABEL: @slsr_gep_2d(
; v0 = input[s][t];
%p0 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s, i64 %t
- %v0 = load i32, i32* %p0
- call void @foo(i32 %v0)
+ call void @foo(i32* %p0)
; v1 = input[s * 2][t];
%s2 = shl nsw i64 %s, 1
; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 5
%p1 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s2, i64 %t
; CHECK: %p1 = getelementptr inbounds i32, i32* %p0, i64 [[BUMP]]
- %v1 = load i32, i32* %p1
- call void @foo(i32 %v1)
+ call void @foo(i32* %p1)
; v3 = input[s * 3][t];
%s3 = mul nsw i64 %s, 3
%p2 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s3, i64 %t
; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 [[BUMP]]
- %v2 = load i32, i32* %p2
- call void @foo(i32 %v2)
+ call void @foo(i32* %p2)
ret void
}
; CHECK-LABEL: @slsr_gep_uglygep(
; v0 = input[s][t].f1;
%p0 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s, i64 %t, i32 0
- %v0 = load i64, i64* %p0
- call void @bar(i64 %v0)
+ call void @bar(i64* %p0)
; v1 = input[s * 2][t].f1;
%s2 = shl nsw i64 %s, 1
; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 60
%p1 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s2, i64 %t, i32 0
; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
- %v1 = load i64, i64* %p1
- call void @bar(i64 %v1)
+ call void @bar(i64* %p1)
; v2 = input[s * 3][t].f1;
%s3 = mul nsw i64 %s, 3
%p2 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s3, i64 %t, i32 0
; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
- %v2 = load i64, i64* %p2
- call void @bar(i64 %v2)
+ call void @bar(i64* %p2)
ret void
}
; CHECK-LABEL: @slsr_out_of_bounds_gep(
; v0 = input[0];
%p0 = getelementptr i32, i32* %input, i64 0
- %v0 = load i32, i32* %p0
- call void @foo(i32 %v0)
+ call void @foo(i32* %p0)
; v1 = input[(long)s];
%t = sext i32 %s to i64
%p1 = getelementptr i32, i32* %input, i64 %t
; CHECK: %p1 = getelementptr i32, i32* %input, i64 %t
- %v1 = load i32, i32* %p1
- call void @foo(i32 %v1)
+ call void @foo(i32* %p1)
; v2 = input[(long)(s * 2)];
%s2 = shl nsw i32 %s, 1
%t2 = sext i32 %s2 to i64
%p2 = getelementptr i32, i32* %input, i64 %t2
; CHECK: %p2 = getelementptr i32, i32* %p1, i64 %t
- %v2 = load i32, i32* %p2
- call void @foo(i32 %v2)
+ call void @foo(i32* %p2)
ret void
}
-declare void @foo(i32)
-declare void @bar(i64)
+define void @slsr_gep_128bit(i32* %input, i128 %s) {
+; CHECK-LABEL: @slsr_gep_128bit(
+ ; p0 = &input[0]
+ %p0 = getelementptr inbounds i32, i32* %input, i128 0
+ call void @foo(i32* %p0)
+
+ ; p1 = &input[s << 125]
+ %s125 = shl nsw i128 %s, 125
+ %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
+; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
+ call void @foo(i32* %p1)
+
+ ; p2 = &input[s << 126]
+ %s126 = shl nsw i128 %s, 126
+ %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
+; CHECK: %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
+ call void @foo(i32* %p2)
+
+ ret void
+}
+
+declare void @foo(i32*)
+declare void @bar(i64*)