
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
811 lines
27 KiB
LLVM
811 lines
27 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_or_ule(i4 %x, i4 %y, i4 %z, i4 %a) {
|
|
; CHECK-LABEL: @test_or_ule(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_1]], [[C_2]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 [[X]], [[Z]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 [[X]], [[A:%.*]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i4 %x, %y
|
|
%c.2 = icmp ule i4 %y, %z
|
|
%or = or i1 %c.1, %c.2
|
|
br i1 %or, label %bb1, label %exit
|
|
|
|
bb1:
|
|
%c.3 = icmp ule i4 %x, %z
|
|
call void @use(i1 %c.3)
|
|
|
|
%c.4 = icmp ule i4 %x, %a
|
|
call void @use(i1 %c.4)
|
|
|
|
ret void
|
|
|
|
exit:
|
|
%f.1 = icmp ule i4 %x, %z
|
|
call void @use(i1 %f.1)
|
|
|
|
%c.5 = icmp ule i4 %x, %a
|
|
call void @use(i1 %c.5)
|
|
|
|
%t.1 = icmp ugt i4 %y, %z
|
|
call void @use(i1 %t.1)
|
|
|
|
%t.2 = icmp ugt i4 %x, %y
|
|
call void @use(i1 %t.2)
|
|
|
|
%t.3 = icmp ugt i4 %x, %z
|
|
call void @use(i1 %t.3)
|
|
|
|
ret void
|
|
}
|
|
|
|
; The result of test_or_ule and test_or_select_ule should be same
|
|
define void @test_or_select_ule(i4 %x, i4 %y, i4 %z, i4 %a) {
|
|
; CHECK-LABEL: @test_or_select_ule(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[OR:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]]
|
|
; CHECK-NEXT: br i1 [[OR]], label [[BB1:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 [[X]], [[Z]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 [[X]], [[A:%.*]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i4 %x, %y
|
|
%c.2 = icmp ule i4 %y, %z
|
|
%or = select i1 %c.1, i1 true, i1 %c.2
|
|
br i1 %or, label %bb1, label %exit
|
|
|
|
bb1:
|
|
%c.3 = icmp ule i4 %x, %z
|
|
call void @use(i1 %c.3)
|
|
|
|
%c.4 = icmp ule i4 %x, %a
|
|
call void @use(i1 %c.4)
|
|
|
|
ret void
|
|
|
|
exit:
|
|
%f.1 = icmp ule i4 %x, %z
|
|
call void @use(i1 %f.1)
|
|
|
|
%c.5 = icmp ule i4 %x, %a
|
|
call void @use(i1 %c.5)
|
|
|
|
%t.1 = icmp ugt i4 %y, %z
|
|
call void @use(i1 %t.1)
|
|
|
|
%t.2 = icmp ugt i4 %x, %y
|
|
call void @use(i1 %t.2)
|
|
|
|
%t.3 = icmp ugt i4 %x, %z
|
|
call void @use(i1 %t.3)
|
|
|
|
ret void
|
|
}
|
|
|
|
define i1 @test_or_chain_ule_1(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) {
|
|
; CHECK-LABEL: @test_or_chain_ule_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]]
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
|
|
; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[OR_1]], [[C_3]]
|
|
; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[C_4]], [[OR_2]]
|
|
; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
|
|
; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
|
|
; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true
|
|
; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true
|
|
; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], true
|
|
; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], true
|
|
; CHECK-NEXT: [[RES_8:%.*]] = xor i1 [[RES_7]], true
|
|
; CHECK-NEXT: [[RES_9:%.*]] = xor i1 [[RES_8]], true
|
|
; CHECK-NEXT: ret i1 [[RES_9]]
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i4 %x, %y
|
|
%c.2 = icmp ule i4 %y, %z
|
|
%c.3 = icmp ule i4 2, %x
|
|
%c.4 = icmp ule i4 2, %a
|
|
%or.1 = or i1 %c.1, %c.2
|
|
%or.2 = or i1 %or.1, %c.3
|
|
%or.3 = or i1 %c.4, %or.2
|
|
br i1 %or.3, label %bb1, label %exit
|
|
|
|
bb1:
|
|
%c.5 = icmp ule i4 %x, %z
|
|
%c.6 = icmp ule i4 %x, %a
|
|
%res.1 = xor i1 %c.5, %c.6
|
|
%c.7 = icmp ule i4 2, %x
|
|
%res.2 = xor i1 %res.1, %c.7
|
|
ret i1 %res.2
|
|
|
|
exit:
|
|
%f.1 = icmp ule i4 %x, %z
|
|
%f.2 = icmp ule i4 2, %x
|
|
%res.3 = xor i1 %f.1, %f.2
|
|
|
|
%t.1 = icmp ugt i4 %y, %z
|
|
%res.4 = xor i1 %res.3, %t.1
|
|
|
|
%t.2 = icmp ugt i4 %x, %y
|
|
%res.5 = xor i1 %res.4, %t.2
|
|
|
|
%t.3 = icmp ugt i4 %x, %z
|
|
%res.6 = xor i1 %res.5, %t.3
|
|
|
|
%t.4 = icmp ugt i4 2, %a
|
|
%res.7 = xor i1 %res.6, %t.4
|
|
|
|
%c.8 = icmp ule i4 %x, %a
|
|
%res.8 = xor i1 %res.7, %c.8
|
|
|
|
%c.9 = icmp ule i4 %x, %b
|
|
%res.9 = xor i1 %res.8, %c.9
|
|
|
|
ret i1 %res.9
|
|
}
|
|
|
|
; Same as @test_or_chain_ule_1, but with the `or`s ordered differently.
|
|
define i1 @test_or_chain_ule_2(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) {
|
|
; CHECK-LABEL: @test_or_chain_ule_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]]
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
|
|
; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[C_3]], [[C_4]]
|
|
; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[OR_1]], [[OR_2]]
|
|
; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
|
|
; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
|
|
; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, true
|
|
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true
|
|
; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true
|
|
; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], true
|
|
; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], true
|
|
; CHECK-NEXT: [[RES_8:%.*]] = xor i1 [[RES_7]], true
|
|
; CHECK-NEXT: [[RES_9:%.*]] = xor i1 [[RES_8]], true
|
|
; CHECK-NEXT: ret i1 [[RES_9]]
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i4 %x, %y
|
|
%c.2 = icmp ule i4 %y, %z
|
|
%c.3 = icmp ule i4 2, %x
|
|
%c.4 = icmp ule i4 2, %a
|
|
%or.1 = or i1 %c.1, %c.2
|
|
%or.2 = or i1 %c.3, %c.4
|
|
%or.3 = or i1 %or.1, %or.2
|
|
br i1 %or.3, label %bb1, label %exit
|
|
|
|
bb1:
|
|
%c.5 = icmp ule i4 %x, %z
|
|
%c.6 = icmp ule i4 %x, %a
|
|
%res.1 = xor i1 %c.5, %c.6
|
|
%c.7 = icmp ule i4 2, %x
|
|
%res.2 = xor i1 %res.1, %c.7
|
|
ret i1 %res.2
|
|
|
|
exit:
|
|
%f.1 = icmp ule i4 %x, %z
|
|
%f.2 = icmp ule i4 2, %x
|
|
%res.3 = xor i1 %f.1, %f.2
|
|
|
|
%t.1 = icmp ugt i4 %y, %z
|
|
%res.4 = xor i1 %res.3, %t.1
|
|
|
|
%t.2 = icmp ugt i4 %x, %y
|
|
%res.5 = xor i1 %res.4, %t.2
|
|
|
|
%t.3 = icmp ugt i4 %x, %z
|
|
%res.6 = xor i1 %res.5, %t.3
|
|
|
|
%t.4 = icmp ugt i4 2, %a
|
|
%res.7 = xor i1 %res.6, %t.4
|
|
|
|
%c.8 = icmp ule i4 %x, %a
|
|
%res.8 = xor i1 %res.7, %c.8
|
|
|
|
%c.9 = icmp ule i4 %x, %b
|
|
%res.9 = xor i1 %res.8, %c.9
|
|
|
|
ret i1 %res.9
|
|
}
|
|
|
|
declare i1 @cond() readnone
|
|
|
|
; Test with `or` chain that also contains instructions other than `or` and `icmp`.
|
|
define i1 @test_or_chain_with_other_conds_ule(i4 %x, i4 %y, i4 %z, i4 %a, i1 %arg.c) {
|
|
; CHECK-LABEL: @test_or_chain_with_other_conds_ule(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond()
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
|
|
; CHECK-NEXT: [[OR_2:%.*]] = or i1 [[C_3]], [[OR_1]]
|
|
; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[OR_2]], [[ARG_C:%.*]]
|
|
; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
|
|
; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A:%.*]]
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
|
|
; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 false, true
|
|
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true
|
|
; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true
|
|
; CHECK-NEXT: [[C_8:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_8]]
|
|
; CHECK-NEXT: ret i1 [[RES_6]]
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i4 %x, %y
|
|
%c.2 = icmp ule i4 %y, %z
|
|
%c.3 = call i1 @cond()
|
|
%or.1 = or i1 %c.1, %c.2
|
|
%or.2 = or i1 %c.3, %or.1
|
|
%or.3 = or i1 %or.2, %arg.c
|
|
br i1 %or.3, label %bb1, label %exit
|
|
|
|
bb1:
|
|
%c.5 = icmp ule i4 %x, %z
|
|
%c.6 = icmp ule i4 %x, %a
|
|
%res.1 = xor i1 %c.5, %c.6
|
|
%c.7 = icmp ule i4 2, %x
|
|
%res.2 = xor i1 %res.1, %c.7
|
|
ret i1 %res.2
|
|
|
|
exit:
|
|
%f.1 = icmp ule i4 %x, %z
|
|
|
|
%t.1 = icmp ugt i4 %y, %z
|
|
%res.3 = xor i1 %f.1, %t.1
|
|
|
|
%t.2 = icmp ugt i4 %x, %y
|
|
%res.4 = xor i1 %res.3, %t.2
|
|
|
|
%t.3 = icmp ugt i4 %x, %z
|
|
%res.5 = xor i1 %res.4, %t.3
|
|
|
|
%c.8 = icmp ule i4 %x, %a
|
|
%res.6 = xor i1 %res.5, %c.8
|
|
|
|
ret i1 %res.6
|
|
}
|
|
|
|
define i1 @test_or_chain_with_and_ule(i4 %x, i4 %y, i4 %z, i4 %a, i4 %b) {
|
|
; CHECK-LABEL: @test_or_chain_with_and_ule(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp ule i4 [[X:%.*]], [[Y:%.*]]
|
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ule i4 [[Y]], [[Z:%.*]]
|
|
; CHECK-NEXT: [[C_3:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 2, [[A:%.*]]
|
|
; CHECK-NEXT: [[OR_1:%.*]] = or i1 [[C_1]], [[C_2]]
|
|
; CHECK-NEXT: [[AND_2:%.*]] = and i1 [[C_3]], [[C_4]]
|
|
; CHECK-NEXT: [[OR_3:%.*]] = or i1 [[OR_1]], [[AND_2]]
|
|
; CHECK-NEXT: br i1 [[OR_3]], label [[BB1:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: bb1:
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[Z]]
|
|
; CHECK-NEXT: [[C_6:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_5]], [[C_6]]
|
|
; CHECK-NEXT: [[C_7:%.*]] = icmp ule i4 2, [[X]]
|
|
; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[C_7]]
|
|
; CHECK-NEXT: ret i1 [[RES_2]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES_3:%.*]] = xor i1 false, true
|
|
; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], true
|
|
; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_4]], true
|
|
; CHECK-NEXT: [[C_8:%.*]] = icmp ule i4 [[X]], [[A]]
|
|
; CHECK-NEXT: [[RES_6:%.*]] = xor i1 [[RES_5]], [[C_8]]
|
|
; CHECK-NEXT: [[C_9:%.*]] = icmp ule i4 [[X]], [[B:%.*]]
|
|
; CHECK-NEXT: [[RES_7:%.*]] = xor i1 [[RES_6]], [[C_9]]
|
|
; CHECK-NEXT: [[RES_8:%.*]] = xor i1 [[RES_7]], true
|
|
; CHECK-NEXT: [[C_11:%.*]] = icmp ugt i4 2, [[A]]
|
|
; CHECK-NEXT: [[RES_9:%.*]] = xor i1 [[RES_8]], [[C_11]]
|
|
; CHECK-NEXT: ret i1 [[RES_9]]
|
|
;
|
|
entry:
|
|
%c.1 = icmp ule i4 %x, %y
|
|
%c.2 = icmp ule i4 %y, %z
|
|
%c.3 = icmp ule i4 2, %x
|
|
%c.4 = icmp ule i4 2, %a
|
|
%or.1 = or i1 %c.1, %c.2
|
|
%and.2 = and i1 %c.3, %c.4
|
|
%or.3 = or i1 %or.1, %and.2
|
|
br i1 %or.3, label %bb1, label %exit
|
|
|
|
bb1:
|
|
%c.5 = icmp ule i4 %x, %z
|
|
%c.6 = icmp ule i4 %x, %a
|
|
%res.1 = xor i1 %c.5, %c.6
|
|
%c.7 = icmp ule i4 2, %x
|
|
%res.2 = xor i1 %res.1, %c.7
|
|
ret i1 %res.2
|
|
|
|
exit:
|
|
%f.1 = icmp ule i4 %x, %z
|
|
%t.1 = icmp ugt i4 %y, %z
|
|
%res.3 = xor i1 %f.1, %t.1
|
|
|
|
%t.2 = icmp ugt i4 %x, %y
|
|
%res.4 = xor i1 %res.3, %t.2
|
|
|
|
%t.3 = icmp ugt i4 %x, %z
|
|
%res.5 = xor i1 %res.4, %t.3
|
|
|
|
%c.8 = icmp ule i4 %x, %a
|
|
%res.6 = xor i1 %res.5, %c.8
|
|
|
|
%c.9 = icmp ule i4 %x, %b
|
|
%res.7 = xor i1 %res.6, %c.9
|
|
|
|
%c.10 = icmp ule i4 2, %x
|
|
%res.8 = xor i1 %res.7, %c.10
|
|
|
|
%c.11 = icmp ugt i4 2, %a
|
|
%res.9 = xor i1 %res.8, %c.11
|
|
|
|
ret i1 %res.9
|
|
}
|
|
|
|
define void @test_or_as_add_ult(i8 %init_val, i8 %high) {
|
|
; CHECK-LABEL: @test_or_as_add_ult(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
|
|
; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[F_0:%.*]] = icmp ult i8 [[START]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_0]])
|
|
; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: [[F_1:%.*]] = icmp ult i8 [[I_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
|
; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: [[F_2:%.*]] = icmp ult i8 [[I_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: end:
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[START_4]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start = shl nuw nsw i8 %init_val, 2
|
|
%start.plus.3 = add nuw i8 %start, 3
|
|
%c.1 = icmp uge i8 %start.plus.3, %high
|
|
br i1 %c.1, label %then, label %end
|
|
|
|
then: ; preds = %entry
|
|
%f.0 = icmp ult i8 %start, %high
|
|
call void @use(i1 %f.0)
|
|
%i.1 = or disjoint i8 %start, 1
|
|
%f.1 = icmp ult i8 %i.1, %high
|
|
call void @use(i1 %f.1)
|
|
%i.2 = or disjoint i8 %start, 2
|
|
%f.2 = icmp ult i8 %i.2, %high
|
|
call void @use(i1 %f.2)
|
|
ret void
|
|
|
|
end: ; preds = %entry
|
|
%t.0 = icmp ult i8 %start, %high
|
|
call void @use(i1 %t.0)
|
|
%start.1 = or disjoint i8 %start, 1
|
|
%t.1 = icmp ult i8 %start.1, %high
|
|
call void @use(i1 %t.1)
|
|
%start.2 = or disjoint i8 %start, 2
|
|
%t.2 = icmp ult i8 %start.2, %high
|
|
call void @use(i1 %t.2)
|
|
%start.3 = or disjoint i8 %start, 3
|
|
%t.3 = icmp ult i8 %start.3, %high
|
|
call void @use(i1 %t.3)
|
|
%start.4 = or i8 %start, 4
|
|
%c.4 = icmp ult i8 %start.4, %high
|
|
call void @use(i1 %c.4)
|
|
ret void
|
|
}
|
|
|
|
define void @test_or_as_add_ule(i8 %init_val, i8 %high) {
|
|
; CHECK-LABEL: @test_or_as_add_ule(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
|
|
; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[F_0:%.*]] = icmp ule i8 [[START]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_0]])
|
|
; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: [[F_1:%.*]] = icmp ule i8 [[I_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
|
; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: [[F_2:%.*]] = icmp ule i8 [[I_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: end:
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3
|
|
; CHECK-NEXT: call void @use(i1 true)
|
|
; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4
|
|
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i8 [[START_4]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_4]])
|
|
; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i8 [[START_5]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start = shl nuw nsw i8 %init_val, 2
|
|
%start.plus.3 = add nuw i8 %start, 3
|
|
%c.1 = icmp uge i8 %start.plus.3, %high
|
|
br i1 %c.1, label %then, label %end
|
|
|
|
then: ; preds = %entry
|
|
%f.0 = icmp ule i8 %start, %high
|
|
call void @use(i1 %f.0)
|
|
%i.1 = or disjoint i8 %start, 1
|
|
%f.1 = icmp ule i8 %i.1, %high
|
|
call void @use(i1 %f.1)
|
|
%i.2 = or disjoint i8 %start, 2
|
|
%f.2 = icmp ule i8 %i.2, %high
|
|
call void @use(i1 %f.2)
|
|
ret void
|
|
|
|
end: ; preds = %entry
|
|
%t.0 = icmp ule i8 %start, %high
|
|
call void @use(i1 %t.0)
|
|
%start.1 = or disjoint i8 %start, 1
|
|
%t.1 = icmp ule i8 %start.1, %high
|
|
call void @use(i1 %t.1)
|
|
%start.2 = or disjoint i8 %start, 2
|
|
%t.2 = icmp ule i8 %start.2, %high
|
|
call void @use(i1 %t.2)
|
|
%start.3 = or disjoint i8 %start, 3
|
|
%t.3 = icmp ule i8 %start.3, %high
|
|
call void @use(i1 %t.3)
|
|
%start.4 = or i8 %start, 4
|
|
%t.4 = icmp ule i8 %start.4, %high
|
|
call void @use(i1 %t.4)
|
|
%start.5 = or i8 %start, 5
|
|
%c.5 = icmp ule i8 %start.5, %high
|
|
call void @use(i1 %c.5)
|
|
|
|
ret void
|
|
}
|
|
|
|
define void @test_or_as_add_ugt(i8 %init_val, i8 %high) {
|
|
; CHECK-LABEL: @test_or_as_add_ugt(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
|
|
; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[T_0:%.*]] = icmp ugt i8 [[START]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_0]])
|
|
; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[I_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
|
; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: [[T_2:%.*]] = icmp ugt i8 [[I_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: end:
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4
|
|
; CHECK-NEXT: [[F_4:%.*]] = icmp ugt i8 [[START_4]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_4]])
|
|
; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i8 [[START_5]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start = shl nuw nsw i8 %init_val, 2
|
|
%start.plus.3 = add nuw i8 %start, 3
|
|
%c.1 = icmp uge i8 %start.plus.3, %high
|
|
br i1 %c.1, label %then, label %end
|
|
|
|
then: ; preds = %entry
|
|
%t.0 = icmp ugt i8 %start, %high
|
|
call void @use(i1 %t.0)
|
|
%i.1 = or disjoint i8 %start, 1
|
|
%t.1 = icmp ugt i8 %i.1, %high
|
|
call void @use(i1 %t.1)
|
|
%i.2 = or disjoint i8 %start, 2
|
|
%t.2 = icmp ugt i8 %i.2, %high
|
|
call void @use(i1 %t.2)
|
|
ret void
|
|
|
|
end: ; preds = %entry
|
|
%f.0 = icmp ugt i8 %start, %high
|
|
call void @use(i1 %f.0)
|
|
%start.1 = or disjoint i8 %start, 1
|
|
%f.1 = icmp ugt i8 %start.1, %high
|
|
call void @use(i1 %f.1)
|
|
%start.2 = or disjoint i8 %start, 2
|
|
%f.2 = icmp ugt i8 %start.2, %high
|
|
call void @use(i1 %f.2)
|
|
%start.3 = or disjoint i8 %start, 3
|
|
%f.3 = icmp ugt i8 %start.3, %high
|
|
call void @use(i1 %f.3)
|
|
%start.4 = or i8 %start, 4
|
|
%f.4 = icmp ugt i8 %start.4, %high
|
|
call void @use(i1 %f.4)
|
|
%start.5 = or i8 %start, 5
|
|
%c.5 = icmp ugt i8 %start.5, %high
|
|
call void @use(i1 %c.5)
|
|
ret void
|
|
}
|
|
|
|
define void @test_or_as_add_uge(i8 %init_val, i8 %high) {
|
|
; CHECK-LABEL: @test_or_as_add_uge(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START:%.*]] = shl nuw nsw i8 [[INIT_VAL:%.*]], 2
|
|
; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START]], 3
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[T_0:%.*]] = icmp ugt i8 [[START]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_0]])
|
|
; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
|
; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: end:
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start = shl nuw nsw i8 %init_val, 2
|
|
%start.plus.3 = add nuw i8 %start, 3
|
|
%c.1 = icmp uge i8 %start.plus.3, %high
|
|
br i1 %c.1, label %then, label %end
|
|
|
|
then: ; preds = %entry
|
|
%t.0 = icmp ugt i8 %start, %high
|
|
call void @use(i1 %t.0)
|
|
%i.1 = or disjoint i8 %start, 1
|
|
%t.1 = icmp uge i8 %i.1, %high
|
|
call void @use(i1 %t.1)
|
|
%i.2 = or disjoint i8 %start, 2
|
|
%t.2 = icmp uge i8 %i.2, %high
|
|
call void @use(i1 %t.2)
|
|
ret void
|
|
|
|
end: ; preds = %entry
|
|
%f.0 = icmp ugt i8 %start, %high
|
|
call void @use(i1 %f.0)
|
|
%start.1 = or disjoint i8 %start, 1
|
|
%f.1 = icmp uge i8 %start.1, %high
|
|
call void @use(i1 %f.1)
|
|
%start.2 = or disjoint i8 %start, 2
|
|
%f.2 = icmp uge i8 %start.2, %high
|
|
call void @use(i1 %f.2)
|
|
%start.3 = or disjoint i8 %start, 3
|
|
%f.3 = icmp uge i8 %start.3, %high
|
|
call void @use(i1 %f.3)
|
|
%start.4 = or i8 %start, 4
|
|
%c.4 = icmp uge i8 %start.4, %high
|
|
call void @use(i1 %c.4)
|
|
%start.5 = or i8 %start, 5
|
|
%c.5 = icmp uge i8 %start.5, %high
|
|
call void @use(i1 %c.5)
|
|
ret void
|
|
}
|
|
|
|
define void @test_not_decompose(i8 %start, i8 %high) {
|
|
; CHECK-LABEL: @test_not_decompose(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START:%.*]], 3
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[I_1:%.*]] = or i8 [[START]], 1
|
|
; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
|
; CHECK-NEXT: [[I_2:%.*]] = or i8 [[START]], 2
|
|
; CHECK-NEXT: [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: end:
|
|
; CHECK-NEXT: [[START_1:%.*]] = or i8 [[START]], 1
|
|
; CHECK-NEXT: [[F_1:%.*]] = icmp uge i8 [[START_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_1]])
|
|
; CHECK-NEXT: [[START_2:%.*]] = or i8 [[START]], 2
|
|
; CHECK-NEXT: [[F_2:%.*]] = icmp uge i8 [[START_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_2]])
|
|
; CHECK-NEXT: [[START_3:%.*]] = or i8 [[START]], 3
|
|
; CHECK-NEXT: [[F_3:%.*]] = icmp uge i8 [[START_3]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[F_3]])
|
|
; CHECK-NEXT: [[START_4:%.*]] = or i8 [[START]], 4
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: [[START_5:%.*]] = or i8 [[START]], 5
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start.plus.3 = add nuw i8 %start, 3
|
|
%c.1 = icmp uge i8 %start.plus.3, %high
|
|
br i1 %c.1, label %then, label %end
|
|
|
|
then: ; preds = %entry
|
|
%i.1 = or i8 %start, 1
|
|
%t.1 = icmp uge i8 %i.1, %high
|
|
call void @use(i1 %t.1)
|
|
%i.2 = or i8 %start, 2
|
|
%t.2 = icmp uge i8 %i.2, %high
|
|
call void @use(i1 %t.2)
|
|
ret void
|
|
|
|
end: ; preds = %entry
|
|
%start.1 = or i8 %start, 1
|
|
%f.1 = icmp uge i8 %start.1, %high
|
|
call void @use(i1 %f.1)
|
|
%start.2 = or i8 %start, 2
|
|
%f.2 = icmp uge i8 %start.2, %high
|
|
call void @use(i1 %f.2)
|
|
%start.3 = or i8 %start, 3
|
|
%f.3 = icmp uge i8 %start.3, %high
|
|
call void @use(i1 %f.3)
|
|
%start.4 = or i8 %start, 4
|
|
%c.4 = icmp uge i8 %start.4, %high
|
|
call void @use(i1 %c.4)
|
|
%start.5 = or i8 %start, 5
|
|
%c.5 = icmp uge i8 %start.5, %high
|
|
call void @use(i1 %c.5)
|
|
|
|
ret void
|
|
}
|
|
|
|
; Nothing in the IR implies the disjoint flag, but we can still use it
|
|
; to decompose into an add.
|
|
define void @test_decompose_explicit_disjoint(i8 %start, i8 %high) {
|
|
; CHECK-LABEL: @test_decompose_explicit_disjoint(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PLUS_3:%.*]] = add nuw i8 [[START:%.*]], 3
|
|
; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[START_PLUS_3]], [[HIGH:%.*]]
|
|
; CHECK-NEXT: br i1 [[C_1]], label [[THEN:%.*]], label [[END:%.*]]
|
|
; CHECK: then:
|
|
; CHECK-NEXT: [[I_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[I_1]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
|
; CHECK-NEXT: [[I_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: [[T_2:%.*]] = icmp uge i8 [[I_2]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
|
; CHECK-NEXT: ret void
|
|
; CHECK: end:
|
|
; CHECK-NEXT: [[START_1:%.*]] = or disjoint i8 [[START]], 1
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_2:%.*]] = or disjoint i8 [[START]], 2
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_3:%.*]] = or disjoint i8 [[START]], 3
|
|
; CHECK-NEXT: call void @use(i1 false)
|
|
; CHECK-NEXT: [[START_4:%.*]] = or disjoint i8 [[START]], 4
|
|
; CHECK-NEXT: [[C_4:%.*]] = icmp uge i8 [[START_4]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
|
; CHECK-NEXT: [[START_5:%.*]] = or disjoint i8 [[START]], 5
|
|
; CHECK-NEXT: [[C_5:%.*]] = icmp uge i8 [[START_5]], [[HIGH]]
|
|
; CHECK-NEXT: call void @use(i1 [[C_5]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%start.plus.3 = add nuw i8 %start, 3
|
|
%c.1 = icmp uge i8 %start.plus.3, %high
|
|
br i1 %c.1, label %then, label %end
|
|
|
|
then: ; preds = %entry
|
|
%i.1 = or disjoint i8 %start, 1
|
|
%t.1 = icmp uge i8 %i.1, %high
|
|
call void @use(i1 %t.1)
|
|
%i.2 = or disjoint i8 %start, 2
|
|
%t.2 = icmp uge i8 %i.2, %high
|
|
call void @use(i1 %t.2)
|
|
ret void
|
|
|
|
end: ; preds = %entry
|
|
%start.1 = or disjoint i8 %start, 1
|
|
%f.1 = icmp uge i8 %start.1, %high
|
|
call void @use(i1 %f.1)
|
|
%start.2 = or disjoint i8 %start, 2
|
|
%f.2 = icmp uge i8 %start.2, %high
|
|
call void @use(i1 %f.2)
|
|
%start.3 = or disjoint i8 %start, 3
|
|
%f.3 = icmp uge i8 %start.3, %high
|
|
call void @use(i1 %f.3)
|
|
%start.4 = or disjoint i8 %start, 4
|
|
%c.4 = icmp uge i8 %start.4, %high
|
|
call void @use(i1 %c.4)
|
|
%start.5 = or disjoint i8 %start, 5
|
|
%c.5 = icmp uge i8 %start.5, %high
|
|
call void @use(i1 %c.5)
|
|
|
|
ret void
|
|
}
|