1f24175fcSPhilip Reames; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2cee313d2SEric Christopher; RUN: opt < %s -jump-threading -dce -S | FileCheck %s
3cee313d2SEric Christopher
4cee313d2SEric Christopherdeclare void @llvm.experimental.guard(i1, ...)
5cee313d2SEric Christopher
6cee313d2SEric Christopherdeclare i32 @f1()
7cee313d2SEric Christopherdeclare i32 @f2()
8cee313d2SEric Christopher
9cee313d2SEric Christopherdefine i32 @branch_implies_guard(i32 %a) {
10cee313d2SEric Christopher; CHECK-LABEL: @branch_implies_guard(
11f24175fcSPhilip Reames; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], 10
12f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[COND]], label [[T1_SPLIT:%.*]], label [[F1_SPLIT:%.*]]
13f24175fcSPhilip Reames; CHECK:       T1.split:
14f24175fcSPhilip Reames; CHECK-NEXT:    [[V1:%.*]] = call i32 @f1()
15f24175fcSPhilip Reames; CHECK-NEXT:    [[RETVAL3:%.*]] = add i32 [[V1]], 10
16f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE:%.*]]
17f24175fcSPhilip Reames; CHECK:       F1.split:
18f24175fcSPhilip Reames; CHECK-NEXT:    [[V2:%.*]] = call i32 @f2()
19f24175fcSPhilip Reames; CHECK-NEXT:    [[RETVAL1:%.*]] = add i32 [[V2]], 10
20f24175fcSPhilip Reames; CHECK-NEXT:    [[CONDGUARD2:%.*]] = icmp slt i32 [[A]], 20
21f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD2]]) [ "deopt"() ]
22f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE]]
23f24175fcSPhilip Reames; CHECK:       Merge:
24f24175fcSPhilip Reames; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[RETVAL3]], [[T1_SPLIT]] ], [ [[RETVAL1]], [[F1_SPLIT]] ]
25f24175fcSPhilip Reames; CHECK-NEXT:    ret i32 [[TMP1]]
26f24175fcSPhilip Reames;
27cee313d2SEric Christopher  %cond = icmp slt i32 %a, 10
28cee313d2SEric Christopher  br i1 %cond, label %T1, label %F1
29cee313d2SEric Christopher
30cee313d2SEric ChristopherT1:
31cee313d2SEric Christopher  %v1 = call i32 @f1()
32cee313d2SEric Christopher  br label %Merge
33cee313d2SEric Christopher
34cee313d2SEric ChristopherF1:
35cee313d2SEric Christopher  %v2 = call i32 @f2()
36cee313d2SEric Christopher  br label %Merge
37cee313d2SEric Christopher
38cee313d2SEric ChristopherMerge:
39cee313d2SEric Christopher  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
40cee313d2SEric Christopher  %retVal = add i32 %retPhi, 10
41cee313d2SEric Christopher  %condGuard = icmp slt i32 %a, 20
42cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
43cee313d2SEric Christopher  ret i32 %retVal
44cee313d2SEric Christopher}
45cee313d2SEric Christopher
46cee313d2SEric Christopherdefine i32 @not_branch_implies_guard(i32 %a) {
47cee313d2SEric Christopher; CHECK-LABEL: @not_branch_implies_guard(
48f24175fcSPhilip Reames; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], 20
49f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[COND]], label [[T1_SPLIT:%.*]], label [[F1_SPLIT:%.*]]
50f24175fcSPhilip Reames; CHECK:       T1.split:
51f24175fcSPhilip Reames; CHECK-NEXT:    [[V1:%.*]] = call i32 @f1()
52f24175fcSPhilip Reames; CHECK-NEXT:    [[RETVAL1:%.*]] = add i32 [[V1]], 10
53f24175fcSPhilip Reames; CHECK-NEXT:    [[CONDGUARD2:%.*]] = icmp sgt i32 [[A]], 10
54f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD2]]) [ "deopt"() ]
55f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE:%.*]]
56f24175fcSPhilip Reames; CHECK:       F1.split:
57f24175fcSPhilip Reames; CHECK-NEXT:    [[V2:%.*]] = call i32 @f2()
58f24175fcSPhilip Reames; CHECK-NEXT:    [[RETVAL3:%.*]] = add i32 [[V2]], 10
59f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE]]
60f24175fcSPhilip Reames; CHECK:       Merge:
61f24175fcSPhilip Reames; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[RETVAL3]], [[F1_SPLIT]] ], [ [[RETVAL1]], [[T1_SPLIT]] ]
62f24175fcSPhilip Reames; CHECK-NEXT:    ret i32 [[TMP1]]
63f24175fcSPhilip Reames;
64cee313d2SEric Christopher  %cond = icmp slt i32 %a, 20
65cee313d2SEric Christopher  br i1 %cond, label %T1, label %F1
66cee313d2SEric Christopher
67cee313d2SEric ChristopherT1:
68cee313d2SEric Christopher  %v1 = call i32 @f1()
69cee313d2SEric Christopher  br label %Merge
70cee313d2SEric Christopher
71cee313d2SEric ChristopherF1:
72cee313d2SEric Christopher  %v2 = call i32 @f2()
73cee313d2SEric Christopher  br label %Merge
74cee313d2SEric Christopher
75cee313d2SEric ChristopherMerge:
76cee313d2SEric Christopher  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
77cee313d2SEric Christopher  %retVal = add i32 %retPhi, 10
78cee313d2SEric Christopher  %condGuard = icmp sgt i32 %a, 10
79cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
80cee313d2SEric Christopher  ret i32 %retVal
81cee313d2SEric Christopher}
82cee313d2SEric Christopher
83cee313d2SEric Christopherdefine i32 @branch_overlaps_guard(i32 %a) {
84cee313d2SEric Christopher; CHECK-LABEL: @branch_overlaps_guard(
85f24175fcSPhilip Reames; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], 20
86f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[COND]], label [[T1:%.*]], label [[F1:%.*]]
87f24175fcSPhilip Reames; CHECK:       T1:
88f24175fcSPhilip Reames; CHECK-NEXT:    [[V1:%.*]] = call i32 @f1()
89f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE:%.*]]
90f24175fcSPhilip Reames; CHECK:       F1:
91f24175fcSPhilip Reames; CHECK-NEXT:    [[V2:%.*]] = call i32 @f2()
92f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE]]
93f24175fcSPhilip Reames; CHECK:       Merge:
94f24175fcSPhilip Reames; CHECK-NEXT:    [[RETPHI:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ]
95f24175fcSPhilip Reames; CHECK-NEXT:    [[RETVAL:%.*]] = add i32 [[RETPHI]], 10
96f24175fcSPhilip Reames; CHECK-NEXT:    [[CONDGUARD:%.*]] = icmp slt i32 [[A]], 10
97f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD]]) [ "deopt"() ]
98f24175fcSPhilip Reames; CHECK-NEXT:    ret i32 [[RETVAL]]
99f24175fcSPhilip Reames;
100cee313d2SEric Christopher  %cond = icmp slt i32 %a, 20
101cee313d2SEric Christopher  br i1 %cond, label %T1, label %F1
102cee313d2SEric Christopher
103cee313d2SEric ChristopherT1:
104cee313d2SEric Christopher  %v1 = call i32 @f1()
105cee313d2SEric Christopher  br label %Merge
106cee313d2SEric Christopher
107cee313d2SEric ChristopherF1:
108cee313d2SEric Christopher  %v2 = call i32 @f2()
109cee313d2SEric Christopher  br label %Merge
110cee313d2SEric Christopher
111cee313d2SEric ChristopherMerge:
112cee313d2SEric Christopher  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
113cee313d2SEric Christopher  %retVal = add i32 %retPhi, 10
114cee313d2SEric Christopher  %condGuard = icmp slt i32 %a, 10
115cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
116cee313d2SEric Christopher  ret i32 %retVal
117cee313d2SEric Christopher}
118cee313d2SEric Christopher
119cee313d2SEric Christopherdefine i32 @branch_doesnt_overlap_guard(i32 %a) {
120cee313d2SEric Christopher; CHECK-LABEL: @branch_doesnt_overlap_guard(
121f24175fcSPhilip Reames; CHECK-NEXT:    [[COND:%.*]] = icmp slt i32 [[A:%.*]], 10
122f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[COND]], label [[T1:%.*]], label [[F1:%.*]]
123f24175fcSPhilip Reames; CHECK:       T1:
124f24175fcSPhilip Reames; CHECK-NEXT:    [[V1:%.*]] = call i32 @f1()
125f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE:%.*]]
126f24175fcSPhilip Reames; CHECK:       F1:
127f24175fcSPhilip Reames; CHECK-NEXT:    [[V2:%.*]] = call i32 @f2()
128f24175fcSPhilip Reames; CHECK-NEXT:    br label [[MERGE]]
129f24175fcSPhilip Reames; CHECK:       Merge:
130f24175fcSPhilip Reames; CHECK-NEXT:    [[RETPHI:%.*]] = phi i32 [ [[V1]], [[T1]] ], [ [[V2]], [[F1]] ]
131f24175fcSPhilip Reames; CHECK-NEXT:    [[RETVAL:%.*]] = add i32 [[RETPHI]], 10
132f24175fcSPhilip Reames; CHECK-NEXT:    [[CONDGUARD:%.*]] = icmp sgt i32 [[A]], 20
133f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CONDGUARD]]) [ "deopt"() ]
134f24175fcSPhilip Reames; CHECK-NEXT:    ret i32 [[RETVAL]]
135f24175fcSPhilip Reames;
136cee313d2SEric Christopher  %cond = icmp slt i32 %a, 10
137cee313d2SEric Christopher  br i1 %cond, label %T1, label %F1
138cee313d2SEric Christopher
139cee313d2SEric ChristopherT1:
140cee313d2SEric Christopher  %v1 = call i32 @f1()
141cee313d2SEric Christopher  br label %Merge
142cee313d2SEric Christopher
143cee313d2SEric ChristopherF1:
144cee313d2SEric Christopher  %v2 = call i32 @f2()
145cee313d2SEric Christopher  br label %Merge
146cee313d2SEric Christopher
147cee313d2SEric ChristopherMerge:
148cee313d2SEric Christopher  %retPhi = phi i32 [ %v1, %T1 ], [ %v2, %F1 ]
149cee313d2SEric Christopher  %retVal = add i32 %retPhi, 10
150cee313d2SEric Christopher  %condGuard = icmp sgt i32 %a, 20
151cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %condGuard) [ "deopt"() ]
152cee313d2SEric Christopher  ret i32 %retVal
153cee313d2SEric Christopher}
154cee313d2SEric Christopher
155cee313d2SEric Christopherdefine i32 @not_a_diamond1(i32 %a, i1 %cond1) {
156cee313d2SEric Christopher; CHECK-LABEL: @not_a_diamond1(
157f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[PRED:%.*]], label [[EXIT:%.*]]
158f24175fcSPhilip Reames; CHECK:       Pred:
159f24175fcSPhilip Reames; CHECK-NEXT:    switch i32 [[A:%.*]], label [[EXIT]] [
160f24175fcSPhilip Reames; CHECK-NEXT:    i32 10, label [[MERGE:%.*]]
161f24175fcSPhilip Reames; CHECK-NEXT:    i32 20, label [[MERGE]]
162f24175fcSPhilip Reames; CHECK-NEXT:    ]
163f24175fcSPhilip Reames; CHECK:       Merge:
164f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND1]]) [ "deopt"() ]
165f24175fcSPhilip Reames; CHECK-NEXT:    br label [[EXIT]]
166f24175fcSPhilip Reames; CHECK:       Exit:
167f24175fcSPhilip Reames; CHECK-NEXT:    ret i32 [[A]]
168f24175fcSPhilip Reames;
169cee313d2SEric Christopher  br i1 %cond1, label %Pred, label %Exit
170cee313d2SEric Christopher
171cee313d2SEric ChristopherPred:
172cee313d2SEric Christopher  switch i32 %a, label %Exit [
173cee313d2SEric Christopher  i32 10, label %Merge
174cee313d2SEric Christopher  i32 20, label %Merge
175cee313d2SEric Christopher  ]
176cee313d2SEric Christopher
177cee313d2SEric ChristopherMerge:
178cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
179cee313d2SEric Christopher  br label %Exit
180cee313d2SEric Christopher
181cee313d2SEric ChristopherExit:
182cee313d2SEric Christopher  ret i32 %a
183cee313d2SEric Christopher}
184cee313d2SEric Christopher
185cee313d2SEric Christopherdefine void @not_a_diamond2(i32 %a, i1 %cond1) {
186cee313d2SEric Christopher; CHECK-LABEL: @not_a_diamond2(
187f24175fcSPhilip Reames; CHECK-NEXT:  Pred:
188f24175fcSPhilip Reames; CHECK-NEXT:    switch i32 [[A:%.*]], label [[EXIT:%.*]] [
189f24175fcSPhilip Reames; CHECK-NEXT:    i32 10, label [[MERGE:%.*]]
190f24175fcSPhilip Reames; CHECK-NEXT:    i32 20, label [[MERGE]]
191f24175fcSPhilip Reames; CHECK-NEXT:    ]
192f24175fcSPhilip Reames; CHECK:       Merge:
193f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND1:%.*]]) [ "deopt"() ]
194f24175fcSPhilip Reames; CHECK-NEXT:    ret void
195f24175fcSPhilip Reames; CHECK:       Exit:
196f24175fcSPhilip Reames; CHECK-NEXT:    ret void
197f24175fcSPhilip Reames;
198cee313d2SEric Christopher  br label %Parent
199cee313d2SEric Christopher
200cee313d2SEric ChristopherMerge:
201cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %cond1)[ "deopt"() ]
202cee313d2SEric Christopher  ret void
203cee313d2SEric Christopher
204cee313d2SEric ChristopherPred:
205cee313d2SEric Christopher  switch i32 %a, label %Exit [
206cee313d2SEric Christopher  i32 10, label %Merge
207cee313d2SEric Christopher  i32 20, label %Merge
208cee313d2SEric Christopher  ]
209cee313d2SEric Christopher
210cee313d2SEric ChristopherParent:
211cee313d2SEric Christopher  br label %Pred
212cee313d2SEric Christopher
213cee313d2SEric ChristopherExit:
214cee313d2SEric Christopher  ret void
215cee313d2SEric Christopher}
216cee313d2SEric Christopher
217cee313d2SEric Christopherdeclare void @never_called(i1)
218cee313d2SEric Christopher
219cee313d2SEric Christopher; LVI uses guard to identify value of %c2 in branch as true, we cannot replace that
220cee313d2SEric Christopher; guard with guard(true & c1).
221cee313d2SEric Christopherdefine void @dont_fold_guard(i8* %addr, i32 %i, i32 %length) {
222f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard(
223f24175fcSPhilip Reames; CHECK-NEXT:  BB1:
224f24175fcSPhilip Reames; CHECK-NEXT:    [[C1:%.*]] = icmp ult i32 [[I:%.*]], [[LENGTH:%.*]]
225f24175fcSPhilip Reames; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 [[I]], 0
226f24175fcSPhilip Reames; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
227f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
228cee313d2SEric Christopher; CHECK-NEXT:    call void @never_called(i1 true)
229cee313d2SEric Christopher; CHECK-NEXT:    ret void
230f24175fcSPhilip Reames;
231cee313d2SEric Christopher  %c1 = icmp ult i32 %i, %length
232cee313d2SEric Christopher  %c2 = icmp eq i32 %i, 0
233cee313d2SEric Christopher  %wide.chk = and i1 %c1, %c2
234cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
235cee313d2SEric Christopher  br i1 %c2, label %BB1, label %BB2
236cee313d2SEric Christopher
237cee313d2SEric ChristopherBB1:
238cee313d2SEric Christopher  call void @never_called(i1 %c2)
239cee313d2SEric Christopher  ret void
240cee313d2SEric Christopher
241cee313d2SEric ChristopherBB2:
242cee313d2SEric Christopher  ret void
243cee313d2SEric Christopher}
244cee313d2SEric Christopher
2455d12b976SNikita Popovdeclare void @dummy(i1) nounwind willreturn
246cee313d2SEric Christopher; same as dont_fold_guard1 but there's a use immediately after guard and before
247cee313d2SEric Christopher; branch. We can fold that use.
248cee313d2SEric Christopherdefine void @dont_fold_guard2(i8* %addr, i32 %i, i32 %length) {
249f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard2(
250f24175fcSPhilip Reames; CHECK-NEXT:  BB1:
251f24175fcSPhilip Reames; CHECK-NEXT:    [[C1:%.*]] = icmp ult i32 [[I:%.*]], [[LENGTH:%.*]]
252f24175fcSPhilip Reames; CHECK-NEXT:    [[C2:%.*]] = icmp eq i32 [[I]], 0
253f24175fcSPhilip Reames; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C1]], [[C2]]
254f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
255f24175fcSPhilip Reames; CHECK-NEXT:    call void @dummy(i1 true)
256cee313d2SEric Christopher; CHECK-NEXT:    call void @never_called(i1 true)
257cee313d2SEric Christopher; CHECK-NEXT:    ret void
258f24175fcSPhilip Reames;
259cee313d2SEric Christopher  %c1 = icmp ult i32 %i, %length
260cee313d2SEric Christopher  %c2 = icmp eq i32 %i, 0
261cee313d2SEric Christopher  %wide.chk = and i1 %c1, %c2
262cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
263cee313d2SEric Christopher  call void @dummy(i1 %c2)
264cee313d2SEric Christopher  br i1 %c2, label %BB1, label %BB2
265cee313d2SEric Christopher
266cee313d2SEric ChristopherBB1:
267cee313d2SEric Christopher  call void @never_called(i1 %c2)
268cee313d2SEric Christopher  ret void
269cee313d2SEric Christopher
270cee313d2SEric ChristopherBB2:
271cee313d2SEric Christopher  ret void
272cee313d2SEric Christopher}
273cee313d2SEric Christopher
274cee313d2SEric Christopher; same as dont_fold_guard1 but condition %cmp is not an instruction.
275cee313d2SEric Christopher; We cannot fold the guard under any circumstance.
276cee313d2SEric Christopher; FIXME: We can merge unreachableBB2 into not_zero.
277cee313d2SEric Christopherdefine void @dont_fold_guard3(i8* %addr, i1 %cmp, i32 %i, i32 %length) {
278f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard3(
279f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CMP:%.*]]) [ "deopt"() ]
280f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[CMP]], label [[BB1:%.*]], label [[BB2:%.*]]
281f24175fcSPhilip Reames; CHECK:       BB1:
282f24175fcSPhilip Reames; CHECK-NEXT:    call void @never_called(i1 [[CMP]])
283f24175fcSPhilip Reames; CHECK-NEXT:    ret void
284f24175fcSPhilip Reames; CHECK:       BB2:
285f24175fcSPhilip Reames; CHECK-NEXT:    ret void
286f24175fcSPhilip Reames;
287cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
288cee313d2SEric Christopher  br i1 %cmp, label %BB1, label %BB2
289cee313d2SEric Christopher
290cee313d2SEric ChristopherBB1:
291cee313d2SEric Christopher  call void @never_called(i1 %cmp)
292cee313d2SEric Christopher  ret void
293cee313d2SEric Christopher
294cee313d2SEric ChristopherBB2:
295cee313d2SEric Christopher  ret void
296cee313d2SEric Christopher}
297cee313d2SEric Christopher
298cee313d2SEric Christopherdeclare void @f(i1)
299cee313d2SEric Christopher; Same as dont_fold_guard1 but use switch instead of branch.
300cee313d2SEric Christopher; triggers source code `ProcessThreadableEdges`.
301cee313d2SEric Christopherdefine void @dont_fold_guard4(i1 %cmp1, i32 %i) nounwind {
302f24175fcSPhilip Reames; CHECK-LABEL: @dont_fold_guard4(
303f24175fcSPhilip Reames; CHECK-NEXT:  entry:
304f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[CMP1:%.*]], label [[L2:%.*]], label [[L3:%.*]]
305f24175fcSPhilip Reames; CHECK:       L2:
306f24175fcSPhilip Reames; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
307f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[CMP]]) [ "deopt"() ]
308f24175fcSPhilip Reames; CHECK-NEXT:    call void @dummy(i1 true)
309f24175fcSPhilip Reames; CHECK-NEXT:    call void @f(i1 true)
310cee313d2SEric Christopher; CHECK-NEXT:    ret void
311f24175fcSPhilip Reames; CHECK:       L3:
312f24175fcSPhilip Reames; CHECK-NEXT:    ret void
313f24175fcSPhilip Reames;
314cee313d2SEric Christopherentry:
315cee313d2SEric Christopher  br i1 %cmp1, label %L0, label %L3
316cee313d2SEric ChristopherL0:
317cee313d2SEric Christopher  %cmp = icmp eq i32 %i, 0
318cee313d2SEric Christopher  call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
319cee313d2SEric Christopher  call void @dummy(i1 %cmp)
320cee313d2SEric Christopher  switch i1 %cmp, label %L3 [
321cee313d2SEric Christopher  i1 false, label %L1
322cee313d2SEric Christopher  i1 true, label %L2
323cee313d2SEric Christopher  ]
324cee313d2SEric Christopher
325cee313d2SEric ChristopherL1:
326cee313d2SEric Christopher  ret void
327cee313d2SEric ChristopherL2:
328cee313d2SEric Christopher  call void @f(i1 %cmp)
329cee313d2SEric Christopher  ret void
330cee313d2SEric ChristopherL3:
331cee313d2SEric Christopher  ret void
332cee313d2SEric Christopher}
333cee313d2SEric Christopher
334cee313d2SEric Christopher; Make sure that we don't PRE a non-speculable load across a guard.
335cee313d2SEric Christopherdefine void @unsafe_pre_across_guard(i8* %p, i1 %load.is.valid) {
336cee313d2SEric Christopher; CHECK-LABEL: @unsafe_pre_across_guard(
337f24175fcSPhilip Reames; CHECK-NEXT:  entry:
338f24175fcSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
339cee313d2SEric Christopher; CHECK:       loop:
340f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[LOAD_IS_VALID:%.*]]) [ "deopt"() ]
341f24175fcSPhilip Reames; CHECK-NEXT:    [[LOADED:%.*]] = load i8, i8* [[P:%.*]], align 1
342f24175fcSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0
343f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]]
344f24175fcSPhilip Reames; CHECK:       exit:
345f24175fcSPhilip Reames; CHECK-NEXT:    ret void
346f24175fcSPhilip Reames;
347cee313d2SEric Christopherentry:
348cee313d2SEric Christopher  br label %loop
349cee313d2SEric Christopher
350cee313d2SEric Christopherloop:                                             ; preds = %loop, %entry
351cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ]
352cee313d2SEric Christopher  %loaded = load i8, i8* %p
353cee313d2SEric Christopher  %continue = icmp eq i8 %loaded, 0
354cee313d2SEric Christopher  br i1 %continue, label %exit, label %loop
355cee313d2SEric Christopher
356cee313d2SEric Christopherexit:                                             ; preds = %loop
357cee313d2SEric Christopher  ret void
358cee313d2SEric Christopher}
359cee313d2SEric Christopher
360cee313d2SEric Christopher; Make sure that we can safely PRE a speculable load across a guard.
361*e75a2dfeSPhilip Reamesdefine void @safe_pre_across_guard(i8* noalias nocapture readonly dereferenceable(8) %p, i1 %load.is.valid) nofree nosync {
362cee313d2SEric Christopher; CHECK-LABEL: @safe_pre_across_guard(
363f24175fcSPhilip Reames; CHECK-NEXT:  entry:
364f24175fcSPhilip Reames; CHECK-NEXT:    [[LOADED_PR:%.*]] = load i8, i8* [[P:%.*]], align 1
365f24175fcSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
366cee313d2SEric Christopher; CHECK:       loop:
367f24175fcSPhilip Reames; CHECK-NEXT:    [[LOADED:%.*]] = phi i8 [ [[LOADED]], [[LOOP]] ], [ [[LOADED_PR]], [[ENTRY:%.*]] ]
368f24175fcSPhilip Reames; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[LOAD_IS_VALID:%.*]]) [ "deopt"() ]
369f24175fcSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0
370f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]]
371f24175fcSPhilip Reames; CHECK:       exit:
372f24175fcSPhilip Reames; CHECK-NEXT:    ret void
373f24175fcSPhilip Reames;
374cee313d2SEric Christopher
375cee313d2SEric Christopherentry:
376cee313d2SEric Christopher  br label %loop
377cee313d2SEric Christopher
378cee313d2SEric Christopherloop:                                             ; preds = %loop, %entry
379cee313d2SEric Christopher  call void (i1, ...) @llvm.experimental.guard(i1 %load.is.valid) [ "deopt"() ]
380cee313d2SEric Christopher  %loaded = load i8, i8* %p
381cee313d2SEric Christopher  %continue = icmp eq i8 %loaded, 0
382cee313d2SEric Christopher  br i1 %continue, label %exit, label %loop
383cee313d2SEric Christopher
384cee313d2SEric Christopherexit:                                             ; preds = %loop
385cee313d2SEric Christopher  ret void
386cee313d2SEric Christopher}
387cee313d2SEric Christopher
388cee313d2SEric Christopher; Make sure that we don't PRE a non-speculable load across a call which may
389cee313d2SEric Christopher; alias with the load.
390cee313d2SEric Christopherdefine void @unsafe_pre_across_call(i8* %p) {
391cee313d2SEric Christopher; CHECK-LABEL: @unsafe_pre_across_call(
392f24175fcSPhilip Reames; CHECK-NEXT:  entry:
393f24175fcSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
394cee313d2SEric Christopher; CHECK:       loop:
395f24175fcSPhilip Reames; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @f1()
396f24175fcSPhilip Reames; CHECK-NEXT:    [[LOADED:%.*]] = load i8, i8* [[P:%.*]], align 1
397f24175fcSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0
398f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]]
399f24175fcSPhilip Reames; CHECK:       exit:
400f24175fcSPhilip Reames; CHECK-NEXT:    ret void
401f24175fcSPhilip Reames;
402cee313d2SEric Christopherentry:
403cee313d2SEric Christopher  br label %loop
404cee313d2SEric Christopher
405cee313d2SEric Christopherloop:                                             ; preds = %loop, %entry
406cee313d2SEric Christopher  call i32 @f1()
407cee313d2SEric Christopher  %loaded = load i8, i8* %p
408cee313d2SEric Christopher  %continue = icmp eq i8 %loaded, 0
409cee313d2SEric Christopher  br i1 %continue, label %exit, label %loop
410cee313d2SEric Christopher
411cee313d2SEric Christopherexit:                                             ; preds = %loop
412cee313d2SEric Christopher  ret void
413cee313d2SEric Christopher}
414cee313d2SEric Christopher
415cee313d2SEric Christopher; Make sure that we can safely PRE a speculable load across a call.
416*e75a2dfeSPhilip Reamesdefine void @safe_pre_across_call(i8* noalias nocapture readonly dereferenceable(8) %p) nofree nosync {
417cee313d2SEric Christopher; CHECK-LABEL: @safe_pre_across_call(
418f24175fcSPhilip Reames; CHECK-NEXT:  entry:
419f24175fcSPhilip Reames; CHECK-NEXT:    [[LOADED_PR:%.*]] = load i8, i8* [[P:%.*]], align 1
420f24175fcSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
421cee313d2SEric Christopher; CHECK:       loop:
422f24175fcSPhilip Reames; CHECK-NEXT:    [[LOADED:%.*]] = phi i8 [ [[LOADED]], [[LOOP]] ], [ [[LOADED_PR]], [[ENTRY:%.*]] ]
423f24175fcSPhilip Reames; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @f1()
424f24175fcSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp eq i8 [[LOADED]], 0
425f24175fcSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[EXIT:%.*]], label [[LOOP]]
426f24175fcSPhilip Reames; CHECK:       exit:
427f24175fcSPhilip Reames; CHECK-NEXT:    ret void
428f24175fcSPhilip Reames;
429cee313d2SEric Christopher
430cee313d2SEric Christopherentry:
431cee313d2SEric Christopher  br label %loop
432cee313d2SEric Christopher
433cee313d2SEric Christopherloop:                                             ; preds = %loop, %entry
434cee313d2SEric Christopher  call i32 @f1()
435cee313d2SEric Christopher  %loaded = load i8, i8* %p
436cee313d2SEric Christopher  %continue = icmp eq i8 %loaded, 0
437cee313d2SEric Christopher  br i1 %continue, label %exit, label %loop
438cee313d2SEric Christopher
439cee313d2SEric Christopherexit:                                             ; preds = %loop
440cee313d2SEric Christopher  ret void
441cee313d2SEric Christopher}
442