Chromium Code Reviews| 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..08f00fb1e94a5f4a4b96d0f2cfba6c212f682d22 |
| --- /dev/null |
| +++ b/tests_lit/llvm2ice_tests/bool-folding.ll |
| @@ -0,0 +1,204 @@ |
| +; 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: 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: call |
|
jvoung (off chromium)
2015/05/15 21:48:20
Maybe show the ; CHECK-NOT: cmp
before the call,
Jim Stichnoth
2015/05/16 17:32:51
Done. (in both "intervening" tests)
|
| +; 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 |