| Index: tests_lit/llvm2ice_tests/bool-folding.ll
|
| diff --git a/tests_lit/llvm2ice_tests/bool-folding.ll b/tests_lit/llvm2ice_tests/bool-folding.ll
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d979927c4f0c1d759f62ae380f601ba7cc6cabeb
|
| --- /dev/null
|
| +++ b/tests_lit/llvm2ice_tests/bool-folding.ll
|
| @@ -0,0 +1,206 @@
|
| +; This tests the optimization where producers and consumers of i1 (bool)
|
| +; variables are combined to implicitly use flags instead of explicitly using
|
| +; stack or register variables.
|
| +
|
| +; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 | FileCheck %s
|
| +
|
| +declare void @use_value(i32)
|
| +
|
| +; Basic cmp/branch folding.
|
| +define i32 @fold_cmp_br(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + br i1 %cmp1, label %branch1, label %branch2
|
| +branch1:
|
| + ret i32 1
|
| +branch2:
|
| + ret i32 2
|
| +}
|
| +
|
| +; CHECK-LABEL: fold_cmp_br
|
| +; CHECK: cmp
|
| +; CHECK: jge
|
| +
|
| +
|
| +; Cmp/branch folding with intervening instructions.
|
| +define i32 @fold_cmp_br_intervening_insts(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + call void @use_value(i32 %arg1)
|
| + br i1 %cmp1, label %branch1, label %branch2
|
| +branch1:
|
| + ret i32 1
|
| +branch2:
|
| + ret i32 2
|
| +}
|
| +
|
| +; CHECK-LABEL: fold_cmp_br_intervening_insts
|
| +; CHECK-NOT: cmp
|
| +; CHECK: call
|
| +; CHECK: cmp
|
| +; CHECK: jge
|
| +
|
| +
|
| +; Cmp/branch non-folding because of live-out.
|
| +define i32 @no_fold_cmp_br_liveout(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + br label %next
|
| +next:
|
| + br i1 %cmp1, label %branch1, label %branch2
|
| +branch1:
|
| + ret i32 1
|
| +branch2:
|
| + ret i32 2
|
| +}
|
| +
|
| +; CHECK-LABEL: no_fold_cmp_br_liveout
|
| +; CHECK: cmp
|
| +; CHECK: set
|
| +; CHECK: cmp
|
| +; CHECK: je
|
| +
|
| +
|
| +; Cmp/branch non-folding because of extra non-whitelisted uses.
|
| +define i32 @no_fold_cmp_br_non_whitelist(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + %result = zext i1 %cmp1 to i32
|
| + br i1 %cmp1, label %branch1, label %branch2
|
| +branch1:
|
| + ret i32 %result
|
| +branch2:
|
| + ret i32 2
|
| +}
|
| +
|
| +; CHECK-LABEL: no_fold_cmp_br_non_whitelist
|
| +; CHECK: cmp
|
| +; CHECK: set
|
| +; CHECK: movzx
|
| +; CHECK: cmp
|
| +; CHECK: je
|
| +
|
| +
|
| +; Basic cmp/select folding.
|
| +define i32 @fold_cmp_select(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + %result = select i1 %cmp1, i32 %arg1, i32 %arg2
|
| + ret i32 %result
|
| +}
|
| +
|
| +; CHECK-LABEL: fold_cmp_select
|
| +; CHECK: cmp
|
| +; CHECK: jl
|
| +; CHECK: mov
|
| +
|
| +
|
| +; 64-bit cmp/select folding.
|
| +define i64 @fold_cmp_select_64(i64 %arg1, i64 %arg2) {
|
| +entry:
|
| + %arg1_trunc = trunc i64 %arg1 to i32
|
| + %arg2_trunc = trunc i64 %arg2 to i32
|
| + %cmp1 = icmp slt i32 %arg1_trunc, %arg2_trunc
|
| + %result = select i1 %cmp1, i64 %arg1, i64 %arg2
|
| + ret i64 %result
|
| +}
|
| +
|
| +; CHECK-LABEL: fold_cmp_select_64
|
| +; CHECK: cmp
|
| +; CHECK: jl
|
| +; CHECK: mov
|
| +; CHECK: mov
|
| +
|
| +
|
| +; Cmp/select folding with intervening instructions.
|
| +define i32 @fold_cmp_select_intervening_insts(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + call void @use_value(i32 %arg1)
|
| + %result = select i1 %cmp1, i32 %arg1, i32 %arg2
|
| + ret i32 %result
|
| +}
|
| +
|
| +; CHECK-LABEL: fold_cmp_select_intervening_insts
|
| +; CHECK-NOT: cmp
|
| +; CHECK: call
|
| +; CHECK: cmp
|
| +; CHECK: jl
|
| +; CHECK: mov
|
| +
|
| +
|
| +; Cmp/multi-select folding.
|
| +define i32 @fold_cmp_select_multi(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + %a = select i1 %cmp1, i32 %arg1, i32 %arg2
|
| + %b = select i1 %cmp1, i32 %arg2, i32 %arg1
|
| + %c = select i1 %cmp1, i32 123, i32 %arg1
|
| + %partial = add i32 %a, %b
|
| + %result = add i32 %partial, %c
|
| + ret i32 %result
|
| +}
|
| +
|
| +; CHECK-LABEL: fold_cmp_select_multi
|
| +; CHECK: cmp
|
| +; CHECK: jl
|
| +; CHECK: cmp
|
| +; CHECK: jl
|
| +; CHECK: cmp
|
| +; CHECK: jl
|
| +; CHECK: add
|
| +; CHECK: add
|
| +
|
| +
|
| +; Cmp/multi-select non-folding because of live-out.
|
| +define i32 @no_fold_cmp_select_multi_liveout(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + %a = select i1 %cmp1, i32 %arg1, i32 %arg2
|
| + %b = select i1 %cmp1, i32 %arg2, i32 %arg1
|
| + br label %next
|
| +next:
|
| + %c = select i1 %cmp1, i32 123, i32 %arg1
|
| + %partial = add i32 %a, %b
|
| + %result = add i32 %partial, %c
|
| + ret i32 %result
|
| +}
|
| +
|
| +; CHECK-LABEL: no_fold_cmp_select_multi_liveout
|
| +; CHECK: set
|
| +; CHECK: cmp
|
| +; CHECK: jne
|
| +; CHECK: cmp
|
| +; CHECK: jne
|
| +; CHECK: cmp
|
| +; CHECK: jne
|
| +; CHECK: add
|
| +; CHECK: add
|
| +
|
| +
|
| +; Cmp/multi-select non-folding because of extra non-whitelisted uses.
|
| +define i32 @no_fold_cmp_select_multi_non_whitelist(i32 %arg1, i32 %arg2) {
|
| +entry:
|
| + %cmp1 = icmp slt i32 %arg1, %arg2
|
| + %a = select i1 %cmp1, i32 %arg1, i32 %arg2
|
| + %b = select i1 %cmp1, i32 %arg2, i32 %arg1
|
| + %c = select i1 %cmp1, i32 123, i32 %arg1
|
| + %ext = zext i1 %cmp1 to i32
|
| + %partial1 = add i32 %a, %b
|
| + %partial2 = add i32 %partial1, %c
|
| + %result = add i32 %partial2, %ext
|
| + ret i32 %result
|
| +}
|
| +
|
| +; CHECK-LABEL: no_fold_cmp_select_multi_non_whitelist
|
| +; CHECK: set
|
| +; CHECK: cmp
|
| +; CHECK: jne
|
| +; CHECK: cmp
|
| +; CHECK: jne
|
| +; CHECK: cmp
|
| +; CHECK: jne
|
| +; CHECK: movzx
|
| +; CHECK: add
|
| +; CHECK: add
|
| +; CHECK: add
|
|
|