1; RUN: opt < %s -S -speculative-execution \
2; RUN:   -spec-exec-max-speculation-cost 4 -spec-exec-max-not-hoisted 3 \
3; RUN:   | FileCheck %s
4
5target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
6
7; Hoist in if-then pattern.
8define void @ifThen() {
9; CHECK-LABEL: @ifThen(
10; CHECK: %x = add i32 2, 3
11; CHECK: br i1 true
12  br i1 true, label %a, label %b
13; CHECK: a:
14a:
15  %x = add i32 2, 3
16; CHECK: br label
17  br label %b
18; CHECK: b:
19b:
20; CHECK: ret void
21  ret void
22}
23
24; Hoist in if-else pattern.
25define void @ifElse() {
26; CHECK-LABEL: @ifElse(
27; CHECK: %x = add i32 2, 3
28; CHECK: br i1 true
29  br i1 true, label %b, label %a
30; CHECK: a:
31a:
32  %x = add i32 2, 3
33; CHECK: br label
34  br label %b
35; CHECK: b:
36b:
37; CHECK: ret void
38  ret void
39}
40
41; Hoist in if-then-else pattern if it is equivalent to if-then.
42define void @ifElseThenAsIfThen() {
43; CHECK-LABEL: @ifElseThenAsIfThen(
44; CHECK: %x = add i32 2, 3
45; CHECK: br
46  br i1 true, label %a, label %b
47; CHECK: a:
48a:
49  %x = add i32 2, 3
50; CHECK: br label
51  br label %c
52; CHECK: b:
53b:
54  br label %c
55; CHECK: c
56c:
57  ret void
58}
59
60; Hoist in if-then-else pattern if it is equivalent to if-else.
61define void @ifElseThenAsIfElse() {
62; CHECK-LABEL: @ifElseThenAsIfElse(
63; CHECK: %x = add i32 2, 3
64; CHECK: br
65  br i1 true, label %b, label %a
66; CHECK: a:
67a:
68  %x = add i32 2, 3
69; CHECK: br label
70  br label %c
71; CHECK: b:
72b:
73  br label %c
74; CHECK: c
75c:
76  ret void
77}
78
79; Do not hoist if-then-else pattern if it is not equivalent to if-then
80; or if-else.
81define void @ifElseThen() {
82; CHECK-LABEL: @ifElseThen(
83; CHECK: br
84  br i1 true, label %a, label %b
85; CHECK: a:
86a:
87; CHECK: %x = add
88  %x = add i32 2, 3
89; CHECK: br label
90  br label %c
91; CHECK: b:
92b:
93; CHECK: %y = add
94  %y = add i32 2, 3
95  br label %c
96; CHECK: c
97c:
98  ret void
99}
100
101; Do not hoist loads and do not hoist an instruction past a definition of
102; an operand.
103define void @doNotHoistPastDef() {
104; CHECK-LABEL: @doNotHoistPastDef(
105  br i1 true, label %b, label %a
106; CHECK-NOT: load
107; CHECK-NOT: add
108; CHECK: a:
109a:
110; CHECK: %def = load
111  %def = load i32, i32* null
112; CHECK: %use = add
113  %use = add i32 %def, 0
114  br label %b
115; CHECK: b:
116b:
117  ret void
118}
119
120; Case with nothing to speculate.
121define void @nothingToSpeculate() {
122; CHECK-LABEL: @nothingToSpeculate(
123  br i1 true, label %b, label %a
124; CHECK: a:
125a:
126; CHECK: %def = load
127  %def = load i32, i32* null
128  br label %b
129; CHECK: b:
130b:
131  ret void
132}
133
134; Still hoist if an operand is defined before the block or is itself hoisted.
135define void @hoistIfNotPastDef() {
136; CHECK-LABEL: @hoistIfNotPastDef(
137; CHECK: %x = load
138  %x = load i32, i32* null
139; CHECK: %y = add i32 %x, 1
140; CHECK: %z = add i32 %y, 1
141; CHECK: br
142  br i1 true, label %b, label %a
143; CHECK: a:
144a:
145  %y = add i32 %x, 1
146  %z = add i32 %y, 1
147  br label %b
148; CHECK: b:
149b:
150  ret void
151}
152
153; Do not hoist if the speculation cost is too high.
154define void @costTooHigh() {
155; CHECK-LABEL: @costTooHigh(
156; CHECK: br
157  br i1 true, label %b, label %a
158; CHECK: a:
159a:
160; CHECK: %r1 = add
161  %r1 = add i32 1, 1
162; CHECK: %r2 = add
163  %r2 = add i32 1, 1
164; CHECK: %r3 = add
165  %r3 = add i32 1, 1
166; CHECK: %r4 = add
167  %r4 = add i32 1, 1
168; CHECK: %r5 = add
169  %r5 = add i32 1, 1
170  br label %b
171; CHECK: b:
172b:
173  ret void
174}
175
176; Do not hoist if too many instructions are left behind.
177define void @tooMuchLeftBehind() {
178; CHECK-LABEL: @tooMuchLeftBehind(
179; CHECK: br
180  br i1 true, label %b, label %a
181; CHECK: a:
182a:
183; CHECK: %x = load
184  %x = load i32, i32* null
185; CHECK: %r1 = add
186  %r1 = add i32 %x, 1
187; CHECK: %r2 = add
188  %r2 = add i32 %x, 1
189; CHECK: %r3 = add
190  %r3 = add i32 %x, 1
191  br label %b
192; CHECK: b:
193b:
194  ret void
195}
196