Skip to content

Commit 6db71b8

Browse files
committed
[ConstraintElim] Use helper to allow overflow for coefficients of GEPs
If the arithmetic for indices of inbounds GEPs overflows, the result is poison. This means it is also OK for the coefficients to overflow. GEP decomposition is limited to cases where the index size is <= 64 bit, which can be represented by int64_t used for the coefficients in the constraint system.
1 parent d8af31e commit 6db71b8

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

llvm/lib/Transforms/Scalar/ConstraintElimination.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ static int64_t multiplyWithOverflow(int64_t A, int64_t B) {
196196
return Result;
197197
}
198198

199+
// A helper to add 2 signed integers where overflowing is allowed.
200+
static int64_t addWithOverflow(int64_t A, int64_t B) {
201+
int64_t Result;
202+
AddOverflow(A, B, Result);
203+
return Result;
204+
}
205+
199206
static SmallVector<DecompEntry, 4>
200207
decomposeGEP(GetElementPtrInst &GEP,
201208
SmallVector<PreconditionTy, 4> &Preconditions, bool IsSigned,
@@ -225,7 +232,9 @@ decomposeGEP(GetElementPtrInst &GEP,
225232
int64_t Scale = static_cast<int64_t>(
226233
DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize());
227234

228-
Result[0].Coefficient += multiplyWithOverflow(Scale, Offset.getSExtValue());
235+
Result[0].Coefficient =
236+
addWithOverflow(Result[0].Coefficient,
237+
multiplyWithOverflow(Scale, Offset.getSExtValue()));
229238
if (Offset.isNegative()) {
230239
// Add pre-condition ensuring the GEP is increasing monotonically and
231240
// can be de-composed.
@@ -257,8 +266,9 @@ decomposeGEP(GetElementPtrInst &GEP,
257266
continue;
258267

259268
// Add offset to constant factor.
260-
Result[0].Coefficient +=
261-
DL.getStructLayout(STy)->getElementOffset(FieldNo);
269+
Result[0].Coefficient = addWithOverflow(
270+
Result[0].Coefficient,
271+
int64_t(DL.getStructLayout(STy)->getElementOffset(FieldNo)));
262272
continue;
263273
}
264274

llvm/test/Transforms/ConstraintElimination/large-constant-ints.ll

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,4 +350,54 @@ entry:
350350
ret i1 %res
351351
}
352352

353+
define i1 @gep_decomp_large_index_63_bits_chained_overflow(ptr %a) {
354+
; CHECK-LABEL: @gep_decomp_large_index_63_bits_chained_overflow(
355+
; CHECK-NEXT: entry:
356+
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 9223372036854775804
357+
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds ptr, ptr [[A]], i64 1152921504606846976
358+
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i64, ptr [[GEP_2]], i64 1152921504606846976
359+
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[GEP_1]], [[GEP_3]]
360+
; CHECK-NEXT: call void @llvm.assume(i1 [[NE]])
361+
; CHECK-NEXT: [[CMP_ULE:%.*]] = icmp ule ptr [[GEP_1]], [[GEP_3]]
362+
; CHECK-NEXT: [[CMP_UGE:%.*]] = icmp uge ptr [[GEP_1]], [[GEP_3]]
363+
; CHECK-NEXT: [[RES:%.*]] = xor i1 true, true
364+
; CHECK-NEXT: ret i1 [[RES]]
365+
;
366+
entry:
367+
%gep.1 = getelementptr inbounds i64, ptr %a, i64 9223372036854775804
368+
%gep.2 = getelementptr inbounds ptr, ptr %a, i64 1152921504606846976
369+
%gep.3 = getelementptr inbounds i64, ptr %gep.2, i64 1152921504606846976
370+
%ne = icmp ne ptr %gep.1, %gep.3
371+
call void @llvm.assume(i1 %ne)
372+
%cmp.ule = icmp ule ptr %gep.1, %gep.3
373+
%cmp.uge = icmp uge ptr %gep.1, %gep.3
374+
%res = xor i1 %cmp.ule, %cmp.ule
375+
ret i1 %res
376+
}
377+
378+
%struct = type { [128 x i64], [2 x i32] }
379+
380+
define i1 @gep_decomp_large_index_63_bits_overflow_struct(ptr %a) {
381+
; CHECK-LABEL: @gep_decomp_large_index_63_bits_overflow_struct(
382+
; CHECK-NEXT: entry:
383+
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 9223372036854775804
384+
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds [[STRUCT:%.*]], ptr [[A]], i64 8937376004704240, i32 1, i32 1
385+
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[GEP_1]], [[GEP_2]]
386+
; CHECK-NEXT: call void @llvm.assume(i1 [[NE]])
387+
; CHECK-NEXT: [[CMP_ULE:%.*]] = icmp ule ptr [[GEP_1]], [[GEP_2]]
388+
; CHECK-NEXT: [[CMP_UGE:%.*]] = icmp uge ptr [[GEP_1]], [[GEP_2]]
389+
; CHECK-NEXT: [[RES:%.*]] = xor i1 false, false
390+
; CHECK-NEXT: ret i1 [[RES]]
391+
;
392+
entry:
393+
%gep.1 = getelementptr inbounds i64, ptr %a, i64 9223372036854775804
394+
%gep.2 = getelementptr inbounds %struct, ptr %a, i64 8937376004704240, i32 1, i32 1
395+
%ne = icmp ne ptr %gep.1, %gep.2
396+
call void @llvm.assume(i1 %ne)
397+
%cmp.ule = icmp ule ptr %gep.1, %gep.2
398+
%cmp.uge = icmp uge ptr %gep.1, %gep.2
399+
%res = xor i1 %cmp.ule, %cmp.ule
400+
ret i1 %res
401+
}
402+
353403
declare void @llvm.assume(i1)

0 commit comments

Comments
 (0)