xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll (revision 07b9d231ff9baa6473b0dd588a3ce5330d3e4871)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes='simplifycfg<hoist-common-insts;no-sink-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
3
4define i1 @common_instr_with_unreachable(i64 %a, i64 %b, i64 %c) {
5; CHECK-LABEL: @common_instr_with_unreachable(
6; CHECK-NEXT:  start:
7; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
8; CHECK-NEXT:    ret i1 [[TMP0]]
9;
10start:
11  switch i64 %a, label %unreachable [
12  i64 0, label %bb0
13  i64 1, label %bb1
14  i64 2, label %bb2
15  ]
16
17unreachable:
18  unreachable
19
20bb0:                                              ; preds = %start
21  %0 = icmp eq i64 %b, %c
22  br label %exit
23
24bb1:                                              ; preds = %start
25  %1 = icmp eq i64 %b, %c
26  br label %exit
27
28bb2:                                              ; preds = %start
29  %2 = icmp eq i64 %b, %c
30  br label %exit
31
32exit:                                             ; preds = %bb2, %bb1, %bb0
33  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
34  ret i1 %result
35}
36
37define i1 @common_instr_with_unreachable_2(i64 %a, i64 %b, i64 %c) {
38; CHECK-LABEL: @common_instr_with_unreachable_2(
39; CHECK-NEXT:  start:
40; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
41; CHECK-NEXT:    ret i1 [[TMP0]]
42;
43start:
44  switch i64 %a, label %bb1 [
45  i64 0, label %bb0
46  i64 1, label %unreachable
47  i64 2, label %bb2
48  ]
49
50unreachable:
51  unreachable
52
53bb0:                                              ; preds = %start
54  %0 = icmp eq i64 %b, %c
55  br label %exit
56
57bb1:                                              ; preds = %start
58  %1 = icmp eq i64 %b, %c
59  br label %exit
60
61bb2:                                              ; preds = %start
62  %2 = icmp eq i64 %b, %c
63  br label %exit
64
65exit:                                             ; preds = %bb2, %bb1, %bb0
66  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
67  ret i1 %result
68}
69
70define i1 @not_only_unreachable(i64 %a, i64 %b, i64 %c) {
71; CHECK-LABEL: @not_only_unreachable(
72; CHECK-NEXT:  start:
73; CHECK-NEXT:    switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [
74; CHECK-NEXT:      i64 0, label [[BB0:%.*]]
75; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
76; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
77; CHECK-NEXT:    ]
78; CHECK:       unreachable:
79; CHECK-NEXT:    call void @no_return()
80; CHECK-NEXT:    unreachable
81; CHECK:       bb0:
82; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
83; CHECK-NEXT:    call void @foo()
84; CHECK-NEXT:    br label [[EXIT:%.*]]
85; CHECK:       bb1:
86; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]]
87; CHECK-NEXT:    call void @foo()
88; CHECK-NEXT:    br label [[EXIT]]
89; CHECK:       bb2:
90; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
91; CHECK-NEXT:    call void @foo()
92; CHECK-NEXT:    br label [[EXIT]]
93; CHECK:       exit:
94; CHECK-NEXT:    [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
95; CHECK-NEXT:    ret i1 [[RESULT]]
96;
97start:
98  switch i64 %a, label %unreachable [
99  i64 0, label %bb0
100  i64 1, label %bb1
101  i64 2, label %bb2
102  ]
103
104unreachable:
105  call void @no_return()
106  unreachable
107
108bb0:                                              ; preds = %start
109  %0 = icmp eq i64 %b, %c
110  call void @foo()
111  br label %exit
112
113bb1:                                              ; preds = %start
114  %1 = icmp eq i64 %b, %c
115  call void @foo()
116  br label %exit
117
118bb2:                                              ; preds = %start
119  %2 = icmp eq i64 %b, %c
120  call void @foo()
121  br label %exit
122
123exit:                                             ; preds = %bb2, %bb1, %bb0
124  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
125  ret i1 %result
126}
127
128; If we can hoist a musttail call,
129; we can and have to hoist subsequent bitcast and ret instructions.
130define ptr @switch_musttail_call(ptr %arg) {
131; CHECK-LABEL: @switch_musttail_call(
132; CHECK-NEXT:  bb:
133; CHECK-NEXT:    [[P0:%.*]] = musttail call ptr @musttail_call(ptr [[ARG:%.*]])
134; CHECK-NEXT:    ret ptr [[P0]]
135;
136bb:
137  %load = load i16, ptr %arg, align 2
138  switch i16 %load, label %unreachable [
139  i16 0, label %bb0
140  i16 1, label %bb1
141  i16 2, label %bb2
142  ]
143
144unreachable:
145  unreachable
146
147bb0:
148  %p0 = musttail call ptr @musttail_call(ptr %arg)
149  ret ptr %p0
150
151bb1:
152  %p1 = musttail call ptr @musttail_call(ptr %arg)
153  ret ptr %p1
154
155bb2:
156  %p2 = musttail call ptr @musttail_call(ptr %arg)
157  ret ptr %p2
158}
159
160declare void @no_return()
161declare void @foo()
162declare ptr @musttail_call(ptr)
163