[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / LoopSimplify / basictest.ll
blob17d715dbe584320620d8bb258b592fe89ed0c649
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s
4 ; This function should get a preheader inserted before bb3, that is jumped
5 ; to by bb1 & bb2
6 define void @test() {
7 ; CHECK-LABEL: @test(
8 ; CHECK-NEXT:  entry:
9 ; CHECK-NEXT:    br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]
10 ; CHECK:       bb1:
11 ; CHECK-NEXT:    br label [[BB3_PREHEADER:%.*]]
12 ; CHECK:       bb2:
13 ; CHECK-NEXT:    br label [[BB3_PREHEADER]]
14 ; CHECK:       bb3.preheader:
15 ; CHECK-NEXT:    br label [[BB3:%.*]]
16 ; CHECK:       bb3:
17 ; CHECK-NEXT:    br label [[BB3]]
19 entry:
20   br i1 true, label %bb1, label %bb2
22 bb1:
23   br label %bb3
25 bb2:
26   br label %bb3
28 bb3:
29   br label %bb3
32 ; Test a case where we have multiple exit blocks as successors of a single loop
33 ; block that need to be made dedicated exit blocks. We also have multiple
34 ; exiting edges to one of the exit blocks that all should be rewritten.
35 define void @test_multiple_exits_from_single_block(i8 %a, ptr %b.ptr) {
36 ; CHECK-LABEL: @test_multiple_exits_from_single_block(
37 ; CHECK-NEXT:  entry:
38 ; CHECK-NEXT:    switch i8 [[A:%.*]], label [[LOOP_PREHEADER:%.*]] [
39 ; CHECK-NEXT:    i8 0, label [[EXIT_A:%.*]]
40 ; CHECK-NEXT:    i8 1, label [[EXIT_B:%.*]]
41 ; CHECK-NEXT:    ]
42 ; CHECK:       loop.preheader:
43 ; CHECK-NEXT:    br label [[LOOP:%.*]]
44 ; CHECK:       loop:
45 ; CHECK-NEXT:    [[B:%.*]] = load volatile i8, ptr [[B_PTR:%.*]]
46 ; CHECK-NEXT:    switch i8 [[B]], label [[LOOP_BACKEDGE:%.*]] [
47 ; CHECK-NEXT:    i8 0, label [[EXIT_A_LOOPEXIT:%.*]]
48 ; CHECK-NEXT:    i8 1, label [[EXIT_B_LOOPEXIT:%.*]]
49 ; CHECK-NEXT:    i8 2, label [[LOOP_BACKEDGE]]
50 ; CHECK-NEXT:    i8 3, label [[EXIT_A_LOOPEXIT]]
51 ; CHECK-NEXT:    i8 4, label [[LOOP_BACKEDGE]]
52 ; CHECK-NEXT:    i8 5, label [[EXIT_A_LOOPEXIT]]
53 ; CHECK-NEXT:    i8 6, label [[LOOP_BACKEDGE]]
54 ; CHECK-NEXT:    ]
55 ; CHECK:       loop.backedge:
56 ; CHECK-NEXT:    br label [[LOOP]]
57 ; CHECK:       exit.a.loopexit:
58 ; CHECK-NEXT:    br label [[EXIT_A]]
59 ; CHECK:       exit.a:
60 ; CHECK-NEXT:    ret void
61 ; CHECK:       exit.b.loopexit:
62 ; CHECK-NEXT:    br label [[EXIT_B]]
63 ; CHECK:       exit.b:
64 ; CHECK-NEXT:    ret void
66 entry:
67   switch i8 %a, label %loop [
68   i8 0, label %exit.a
69   i8 1, label %exit.b
70   ]
72 loop:
73   %b = load volatile i8, ptr %b.ptr
74   switch i8 %b, label %loop [
75   i8 0, label %exit.a
76   i8 1, label %exit.b
77   i8 2, label %loop
78   i8 3, label %exit.a
79   i8 4, label %loop
80   i8 5, label %exit.a
81   i8 6, label %loop
82   ]
84 exit.a:
85   ret void
87 exit.b:
88   ret void
91 ; Check that we leave already dedicated exits alone when forming dedicated exit
92 ; blocks.
93 define void @test_pre_existing_dedicated_exits(i1 %a, ptr %ptr) {
94 ; CHECK-LABEL: @test_pre_existing_dedicated_exits(
95 ; CHECK-NEXT:  entry:
96 ; CHECK-NEXT:    br i1 [[A:%.*]], label [[LOOP_PH:%.*]], label [[NON_DEDICATED_EXIT:%.*]]
97 ; CHECK:       loop.ph:
98 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
99 ; CHECK:       loop.header:
100 ; CHECK-NEXT:    [[C1:%.*]] = load volatile i1, ptr [[PTR:%.*]]
101 ; CHECK-NEXT:    br i1 [[C1]], label [[LOOP_BODY1:%.*]], label [[DEDICATED_EXIT1:%.*]]
102 ; CHECK:       loop.body1:
103 ; CHECK-NEXT:    [[C2:%.*]] = load volatile i1, ptr [[PTR]]
104 ; CHECK-NEXT:    br i1 [[C2]], label [[LOOP_BODY2:%.*]], label [[NON_DEDICATED_EXIT_LOOPEXIT:%.*]]
105 ; CHECK:       loop.body2:
106 ; CHECK-NEXT:    [[C3:%.*]] = load volatile i1, ptr [[PTR]]
107 ; CHECK-NEXT:    br i1 [[C3]], label [[LOOP_BACKEDGE:%.*]], label [[DEDICATED_EXIT2:%.*]]
108 ; CHECK:       loop.backedge:
109 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
110 ; CHECK:       dedicated_exit1:
111 ; CHECK-NEXT:    ret void
112 ; CHECK:       dedicated_exit2:
113 ; CHECK-NEXT:    ret void
114 ; CHECK:       non_dedicated_exit.loopexit:
115 ; CHECK-NEXT:    br label [[NON_DEDICATED_EXIT]]
116 ; CHECK:       non_dedicated_exit:
117 ; CHECK-NEXT:    ret void
119 entry:
120   br i1 %a, label %loop.ph, label %non_dedicated_exit
122 loop.ph:
123   br label %loop.header
125 loop.header:
126   %c1 = load volatile i1, ptr %ptr
127   br i1 %c1, label %loop.body1, label %dedicated_exit1
129 loop.body1:
130   %c2 = load volatile i1, ptr %ptr
131   br i1 %c2, label %loop.body2, label %non_dedicated_exit
133 loop.body2:
134   %c3 = load volatile i1, ptr %ptr
135   br i1 %c3, label %loop.backedge, label %dedicated_exit2
137 loop.backedge:
138   br label %loop.header
140 dedicated_exit1:
141   ret void
142 ; Check that there isn't a split loop exit.
144 dedicated_exit2:
145   ret void
146 ; Check that there isn't a split loop exit.
148 non_dedicated_exit:
149   ret void
152 ; Check that we form what dedicated exits we can even when some exits are
153 ; reached via indirectbr which precludes forming dedicated exits.
154 define void @test_form_some_dedicated_exits_despite_indirectbr(i8 %a, ptr %ptr, ptr %addr.ptr) {
155 ; CHECK-LABEL: @test_form_some_dedicated_exits_despite_indirectbr(
156 ; CHECK-NEXT:  entry:
157 ; CHECK-NEXT:    switch i8 [[A:%.*]], label [[LOOP_PH:%.*]] [
158 ; CHECK-NEXT:    i8 0, label [[EXIT_A:%.*]]
159 ; CHECK-NEXT:    i8 1, label [[EXIT_B:%.*]]
160 ; CHECK-NEXT:    i8 2, label [[EXIT_C:%.*]]
161 ; CHECK-NEXT:    ]
162 ; CHECK:       loop.ph:
163 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
164 ; CHECK:       loop.header:
165 ; CHECK-NEXT:    [[ADDR1:%.*]] = load volatile ptr, ptr [[ADDR_PTR:%.*]]
166 ; CHECK-NEXT:    indirectbr ptr [[ADDR1]], [label [[LOOP_BODY1:%.*]], label %exit.a]
167 ; CHECK:       loop.body1:
168 ; CHECK-NEXT:    [[B:%.*]] = load volatile i8, ptr [[PTR:%.*]]
169 ; CHECK-NEXT:    switch i8 [[B]], label [[LOOP_BODY2:%.*]] [
170 ; CHECK-NEXT:    i8 0, label [[EXIT_A]]
171 ; CHECK-NEXT:    i8 1, label [[EXIT_B_LOOPEXIT:%.*]]
172 ; CHECK-NEXT:    i8 2, label [[EXIT_C]]
173 ; CHECK-NEXT:    ]
174 ; CHECK:       loop.body2:
175 ; CHECK-NEXT:    [[ADDR2:%.*]] = load volatile ptr, ptr [[ADDR_PTR]]
176 ; CHECK-NEXT:    indirectbr ptr [[ADDR2]], [label [[LOOP_BACKEDGE:%.*]], label %exit.c]
177 ; CHECK:       loop.backedge:
178 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
179 ; CHECK:       exit.a:
180 ; CHECK-NEXT:    ret void
181 ; CHECK:       exit.b.loopexit:
182 ; CHECK-NEXT:    br label [[EXIT_B]]
183 ; CHECK:       exit.b:
184 ; CHECK-NEXT:    ret void
185 ; CHECK:       exit.c:
186 ; CHECK-NEXT:    ret void
188 entry:
189   switch i8 %a, label %loop.ph [
190   i8 0, label %exit.a
191   i8 1, label %exit.b
192   i8 2, label %exit.c
193   ]
195 loop.ph:
196   br label %loop.header
198 loop.header:
199   %addr1 = load volatile ptr, ptr %addr.ptr
200   indirectbr ptr %addr1, [label %loop.body1, label %exit.a]
202 loop.body1:
203   %b = load volatile i8, ptr %ptr
204   switch i8 %b, label %loop.body2 [
205   i8 0, label %exit.a
206   i8 1, label %exit.b
207   i8 2, label %exit.c
208   ]
210 loop.body2:
211   %addr2 = load volatile ptr, ptr %addr.ptr
212   indirectbr ptr %addr2, [label %loop.backedge, label %exit.c]
214 loop.backedge:
215   br label %loop.header
217 exit.a:
218   ret void
219 ; Check that there isn't a split loop exit.
221 exit.b:
222   ret void
224 exit.c:
225   ret void
226 ; Check that there isn't a split loop exit.