| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | |
| ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s | |
| ; Test that we can thread a simple known condition through switch statements. | |
| declare void @foo1() | |
| declare void @foo2() | |
| declare void @DEAD() | |
| define void @test1(i32 %V) { | |
| ; CHECK-LABEL: @test1( | |
| ; CHECK-NEXT: switch i32 [[V:%.*]], label [[A:%.*]] [ | |
| ; CHECK-NEXT: i32 4, label [[T:%.*]] | |
| ; CHECK-NEXT: i32 17, label [[COMMON_RET:%.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: T: | |
| ; CHECK-NEXT: call void @foo1() | |
| ; CHECK-NEXT: call void @foo2() | |
| ; CHECK-NEXT: br label [[COMMON_RET]] | |
| ; CHECK: A: | |
| ; CHECK-NEXT: call void @foo1() | |
| ; CHECK-NEXT: br label [[COMMON_RET]] | |
| ; CHECK: common.ret: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| switch i32 %V, label %A [ | |
| i32 4, label %T | |
| i32 17, label %Done | |
| i32 1234, label %A | |
| ] | |
| ;; V == 4 if we get here. | |
| T: ; preds = %0 | |
| call void @foo1( ) | |
| ;; This switch is always statically determined. | |
| switch i32 %V, label %A2 [ | |
| i32 4, label %B | |
| i32 17, label %C | |
| i32 42, label %C | |
| ] | |
| A2: ; preds = %T | |
| call void @DEAD( ) | |
| call void @DEAD( ) | |
| ;; always true | |
| %cond2 = icmp eq i32 %V, 4 ; <i1> [#uses=1] | |
| br i1 %cond2, label %Done, label %C | |
| A: ; preds = %0, %0 | |
| call void @foo1( ) | |
| ;; always true | |
| %cond = icmp ne i32 %V, 4 ; <i1> [#uses=1] | |
| br i1 %cond, label %Done, label %C | |
| Done: ; preds = %B, %A, %A2, %0 | |
| ret void | |
| B: ; preds = %T | |
| call void @foo2( ) | |
| ;; always true | |
| %cond3 = icmp eq i32 %V, 4 ; <i1> [#uses=1] | |
| br i1 %cond3, label %Done, label %C | |
| C: ; preds = %B, %A, %A2, %T, %T | |
| call void @DEAD( ) | |
| ret void | |
| } | |
| define void @test2(i32 %V) { | |
| ; CHECK-LABEL: @test2( | |
| ; CHECK-NEXT: switch i32 [[V:%.*]], label [[A:%.*]] [ | |
| ; CHECK-NEXT: i32 4, label [[T:%.*]] | |
| ; CHECK-NEXT: i32 17, label [[D:%.*]] | |
| ; CHECK-NEXT: i32 1234, label [[COMMON_RET:%.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: A: | |
| ; CHECK-NEXT: call void @foo1() | |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V]], 42 | |
| ; CHECK-NEXT: br i1 [[COND]], label [[D]], label [[COMMON_RET]] | |
| ; CHECK: common.ret: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: T: | |
| ; CHECK-NEXT: call void @foo1() | |
| ; CHECK-NEXT: call void @foo1() | |
| ; CHECK-NEXT: br label [[COMMON_RET]] | |
| ; CHECK: D: | |
| ; CHECK-NEXT: call void @foo1() | |
| ; CHECK-NEXT: br label [[COMMON_RET]] | |
| ; | |
| switch i32 %V, label %A [ | |
| i32 4, label %T | |
| i32 17, label %D | |
| i32 1234, label %E | |
| ] | |
| ;; V != 4, 17, 1234 here. | |
| A: ; preds = %0 | |
| call void @foo1( ) | |
| ;; This switch is always statically determined. | |
| switch i32 %V, label %E [ | |
| i32 4, label %C | |
| i32 17, label %C | |
| i32 42, label %D | |
| ] | |
| ;; unreacahble. | |
| C: ; preds = %A, %A | |
| call void @DEAD( ) | |
| ret void | |
| T: ; preds = %0 | |
| call void @foo1( ) | |
| call void @foo1( ) | |
| ret void | |
| D: ; preds = %A, %0 | |
| call void @foo1( ) | |
| ret void | |
| E: ; preds = %A, %0 | |
| ret void | |
| } | |