xref: /llvm-project/llvm/test/Transforms/LoopPredication/invalidate-analyses.ll (revision 46c2d936624322e141c6eff319e1ad2d25f1afd7)
1; RUN: opt -S -passes='require<scalar-evolution>,require<lazy-value-info>,loop-mssa(loop-predication)' -debug-pass-manager < %s 2>&1 | FileCheck %s
2
3; NOTE: LazyValueAnalysis is an arbitrary analysis that just isn't preserved by
4;       this pass. If after your change this analysis is preserved by the pass,
5;       please update this test some other analysis that isn't preserved.
6
7; CHECK: Running analysis: LazyValueAnalysis on drop_a_wc_and_leave_early
8; CHECK: Running pass: LoopPredicationPass on loop %loop in function drop_a_wc_and_leave_early
9; CHECK: Invalidating analysis: LazyValueAnalysis on drop_a_wc_and_leave_early
10; CHECK: Running analysis: LazyValueAnalysis on drop_a_wc_and_leave
11; CHECK: Running pass: LoopPredicationPass on loop %loop in function drop_a_wc_and_leave
12; CHECK: Invalidating analysis: LazyValueAnalysis on drop_a_wc_and_leave
13
14
15; This test makes the pass drop its attempts to optimize the exit condition in
16; `%loop` BB by using unanalyzable `%cond_0` as an exit condition.
17define i64 @drop_a_wc_and_leave_early(i64 %length, i64 %n, i1 %cond_0, i1 %cond_1) {
18; Make sure the pass has only replaced `%wc2` with `true` in the definition of `%wb_cond`.
19; CHECK-LABEL: define i64 @drop_a_wc_and_leave_early(i64 %length, i64 %n, i1 %cond_0, i1 %cond_1) {
20; CHECK-NEXT: entry:
21; CHECK-NEXT:   %wc1 = call i1 @llvm.experimental.widenable.condition()
22; CHECK-NEXT:   %wc2 = call i1 @llvm.experimental.widenable.condition()
23; CHECK-NEXT:   %exiplicit_guard_cond = and i1 %cond_0, %wc1
24; CHECK-NEXT:   br i1 %exiplicit_guard_cond, label %loop.preheader, label %deopt, !prof !0
25; CHECK:      deopt:
26; CHECK-NEXT:   %deoptret = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
27; CHECK-NEXT:   ret i64 %deoptret
28; CHECK:      loop.preheader:
29; CHECK-NEXT:   br label %loop
30; CHECK:      loop:
31; CHECK-NEXT:   %i = phi i64 [ %i.next, %guarded2 ], [ 0, %loop.preheader ]
32; CHECK-NEXT:   br i1 %cond_0, label %guarded, label %deopt2, !prof !0
33; CHECK:      deopt2:
34; CHECK-NEXT:   %deoptret2 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
35; CHECK-NEXT:   ret i64 %deoptret2
36; CHECK:      guarded:
37; CHECK-NEXT:   %wb_cond = and i1 %cond_1, true
38; CHECK-NEXT:   br i1 %wb_cond, label %guarded2, label %deopt3, !prof !0
39; CHECK:      deopt3:
40; CHECK-NEXT:   %deoptret3 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
41; CHECK-NEXT:   ret i64 %deoptret3
42; CHECK:      guarded2:
43; CHECK-NEXT:   %i.next = add nuw i64 %i, 1
44; CHECK-NEXT:   %continue = icmp ult i64 %i.next, %n
45; CHECK-NEXT:   br i1 %continue, label %loop, label %exit
46; CHECK:      exit:
47; CHECK-NEXT:   ret i64 0
48; CHECK-NEXT: }
49
50entry:
51  %wc1 = call i1 @llvm.experimental.widenable.condition()
52  %wc2 = call i1 @llvm.experimental.widenable.condition()
53  %exiplicit_guard_cond = and i1 %cond_0, %wc1
54  br i1 %exiplicit_guard_cond, label %loop.preheader, label %deopt, !prof !0
55
56deopt:
57  %deoptret = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
58  ret i64 %deoptret
59
60loop.preheader:
61  br label %loop
62
63loop:
64  %i = phi i64 [ %i.next, %guarded2 ], [ 0, %loop.preheader ]
65  br i1 %cond_0, label %guarded, label %deopt2, !prof !0
66
67deopt2:
68  %deoptret2 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
69  ret i64 %deoptret2
70
71guarded:
72  %wb_cond = and i1 %cond_1, %wc2
73  br i1 %wb_cond, label %guarded2, label %deopt3, !prof !0
74
75deopt3:
76  %deoptret3 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
77  ret i64 %deoptret3
78
79guarded2:
80  %i.next = add nuw i64 %i, 1
81  %continue = icmp ult i64 %i.next, %n
82  br i1 %continue, label %loop, label %exit
83
84exit:
85  ret i64 0
86}
87
88; This test makes the pass drop its attempts to optimize the exit condition in
89; `%loop` BB by using trivial `false` as an exit condition.
90define i64 @drop_a_wc_and_leave(i64 %n, i1 %cond_0, i1 %cond_1) {
91; Make sure the pass has only replaced `%wc2` with `true` in the definition of `%wb_cond`.
92; CHECK-LABEL: define i64 @drop_a_wc_and_leave(i64 %n, i1 %cond_0, i1 %cond_1) {
93; CHECK-NEXT: entry:
94; CHECK-NEXT:   %wc1 = call i1 @llvm.experimental.widenable.condition()
95; CHECK-NEXT:   %wc2 = call i1 @llvm.experimental.widenable.condition()
96; CHECK-NEXT:   %exiplicit_guard_cond = and i1 %cond_0, %wc1
97; CHECK-NEXT:   br i1 %exiplicit_guard_cond, label %loop.preheader, label %deopt, !prof !0
98; CHECK:      deopt:
99; CHECK-NEXT:   %deoptret = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
100; CHECK-NEXT:   ret i64 %deoptret
101; CHECK:      loop.preheader:
102; CHECK-NEXT:   br label %loop
103; CHECK:      loop:
104; CHECK-NEXT:   %i = phi i64 [ %i.next, %guarded2 ], [ 0, %loop.preheader ]
105; CHECK-NEXT:   br i1 false, label %guarded, label %deopt2, !prof !0
106; CHECK:      deopt2:
107; CHECK-NEXT:   %deoptret2 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
108; CHECK-NEXT:   ret i64 %deoptret2
109; CHECK:      guarded:
110; CHECK-NEXT:   %wb_cond = and i1 %cond_1, true
111; CHECK-NEXT:   br i1 %wb_cond, label %guarded2, label %deopt3, !prof !0
112; CHECK:      deopt3:
113; CHECK-NEXT:   %deoptret3 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
114; CHECK-NEXT:   ret i64 %deoptret3
115; CHECK:      guarded2:
116; CHECK-NEXT:   %i.next = add nuw i64 %i, 1
117; CHECK-NEXT:   %continue = icmp ult i64 %i.next, %n
118; CHECK-NEXT:   br i1 %continue, label %loop, label %exit
119; CHECK:      exit:
120; CHECK-NEXT:   ret i64 0
121; CHECK-NEXT: }
122
123entry:
124  %wc1 = call i1 @llvm.experimental.widenable.condition()
125  %wc2 = call i1 @llvm.experimental.widenable.condition()
126  %exiplicit_guard_cond = and i1 %cond_0, %wc1
127  br i1 %exiplicit_guard_cond, label %loop.preheader, label %deopt, !prof !0
128
129deopt:
130  %deoptret = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
131  ret i64 %deoptret
132
133loop.preheader:
134  br label %loop
135
136loop:
137  %i = phi i64 [ %i.next, %guarded2 ], [ 0, %loop.preheader ]
138  br i1 false, label %guarded, label %deopt2, !prof !0
139
140deopt2:
141  %deoptret2 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
142  ret i64 %deoptret2
143
144guarded:
145  %wb_cond = and i1 %cond_1, %wc2
146  br i1 %wb_cond, label %guarded2, label %deopt3, !prof !0
147
148deopt3:
149  %deoptret3 = call i64 (...) @llvm.experimental.deoptimize.i64() [ "deopt"() ]
150  ret i64 %deoptret3
151
152guarded2:
153  %i.next = add nuw i64 %i, 1
154  %continue = icmp ult i64 %i.next, %n
155  br i1 %continue, label %loop, label %exit
156
157exit:
158  ret i64 0
159}
160
161
162declare i1 @llvm.experimental.widenable.condition()
163declare i64 @llvm.experimental.deoptimize.i64(...)
164
165!0 = !{!"branch_weights", i64 1048576, i64 1}
166