1! RUN: bbc -emit-fir -o - %s | FileCheck %s
2! RUN: %flang_fc1 -emit-fir -o - %s | FileCheck %s
3
4! Tests for unstructured loops.
5
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
10subroutine simple_unstructured()
11  integer :: i
12  do i=1,100
13    goto 404
14    404 continue
15  end do
16end subroutine
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:.*]]
29! CHECK: ^[[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:.*]]
34! CHECK: ^[[BODY]]:
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]]
43! CHECK: ^[[EXIT]]:
44! CHECK:   return
45
46! Test an unstructured loop with a step. Mostly similar to the previous one.
47! Only difference is a non-unit step.
48subroutine simple_unstructured_with_step()
49  integer :: i
50  do i=1,100,2
51    goto 404
52    404 continue
53  end do
54end subroutine
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:.*]]
67! CHECK: ^[[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:.*]]
72! CHECK: ^[[BODY]]:
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]]
81! CHECK: ^[[EXIT]]:
82! CHECK:   return
83
84! Test a three nested unstructured loop. Three nesting is the basic case where
85! we have loops that are neither innermost or outermost.
86subroutine nested_unstructured()
87  integer :: i, j, k
88  do i=1,100
89    do j=1,200
90      do k=1,300
91        goto 404
92        404 continue
93      end do
94    end do
95  end do
96end subroutine
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]]:
176! CHECK:   return
177
178! Test the existence of a structured loop inside an unstructured loop.
179! Only minimal checks are inserted for the structured loop.
180subroutine nested_structured_in_unstructured()
181  integer :: i, j
182  do i=1,100
183    do j=1,100
184    end do
185    goto 404
186    404 continue
187  end do
188end subroutine
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:.*]]
207! CHECK: ^[[BODY]]:
208! CHECK:   %{{.*}} = fir.do_loop %[[J_INDEX:.*]] = %{{.*}} to %{{.*}} step %{{.*}} -> index {
209! CHECK:     %[[J_INDEX_CVT:.*]] = fir.convert %[[J_INDEX]] : (index) -> i32
210! CHECK:     fir.store %[[J_INDEX_CVT]] to %[[LOOP_VAR_J_REF]] : !fir.ref<i32>
211! CHECK:   }
212! CHECK:   %[[TRIP_VAR_I:.*]] = fir.load %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
213! CHECK:   %[[C1_3:.*]] = arith.constant 1 : i32
214! CHECK:   %[[TRIP_VAR_I_NEXT:.*]] = arith.subi %[[TRIP_VAR_I]], %[[C1_3]] : i32
215! CHECK:   fir.store %[[TRIP_VAR_I_NEXT]] to %[[TRIP_VAR_I_REF]] : !fir.ref<i32>
216! CHECK:   %[[LOOP_VAR_I:.*]] = fir.load %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
217! CHECK:   %[[LOOP_VAR_I_NEXT:.*]] = arith.addi %[[LOOP_VAR_I]], %c1_i32_0 : i32
218! CHECK:   fir.store %[[LOOP_VAR_I_NEXT]] to %[[LOOP_VAR_I_REF]] : !fir.ref<i32>
219! CHECK:   cf.br ^[[HEADER]]
220! CHECK: ^[[EXIT]]:
221! CHECK:   return
222