
The constraint system used for ConstraintElimination assumes all varibles to be signed. This can cause missed optimization in the unsigned system, due to missing the information that all variables are unsigned (non-negative). Variables can be marked as non-negative by adding Var >= 0 for all variables. This is done for arguments on ConstraintInfo construction and after adding new variables. This handles cases like the ones outlined in https://discourse.llvm.org/t/why-does-llvm-not-perform-range-analysis-on-integer-values/74341 The original example shared above is now handled without this change, but adding another variable means that instcombine won't be able to simplify examples like https://godbolt.org/z/hTnra7zdY Adding the extra variables comes with a slight compile-time increase https://llvm-compile-time-tracker.com/compare.php?from=7568b36a2bc1a1e496ec29246966ffdfc3a8b87f&to=641a47f0acce7755e340447386013a2e086f03d9&stat=instructions:u stage1-O3 stage1-ReleaseThinLTO stage1-ReleaseLTO-g stage1-O0-g +0.04% +0.07% +0.05% +0.02% stage2-O3 stage2-O0-g stage2-clang +0.05% +0.05% +0.05% https://github.com/llvm/llvm-project/pull/76262
436 lines
15 KiB
LLVM
436 lines
15 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
|
|
|
|
declare void @use(i1)
|
|
|
|
define void @test_unsigned_too_large(i128 %x) {
|
|
; CHECK-LABEL: @test_unsigned_too_large(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i128 [[X:%.*]], 12345678901234123123123
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ult i128 [[X]], -12345678901234123123123
|
|
; CHECK-NEXT: call void @use(i1 [[C_2]])
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp uge i128 [[X]], -12345678901234123123123
|
|
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp uge i128 [[X]], -12345678901234123123123
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: bb2:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i128 %x, 12345678901234123123123
|
|
br i1 %c.1, label %bb1, label %bb2
|
|
|
|
bb1:
|
|
%c.2 = icmp ult i128 %x, -12345678901234123123123
|
|
call void @use(i1 %c.2)
|
|
%c.3 = icmp uge i128 %x, -12345678901234123123123
|
|
call void @use(i1 %c.3)
|
|
%c.4 = icmp uge i128 %x, -12345678901234123123123
|
|
call void @use(i1 %c.4)
|
|
ret void
|
|
|
|
bb2:
|
|
ret void
|
|
}
|
|
|
|
define void @test_signed_too_large(i128 %x) {
|
|
; CHECK-LABEL: @test_signed_too_large(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp sle i128 [[X:%.*]], 12345678901234123123123
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i128 [[X]], -12345678901234123123123
|
|
; CHECK-NEXT: call void @use(i1 [[C_2]])
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp sge i128 [[X]], -12345678901234123123123
|
|
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp sge i128 [[X]], -12345678901234123123123
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: bb2:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.1 = icmp sle i128 %x, 12345678901234123123123
|
|
br i1 %c.1, label %bb1, label %bb2
|
|
|
|
bb1:
|
|
%c.2 = icmp slt i128 %x, -12345678901234123123123
|
|
call void @use(i1 %c.2)
|
|
%c.3 = icmp sge i128 %x, -12345678901234123123123
|
|
call void @use(i1 %c.3)
|
|
%c.4 = icmp sge i128 %x, -12345678901234123123123
|
|
call void @use(i1 %c.4)
|
|
ret void
|
|
|
|
bb2:
|
|
ret void
|
|
}
|
|
|
|
define i1 @add_decomp_i80(i80 %a) {
|
|
; CHECK-LABEL: @add_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i80 [[A:%.*]], -1973801615886922022913
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult i80 [[ADD]], 1346612317380797267967
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i80 [[A]], -1973801615886922022913
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i80 [[ADD_1]], 1346612317380797267967
|
|
; CHECK-NEXT: ret i1 [[C_1]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%add = add nsw i80 %a, -1973801615886922022913
|
|
%c = icmp ult i80 %add, 1346612317380797267967
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%add.1 = add nsw i80 %a, -1973801615886922022913
|
|
%c.1 = icmp ult i80 %add.1, 1346612317380797267967
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
; TODO: This could be folded.
|
|
define i1 @sub_decomp_i80(i80 %a) {
|
|
; CHECK-LABEL: @sub_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[SUB:%.*]] = sub nuw i80 [[A:%.*]], 1973801615886922022913
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult i80 [[SUB]], 1346612317380797267967
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[SUB_1:%.*]] = sub nuw i80 [[A]], 1973801615886922022913
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ult i80 [[SUB_1]], 1346612317380797267967
|
|
; CHECK-NEXT: ret i1 [[C_1]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%sub = sub nuw i80 %a, 1973801615886922022913
|
|
%c = icmp ult i80 %sub, 1346612317380797267967
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%sub.1 = sub nuw i80 %a, 1973801615886922022913
|
|
%c.1 = icmp ult i80 %sub.1, 1346612317380797267967
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @gep_decomp_i80(ptr %a) {
|
|
; CHECK-LABEL: @gep_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i80 1973801615886922022913
|
|
; CHECK-NEXT: br i1 false, label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i80 1973801615886922022913
|
|
; CHECK-NEXT: ret i1 true
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%gep = getelementptr inbounds i8, ptr %a, i80 1973801615886922022913
|
|
%c = icmp eq ptr %gep, null
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%gep.1 = getelementptr inbounds i8, ptr %a, i80 1973801615886922022913
|
|
%c.1 = icmp eq ptr %gep.1, null
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @gep_zext_shl_decomp_i80(ptr %a, i80 %v) {
|
|
; CHECK-LABEL: @gep_zext_shl_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i80 [[V:%.*]], 1973801615886922022913
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext i80 [[SHL]] to i128
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i128 [[EXT]]
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[GEP]], null
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[SHL_1:%.*]] = shl nuw i80 [[V]], 1973801615886922022913
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = zext i80 [[SHL_1]] to i128
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i128 [[EXT_1]]
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[GEP_1]], null
|
|
; CHECK-NEXT: ret i1 [[C_1]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%shl = shl nuw i80 %v, 1973801615886922022913
|
|
%ext = zext i80 %shl to i128
|
|
%gep = getelementptr inbounds i8, ptr %a, i128 %ext
|
|
%c = icmp eq ptr %gep, null
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%shl.1 = shl nuw i80 %v, 1973801615886922022913
|
|
%ext.1 = zext i80 %shl.1 to i128
|
|
%gep.1 = getelementptr inbounds i8, ptr %a, i128 %ext.1
|
|
%c.1 = icmp eq ptr %gep.1, null
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @gep_zext_add_decomp_i80(ptr %a, i80 %v) {
|
|
; CHECK-LABEL: @gep_zext_add_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i80 [[V:%.*]], 1973801615886922022913
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext i80 [[ADD]] to i128
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i128 [[EXT]]
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[GEP]], null
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i80 [[V]], 1973801615886922022913
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = zext i80 [[ADD_1]] to i128
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i128 [[EXT_1]]
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[GEP_1]], null
|
|
; CHECK-NEXT: ret i1 [[C_1]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%add = add nsw i80 %v, 1973801615886922022913
|
|
%ext = zext i80 %add to i128
|
|
%gep = getelementptr inbounds i8, ptr %a, i128 %ext
|
|
%c = icmp eq ptr %gep, null
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%add.1 = add nsw i80 %v, 1973801615886922022913
|
|
%ext.1 = zext i80 %add.1 to i128
|
|
%gep.1 = getelementptr inbounds i8, ptr %a, i128 %ext.1
|
|
%c.1 = icmp eq ptr %gep.1, null
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @gep_shl_decomp_i80(ptr %a, i80 %v) {
|
|
; CHECK-LABEL: @gep_shl_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i80 [[V:%.*]], 1973801615886922022913
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i80 [[SHL]]
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[GEP]], null
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[SHL_1:%.*]] = shl nuw i80 [[V]], 1973801615886922022913
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i80 [[SHL_1]]
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[GEP_1]], null
|
|
; CHECK-NEXT: ret i1 [[C_1]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%shl = shl nuw i80 %v, 1973801615886922022913
|
|
%gep = getelementptr inbounds i8, ptr %a, i80 %shl
|
|
%c = icmp eq ptr %gep, null
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%shl.1 = shl nuw i80 %v, 1973801615886922022913
|
|
%gep.1 = getelementptr inbounds i8, ptr %a, i80 %shl.1
|
|
%c.1 = icmp eq ptr %gep.1, null
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @gep_add_decomp_i80(ptr %a, i80 %v) {
|
|
; CHECK-LABEL: @gep_add_decomp_i80(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i80 [[V:%.*]], 1973801615886922022913
|
|
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i80 [[ADD]]
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[GEP]], null
|
|
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[ADD_1:%.*]] = add nsw i80 [[V]], 1973801615886922022913
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[A]], i80 [[ADD_1]]
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[GEP_1]], null
|
|
; CHECK-NEXT: ret i1 [[C_1]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
entry:
|
|
%add = add nsw i80 %v, 1973801615886922022913
|
|
%gep = getelementptr inbounds i8, ptr %a, i80 %add
|
|
%c = icmp eq ptr %gep, null
|
|
br i1 %c, label %then, label %else
|
|
|
|
then:
|
|
%add.1 = add nsw i80 %v, 1973801615886922022913
|
|
%gep.1 = getelementptr inbounds i8, ptr %a, i80 %add.1
|
|
%c.1 = icmp eq ptr %gep.1, null
|
|
ret i1 %c.1
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @mul_nsw_decomp(i128 %x) {
|
|
; CHECK-LABEL: @mul_nsw_decomp(
|
|
; CHECK-NEXT: [[VAL:%.*]] = mul nsw i128 [[X:%.*]], 9223372036854775808
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i128 [[X]], [[VAL]]
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i128 [[X]], 0
|
|
; CHECK-NEXT: ret i1 [[CMP2]]
|
|
; CHECK: else:
|
|
; CHECK-NEXT: ret i1 false
|
|
;
|
|
%val = mul nsw i128 %x, 9223372036854775808
|
|
%cmp = icmp sgt i128 %x, %val
|
|
br i1 %cmp, label %then, label %else
|
|
|
|
then:
|
|
%cmp2 = icmp sgt i128 %x, 0
|
|
ret i1 %cmp2
|
|
|
|
else:
|
|
ret i1 false
|
|
}
|
|
|
|
define i1 @add_nuw_decomp_recursive() {
|
|
; CHECK-LABEL: @add_nuw_decomp_recursive(
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 -9223372036854775808, 10
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i64 [[ADD]], 10
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%add = add nuw nsw i64 -9223372036854775808, 10
|
|
%cmp = icmp uge i64 %add, 10
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @add_minus_one_decomp_recursive() {
|
|
; CHECK-LABEL: @add_minus_one_decomp_recursive(
|
|
; CHECK-NEXT: [[ADD:%.*]] = add i64 -9223372036854775808, -1
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i64 [[ADD]], 10
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%add = add i64 -9223372036854775808, -1
|
|
%cmp = icmp uge i64 %add, 10
|
|
ret i1 %cmp
|
|
}
|
|
|
|
define i1 @gep_decomp_large_index_31_bits(ptr %a) {
|
|
; CHECK-LABEL: @gep_decomp_large_index_31_bits(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 2147483646
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 2147483647
|
|
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[NE]])
|
|
; CHECK-NEXT: [[CMP_ULE:%.*]] = icmp ule ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: [[CMP_UGE:%.*]] = icmp uge ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: [[RES:%.*]] = xor i1 true, false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
entry:
|
|
%gep.1 = getelementptr inbounds i64, ptr %a, i64 2147483646
|
|
%gep.2 = getelementptr inbounds i64, ptr %a, i64 2147483647
|
|
%ne = icmp ne ptr %gep.1, %gep.2
|
|
call void @llvm.assume(i1 %ne)
|
|
%cmp.ule = icmp ule ptr %gep.1, %gep.2
|
|
%cmp.uge = icmp uge ptr %gep.1, %gep.2
|
|
%res = xor i1 true, false
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @gep_decomp_large_index_63_bits(ptr %a) {
|
|
; CHECK-LABEL: @gep_decomp_large_index_63_bits(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 9223372036854775804
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 9223372036854775805
|
|
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[NE]])
|
|
; CHECK-NEXT: [[CMP_UGE:%.*]] = icmp uge ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: [[RES:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
entry:
|
|
%gep.1 = getelementptr inbounds i64, ptr %a, i64 9223372036854775804
|
|
%gep.2 = getelementptr inbounds i64, ptr %a, i64 9223372036854775805
|
|
%ne = icmp ne ptr %gep.1, %gep.2
|
|
call void @llvm.assume(i1 %ne)
|
|
%cmp.ule = icmp ule ptr %gep.1, %gep.2
|
|
%cmp.uge = icmp uge ptr %gep.1, %gep.2
|
|
%res = xor i1 %cmp.ule, %cmp.ule
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @gep_decomp_large_index_63_bits_chained_overflow(ptr %a) {
|
|
; CHECK-LABEL: @gep_decomp_large_index_63_bits_chained_overflow(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 9223372036854775804
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds ptr, ptr [[A]], i64 1152921504606846976
|
|
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr inbounds i64, ptr [[GEP_2]], i64 1152921504606846976
|
|
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[GEP_1]], [[GEP_3]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[NE]])
|
|
; CHECK-NEXT: [[CMP_UGE:%.*]] = icmp uge ptr [[GEP_1]], [[GEP_3]]
|
|
; CHECK-NEXT: [[RES:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
entry:
|
|
%gep.1 = getelementptr inbounds i64, ptr %a, i64 9223372036854775804
|
|
%gep.2 = getelementptr inbounds ptr, ptr %a, i64 1152921504606846976
|
|
%gep.3 = getelementptr inbounds i64, ptr %gep.2, i64 1152921504606846976
|
|
%ne = icmp ne ptr %gep.1, %gep.3
|
|
call void @llvm.assume(i1 %ne)
|
|
%cmp.ule = icmp ule ptr %gep.1, %gep.3
|
|
%cmp.uge = icmp uge ptr %gep.1, %gep.3
|
|
%res = xor i1 %cmp.ule, %cmp.ule
|
|
ret i1 %res
|
|
}
|
|
|
|
%struct = type { [128 x i64], [2 x i32] }
|
|
|
|
define i1 @gep_decomp_large_index_63_bits_overflow_struct(ptr %a) {
|
|
; CHECK-LABEL: @gep_decomp_large_index_63_bits_overflow_struct(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 9223372036854775804
|
|
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds [[STRUCT:%.*]], ptr [[A]], i64 8937376004704240, i32 1, i32 1
|
|
; CHECK-NEXT: [[NE:%.*]] = icmp ne ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: call void @llvm.assume(i1 [[NE]])
|
|
; CHECK-NEXT: [[CMP_UGE:%.*]] = icmp uge ptr [[GEP_1]], [[GEP_2]]
|
|
; CHECK-NEXT: [[RES:%.*]] = xor i1 false, false
|
|
; CHECK-NEXT: ret i1 [[RES]]
|
|
;
|
|
entry:
|
|
%gep.1 = getelementptr inbounds i64, ptr %a, i64 9223372036854775804
|
|
%gep.2 = getelementptr inbounds %struct, ptr %a, i64 8937376004704240, i32 1, i32 1
|
|
%ne = icmp ne ptr %gep.1, %gep.2
|
|
call void @llvm.assume(i1 %ne)
|
|
%cmp.ule = icmp ule ptr %gep.1, %gep.2
|
|
%cmp.uge = icmp uge ptr %gep.1, %gep.2
|
|
%res = xor i1 %cmp.ule, %cmp.ule
|
|
ret i1 %res
|
|
}
|
|
|
|
define i1 @pr68751(i128 %arg) {
|
|
; CHECK-LABEL: @pr68751(
|
|
; CHECK-NEXT: [[SHL1:%.*]] = shl nuw nsw i128 [[ARG:%.*]], 32
|
|
; CHECK-NEXT: [[SHL2:%.*]] = shl nuw nsw i128 [[SHL1]], 32
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[SHL2]], 0
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%shl1 = shl nuw nsw i128 %arg, 32
|
|
%shl2 = shl nuw nsw i128 %shl1, 32
|
|
%cmp = icmp eq i128 %shl2, 0
|
|
ret i1 %cmp
|
|
}
|
|
|
|
declare void @llvm.assume(i1)
|