| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s |
| |
| declare void @a() |
| declare void @b() |
| declare void @c() |
| declare void @d() |
| |
| define void @switch_replace_default(i32 %x) { |
| ; CHECK-LABEL: define void @switch_replace_default( |
| ; CHECK-SAME: i32 [[X:%.*]]) { |
| ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3) |
| ; CHECK-NEXT: switch i32 [[X]], label %[[COMMON_RET:.*]] [ |
| ; CHECK-NEXT: i32 0, label %[[CASE0:.*]] |
| ; CHECK-NEXT: i32 1, label %[[CASE1:.*]] |
| ; CHECK-NEXT: i32 2, label %[[CASE2:.*]] |
| ; CHECK-NEXT: ], !prof [[PROF0:![0-9]+]] |
| ; CHECK: [[COMMON_RET]]: |
| ; CHECK-NEXT: ret void |
| ; CHECK: [[CASE0]]: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE1]]: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE2]]: |
| ; CHECK-NEXT: call void @c() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; |
| %min = call i32 @llvm.umin.i32(i32 %x, i32 3) |
| switch i32 %min, label %unreachable [ |
| i32 0, label %case0 |
| i32 1, label %case1 |
| i32 2, label %case2 |
| i32 3, label %case3 |
| ], !prof !0 |
| |
| case0: |
| call void @a() |
| ret void |
| |
| case1: |
| call void @b() |
| ret void |
| |
| case2: |
| call void @c() |
| ret void |
| |
| case3: |
| ret void |
| |
| unreachable: |
| unreachable |
| } |
| |
| define void @switch_replace_default_and_remove_dead_cases(i32 %x) { |
| ; CHECK-LABEL: define void @switch_replace_default_and_remove_dead_cases( |
| ; CHECK-SAME: i32 [[X:%.*]]) { |
| ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3) |
| ; CHECK-NEXT: switch i32 [[X]], label %[[COMMON_RET:.*]] [ |
| ; CHECK-NEXT: i32 2, label %[[CASE2:.*]] |
| ; CHECK-NEXT: i32 1, label %[[CASE1:.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: [[COMMON_RET]]: |
| ; CHECK-NEXT: ret void |
| ; CHECK: [[CASE1]]: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE2]]: |
| ; CHECK-NEXT: call void @c() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; |
| %min = call i32 @llvm.umin.i32(i32 %x, i32 3) |
| switch i32 %min, label %unreachable [ |
| i32 4, label %case4 |
| i32 1, label %case1 |
| i32 2, label %case2 |
| i32 3, label %case3 |
| ] |
| |
| case4: |
| call void @a() |
| ret void |
| |
| case1: |
| call void @b() |
| ret void |
| |
| case2: |
| call void @c() |
| ret void |
| |
| case3: |
| ret void |
| |
| unreachable: |
| unreachable |
| } |
| |
| define void @switch_replace_default_when_holes(i32 %x) { |
| ; CHECK-LABEL: define void @switch_replace_default_when_holes( |
| ; CHECK-SAME: i32 [[X:%.*]]) { |
| ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3) |
| ; CHECK-NEXT: switch i32 [[X]], label %[[COMMON_RET:.*]] [ |
| ; CHECK-NEXT: i32 1, label %[[CASE1:.*]] |
| ; CHECK-NEXT: i32 2, label %[[CASE2:.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: [[COMMON_RET]]: |
| ; CHECK-NEXT: ret void |
| ; CHECK: [[CASE1]]: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE2]]: |
| ; CHECK-NEXT: call void @c() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; |
| %min = call i32 @llvm.umin.i32(i32 %x, i32 3) |
| switch i32 %min, label %unreachable [ |
| i32 1, label %case1 |
| i32 2, label %case2 |
| i32 3, label %case3 |
| ] |
| |
| case1: |
| call void @b() |
| ret void |
| |
| case2: |
| call void @c() |
| ret void |
| |
| case3: |
| ret void |
| |
| unreachable: |
| unreachable |
| } |
| |
| define void @do_not_switch_replace_default(i32 %x, i32 %y) { |
| ; CHECK-LABEL: define void @do_not_switch_replace_default( |
| ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { |
| ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]]) |
| ; CHECK-NEXT: switch i32 [[MIN]], label %[[UNREACHABLE:.*]] [ |
| ; CHECK-NEXT: i32 0, label %[[CASE0:.*]] |
| ; CHECK-NEXT: i32 1, label %[[CASE1:.*]] |
| ; CHECK-NEXT: i32 2, label %[[CASE2:.*]] |
| ; CHECK-NEXT: i32 3, label %[[COMMON_RET:.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: [[COMMON_RET]]: |
| ; CHECK-NEXT: ret void |
| ; CHECK: [[CASE0]]: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE1]]: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE2]]: |
| ; CHECK-NEXT: call void @c() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[UNREACHABLE]]: |
| ; CHECK-NEXT: unreachable |
| ; |
| %min = call i32 @llvm.umin.i32(i32 %x, i32 %y) |
| switch i32 %min, label %unreachable [ |
| i32 0, label %case0 |
| i32 1, label %case1 |
| i32 2, label %case2 |
| i32 3, label %case3 |
| ] |
| |
| case0: |
| call void @a() |
| ret void |
| |
| case1: |
| call void @b() |
| ret void |
| |
| case2: |
| call void @c() |
| ret void |
| |
| case3: |
| ret void |
| |
| unreachable: |
| unreachable |
| } |
| |
| define void @do_not_replace_switch_default_but_remove_dead_cases(i32 %x) { |
| ; CHECK-LABEL: define void @do_not_replace_switch_default_but_remove_dead_cases( |
| ; CHECK-SAME: i32 [[X:%.*]]) { |
| ; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 3) |
| ; CHECK-NEXT: switch i32 [[MIN]], label %[[CASE0:.*]] [ |
| ; CHECK-NEXT: i32 3, label %[[COMMON_RET:.*]] |
| ; CHECK-NEXT: i32 1, label %[[CASE1:.*]] |
| ; CHECK-NEXT: i32 2, label %[[CASE2:.*]] |
| ; CHECK-NEXT: ] |
| ; CHECK: [[COMMON_RET]]: |
| ; CHECK-NEXT: ret void |
| ; CHECK: [[CASE0]]: |
| ; CHECK-NEXT: call void @a() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE1]]: |
| ; CHECK-NEXT: call void @b() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; CHECK: [[CASE2]]: |
| ; CHECK-NEXT: call void @c() |
| ; CHECK-NEXT: br label %[[COMMON_RET]] |
| ; |
| %min = call i32 @llvm.umin.i32(i32 %x, i32 3) |
| switch i32 %min, label %case0 [ ; default is reachable, therefore simplification not triggered |
| i32 0, label %case0 |
| i32 1, label %case1 |
| i32 2, label %case2 |
| i32 3, label %case3 |
| i32 4, label %case4 |
| ] |
| |
| case0: |
| call void @a() |
| ret void |
| |
| case1: |
| call void @b() |
| ret void |
| |
| case2: |
| call void @c() |
| ret void |
| |
| case3: |
| ret void |
| |
| case4: |
| call void @d() |
| ret void |
| |
| } |
| |
| |
| !0 = !{!"branch_weights", i32 1, i32 2, i32 3, i32 99, i32 5} |
| ;. |
| ; CHECK: [[PROF0]] = !{!"branch_weights", i32 5, i32 2, i32 3, i32 99} |
| ;. |