1 ! RUN: bbc -emit-fir -o - %s | FileCheck %s
2 ! RUN: %flang_fc1 -emit-fir -o - %s | FileCheck %s
4 ! Tests for unstructured loops.
6 ! Test a simple unstructured loop. Test for the existence of,
7 ! -> The initialization of the trip-count and loop-variable
8 ! -> The branch to the body or the exit inside the header
9 ! -> The increment of the trip-count and the loop-variable inside the body
10 subroutine simple_unstructured()
17 ! CHECK-LABEL: simple_unstructured
18 ! CHECK: %[[TRIP_VAR_REF:.*]] = fir.alloca i32
19 ! CHECK: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructuredEi"}
20 ! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
21 ! CHECK: %[[HUNDRED:.*]] = arith.constant 100 : i32
22 ! CHECK: %[[STEP_ONE:.*]] = arith.constant 1 : i32
23 ! CHECK: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32
24 ! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP_ONE]] : i32
25 ! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP_ONE]] : i32
26 ! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
27 ! CHECK: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
28 ! CHECK: cf.br ^[[HEADER:.*]]
30 ! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
31 ! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
32 ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
33 ! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
35 ! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
36 ! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
37 ! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32
38 ! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
39 ! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref<i32>
40 ! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP_ONE]] : i32
41 ! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
42 ! CHECK: cf.br ^[[HEADER]]
46 ! Test an unstructured loop with a step. Mostly similar to the previous one.
47 ! Only difference is a non-unit step.
48 subroutine simple_unstructured_with_step()
55 ! CHECK-LABEL: simple_unstructured_with_step
56 ! CHECK: %[[TRIP_VAR_REF:.*]] = fir.alloca i32
57 ! CHECK: %[[LOOP_VAR_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_unstructured_with_stepEi"}
58 ! CHECK: %[[ONE:.*]] = arith.constant 1 : i32
59 ! CHECK: %[[HUNDRED:.*]] = arith.constant 100 : i32
60 ! CHECK: %[[STEP:.*]] = arith.constant 2 : i32
61 ! CHECK: %[[TMP1:.*]] = arith.subi %[[HUNDRED]], %[[ONE]] : i32
62 ! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[STEP]] : i32
63 ! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[STEP]] : i32
64 ! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
65 ! CHECK: fir.store %[[ONE]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
66 ! CHECK: cf.br ^[[HEADER:.*]]
68 ! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
69 ! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
70 ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
71 ! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
73 ! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_REF]] : !fir.ref<i32>
74 ! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
75 ! CHECK: %[[TRIP_VAR_NEXT:.*]] = arith.subi %[[TRIP_VAR]], %[[ONE_1]] : i32
76 ! CHECK: fir.store %[[TRIP_VAR_NEXT]] to %[[TRIP_VAR_REF]] : !fir.ref<i32>
77 ! CHECK: %[[LOOP_VAR:.*]] = fir.load %[[LOOP_VAR_REF]] : !fir.ref<i32>
78 ! CHECK: %[[LOOP_VAR_NEXT:.*]] = arith.addi %[[LOOP_VAR]], %[[STEP]] : i32
79 ! CHECK: fir.store %[[LOOP_VAR_NEXT]] to %[[LOOP_VAR_REF]] : !fir.ref<i32>
80 ! CHECK: cf.br ^[[HEADER]]
84 ! Test a three nested unstructured loop. Three nesting is the basic case where
85 ! we have loops that are neither innermost or outermost.
86 subroutine nested_unstructured()
97 ! CHECK-LABEL: nested_unstructured
98 ! CHECK: %[[TRIP_VAR_K_REF:.*]] = fir.alloca i32
99 ! CHECK: %[[TRIP_VAR_J_REF:.*]] = fir.alloca i32
100 ! CHECK: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32
101 ! CHECK: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_unstructuredEi"}
102 ! CHECK: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_unstructuredEj"}
103 ! CHECK: %[[LOOP_VAR_K_REF:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_unstructuredEk"}
104 ! CHECK: %[[I_START:.*]] = arith.constant 1 : i32
105 ! CHECK: %[[I_END:.*]] = arith.constant 100 : i32
106 ! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
107 ! CHECK: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32
108 ! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32
109 ! CHECK: %[[TRIP_COUNT_I:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32
110 ! CHECK: fir.store %[[TRIP_COUNT_I]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
111 ! CHECK: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
112 ! CHECK: cf.br ^[[HEADER_I:.*]]
113 ! CHECK: ^[[HEADER_I]]:
114 ! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
115 ! CHECK: %[[ZERO_1:.*]] = arith.constant 0 : i32
116 ! CHECK: %[[COND_I:.*]] = arith.cmpi sgt, %[[TRIP_VAR_I]], %[[ZERO_1]] : i32
117 ! CHECK: cf.cond_br %[[COND_I]], ^[[BODY_I:.*]], ^[[EXIT_I:.*]]
118 ! CHECK: ^[[BODY_I]]:
119 ! CHECK: %[[J_START:.*]] = arith.constant 1 : i32
120 ! CHECK: %[[J_END:.*]] = arith.constant 200 : i32
121 ! CHECK: %[[J_STEP:.*]] = arith.constant 1 : i32
122 ! CHECK: %[[TMP3:.*]] = arith.subi %[[J_END]], %[[J_START]] : i32
123 ! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[J_STEP]] : i32
124 ! CHECK: %[[TRIP_COUNT_J:.*]] = arith.divsi %[[TMP4]], %[[J_STEP]] : i32
125 ! CHECK: fir.store %[[TRIP_COUNT_J]] to %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
126 ! CHECK: fir.store %[[J_START]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
127 ! CHECK: cf.br ^[[HEADER_J:.*]]
128 ! CHECK: ^[[HEADER_J]]:
129 ! CHECK: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
130 ! CHECK: %[[ZERO_2:.*]] = arith.constant 0 : i32
131 ! CHECK: %[[COND_J:.*]] = arith.cmpi sgt, %[[TRIP_VAR_J]], %[[ZERO_2]] : i32
132 ! CHECK: cf.cond_br %[[COND_J]], ^[[BODY_J:.*]], ^[[EXIT_J:.*]]
133 ! CHECK: ^[[BODY_J]]:
134 ! CHECK: %[[K_START:.*]] = arith.constant 1 : i32
135 ! CHECK: %[[K_END:.*]] = arith.constant 300 : i32
136 ! CHECK: %[[K_STEP:.*]] = arith.constant 1 : i32
137 ! CHECK: %[[TMP3:.*]] = arith.subi %[[K_END]], %[[K_START]] : i32
138 ! CHECK: %[[TMP4:.*]] = arith.addi %[[TMP3]], %[[K_STEP]] : i32
139 ! CHECK: %[[TRIP_COUNT_K:.*]] = arith.divsi %[[TMP4]], %[[K_STEP]] : i32
140 ! CHECK: fir.store %[[TRIP_COUNT_K]] to %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
141 ! CHECK: fir.store %[[K_START]] to %[[LOOP_VAR_K_REF]] : !fir.ref<i32>
142 ! CHECK: cf.br ^[[HEADER_K:.*]]
143 ! CHECK: ^[[HEADER_K]]:
144 ! CHECK: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
145 ! CHECK: %[[ZERO_2:.*]] = arith.constant 0 : i32
146 ! CHECK: %[[COND_K:.*]] = arith.cmpi sgt, %[[TRIP_VAR_K]], %[[ZERO_2]] : i32
147 ! CHECK: cf.cond_br %[[COND_K]], ^[[BODY_K:.*]], ^[[EXIT_K:.*]]
148 ! CHECK: ^[[BODY_K]]:
149 ! CHECK: %[[TRIP_VAR_K:.*]] = fir.load %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
150 ! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
151 ! CHECK: %[[TRIP_VAR_K_NEXT:.*]] = arith.subi %[[TRIP_VAR_K]], %[[ONE_1]] : i32
152 ! CHECK: fir.store %[[TRIP_VAR_K_NEXT]] to %[[TRIP_VAR_K_REF]] : !fir.ref<i32>
153 ! CHECK: %[[LOOP_VAR_K:.*]] = fir.load %[[LOOP_VAR_K_REF]] : !fir.ref<i32>
154 ! CHECK: %[[LOOP_VAR_K_NEXT:.*]] = arith.addi %[[LOOP_VAR_K]], %[[K_STEP]] : i32
155 ! CHECK: fir.store %[[LOOP_VAR_K_NEXT]] to %[[LOOP_VAR_K_REF]] : !fir.ref<i32>
156 ! CHECK: cf.br ^[[HEADER_K]]
157 ! CHECK: ^[[EXIT_K]]:
158 ! CHECK: %[[TRIP_VAR_J:.*]] = fir.load %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
159 ! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
160 ! CHECK: %[[TRIP_VAR_J_NEXT:.*]] = arith.subi %[[TRIP_VAR_J]], %[[ONE_1]] : i32
161 ! CHECK: fir.store %[[TRIP_VAR_J_NEXT]] to %[[TRIP_VAR_J_REF]] : !fir.ref<i32>
162 ! CHECK: %[[LOOP_VAR_J:.*]] = fir.load %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
163 ! CHECK: %[[LOOP_VAR_J_NEXT:.*]] = arith.addi %[[LOOP_VAR_J]], %[[J_STEP]] : i32
164 ! CHECK: fir.store %[[LOOP_VAR_J_NEXT]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
165 ! CHECK: cf.br ^[[HEADER_J]]
166 ! CHECK: ^[[EXIT_J]]:
167 ! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
168 ! CHECK: %[[ONE_1:.*]] = arith.constant 1 : i32
169 ! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[ONE_1]] : i32
170 ! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
171 ! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
172 ! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %[[I_STEP]] : i32
173 ! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
174 ! CHECK: cf.br ^[[HEADER_I]]
175 ! CHECK: ^[[EXIT_I]]:
178 ! Test the existence of a structured loop inside an unstructured loop.
179 ! Only minimal checks are inserted for the structured loop.
180 subroutine nested_structured_in_unstructured()
189 ! CHECK-LABEL: nested_structured_in_unstructured
190 ! CHECK: %[[TRIP_VAR_I_REF:.*]] = fir.alloca i32
191 ! CHECK: %[[LOOP_VAR_I_REF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFnested_structured_in_unstructuredEi"}
192 ! CHECK: %[[LOOP_VAR_J_REF:.*]] = fir.alloca i32 {bindc_name = "j", uniq_name = "_QFnested_structured_in_unstructuredEj"}
193 ! CHECK: %[[I_START:.*]] = arith.constant 1 : i32
194 ! CHECK: %[[I_END:.*]] = arith.constant 100 : i32
195 ! CHECK: %[[I_STEP:.*]] = arith.constant 1 : i32
196 ! CHECK: %[[TMP1:.*]] = arith.subi %[[I_END]], %[[I_START]] : i32
197 ! CHECK: %[[TMP2:.*]] = arith.addi %[[TMP1]], %[[I_STEP]] : i32
198 ! CHECK: %[[TRIP_COUNT:.*]] = arith.divsi %[[TMP2]], %[[I_STEP]] : i32
199 ! CHECK: fir.store %[[TRIP_COUNT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
200 ! CHECK: fir.store %[[I_START]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
201 ! CHECK: cf.br ^[[HEADER:.*]]
202 ! CHECK: ^[[HEADER]]:
203 ! CHECK: %[[TRIP_VAR:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
204 ! CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
205 ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[TRIP_VAR]], %[[ZERO]] : i32
206 ! CHECK: cf.cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
208 ! CHECK: %{{.*}} = fir.do_loop %[[J_INDEX:[^ ]*]] =
209 ! CHECK-SAME: %{{.*}} to %{{.*}} step %{{[^ ]*}}
210 ! CHECK-SAME: iter_args(%[[J_IV:.*]] = %{{.*}}) -> (index, i32) {
211 ! CHECK: fir.store %[[J_IV]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
213 ! CHECK: %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
214 ! CHECK: %[[C1_3:.*]] = arith.constant 1 : i32
215 ! CHECK: %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32
216 ! CHECK: fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
217 ! CHECK: %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
218 ! CHECK: %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %c1_i32_0 : i32
219 ! CHECK: fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
220 ! CHECK: cf.br ^[[HEADER]]