xref: /llvm-project/flang/test/Lower/OpenMP/unstructured.f90 (revision 937cbce14c9aa956342a9c818c26a8a557802843)
1! Test unstructured code adjacent to and inside OpenMP constructs.
2
3! RUN: bbc %s -fopenmp -emit-hlfir -o "-" \
4! RUN: | FileCheck %s
5
6! CHECK-LABEL: func @_QPss1{{.*}} {
7! CHECK:   br ^bb1
8! CHECK: ^bb1:  // 2 preds: ^bb0, ^bb4
9! CHECK:   cond_br %{{[0-9]*}}, ^bb2, ^bb5
10! CHECK: ^bb2:  // pred: ^bb1
11! CHECK:   cond_br %{{[0-9]*}}, ^bb3, ^bb4
12! CHECK: ^bb4:  // pred: ^bb2
13! CHECK:   fir.call @_FortranAioBeginExternalListOutput
14! CHECK:   br ^bb1
15! CHECK: ^bb5:  // 2 preds: ^bb1, ^bb3
16! CHECK:   omp.master  {
17! CHECK:     @_FortranAioBeginExternalListOutput
18! CHECK:     omp.terminator
19! CHECK:   }
20! CHECK:   @_FortranAioBeginExternalListOutput
21! CHECK: }
22subroutine ss1(n) ! unstructured code followed by a structured OpenMP construct
23  do i = 1, 3
24    if (i .eq. n) exit
25    print*, 'ss1-A', i
26  enddo
27  !$omp master
28    print*, 'ss1-B', i
29  !$omp end master
30  print*
31end
32
33! CHECK-LABEL: func @_QPss2{{.*}} {
34! CHECK:   omp.master  {
35! CHECK:     @_FortranAioBeginExternalListOutput
36! CHECK:     br ^bb1
37! CHECK:   ^bb1:  // 2 preds: ^bb0, ^bb4
38! CHECK:     cond_br %{{[0-9]*}}, ^bb2, ^bb5
39! CHECK:   ^bb2:  // pred: ^bb1
40! CHECK:     cond_br %{{[0-9]*}}, ^bb3, ^bb4
41! CHECK:   ^bb3:  // pred: ^bb2
42! CHECK:     @_FortranAioBeginExternalListOutput
43! CHECK:     br ^bb1
44! CHECK:   ^bb5:  // 2 preds: ^bb1, ^bb3
45! CHECK:     omp.terminator
46! CHECK:   }
47! CHECK:   @_FortranAioBeginExternalListOutput
48! CHECK:   @_FortranAioBeginExternalListOutput
49! CHECK: }
50subroutine ss2(n) ! unstructured OpenMP construct; loop exit inside construct
51  !$omp master
52    print*, 'ss2-A', n
53    do i = 1, 3
54      if (i .eq. n) exit
55      print*, 'ss2-B', i
56    enddo
57  !$omp end master
58  print*, 'ss2-C', i
59  print*
60end
61
62! CHECK-LABEL: func @_QPss3{{.*}} {
63! CHECK:   omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
64! CHECK:     %[[ALLOCA_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned}
65! CHECK:     %[[K_DECL:.*]]:2 = hlfir.declare %[[ALLOCA_K]] {uniq_name = "_QFss3Ek"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
66
67! CHECK:     br ^bb1
68! CHECK:   ^bb1:  // 2 preds: ^bb0, ^bb3
69! CHECK:     cond_br %{{[0-9]*}}, ^bb2, ^bb4
70! CHECK:   ^bb2:  // pred: ^bb1
71
72! CHECK:     %[[ALLOCA_2:.*]] = fir.alloca i32 {{{.*}}, pinned, {{.*}}}
73! CHECK:     %[[OMP_LOOP_K_DECL:.*]]:2 = hlfir.declare %[[ALLOCA_2]] {uniq_name = "_QFss3Ek"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
74! CHECK:     omp.wsloop {
75! CHECK:       omp.loop_nest (%[[ARG1:.*]]) : {{.*}} {
76! CHECK:         fir.store %[[ARG1]] to %[[OMP_LOOP_K_DECL]]#1 : !fir.ref<i32>
77! CHECK:         @_FortranAioBeginExternalListOutput
78! CHECK:         %[[LOAD_1:.*]] = fir.load %[[OMP_LOOP_K_DECL]]#0 : !fir.ref<i32>
79! CHECK:         @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD_1]])
80! CHECK:         omp.yield
81! CHECK:       }
82! CHECK:     }
83
84! CHECK:     %[[ALLOCA_1:.*]] = fir.alloca i32 {{{.*}}, pinned, {{.*}}}
85! CHECK:     %[[OMP_LOOP_J_DECL:.*]]:2 = hlfir.declare %[[ALLOCA_1]] {uniq_name = "_QFss3Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
86
87! CHECK:     omp.wsloop {
88! CHECK:       omp.loop_nest (%[[ARG2:.*]]) : {{.*}} {
89! CHECK:         fir.store %[[ARG2]] to %[[OMP_LOOP_J_DECL]]#1 : !fir.ref<i32>
90! CHECK:         br ^bb1
91! CHECK:       ^bb2:  // 2 preds: ^bb1, ^bb5
92! CHECK:         cond_br %{{[0-9]*}}, ^bb3, ^bb6
93! CHECK:       ^bb3:  // pred: ^bb2
94! CHECK:         cond_br %{{[0-9]*}}, ^bb4, ^bb5
95! CHECK:       ^bb4:  // pred: ^bb3
96! CHECK:         @_FortranAioBeginExternalListOutput
97! CHECK:         %[[LOAD_2:.*]] = fir.load %[[K_DECL]]#0 : !fir.ref<i32>
98! CHECK:         @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD_2]])
99! CHECK:         br ^bb2
100! CHECK:       ^bb6:  // 2 preds: ^bb2, ^bb4
101! CHECK:         omp.yield
102! CHECK:       }
103! CHECK:     }
104! CHECK:     br ^bb1
105! CHECK:   ^bb4:  // pred: ^bb1
106! CHECK:     omp.terminator
107! CHECK:   }
108! CHECK: }
109subroutine ss3(n) ! nested unstructured OpenMP constructs
110  !$omp parallel
111    do i = 1, 3
112      !$omp do
113        do k = 1, 3
114          print*, 'ss3-A', k
115        enddo
116      !$omp end do
117      !$omp do
118        do j = 1, 3
119          do k = 1, 3
120            if (k .eq. n) exit
121            print*, 'ss3-B', k
122          enddo
123        enddo
124      !$omp end do
125    enddo
126  !$omp end parallel
127end
128
129! CHECK-LABEL: func @_QPss4{{.*}} {
130! CHECK:       omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
131! CHECK:         %[[ALLOCA:.*]] = fir.alloca i32 {{{.*}}, pinned, uniq_name = "_QFss4Ej"}
132! CHECK:         %[[OMP_LOOP_J_DECL:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFss4Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
133! CHECK:         omp.wsloop {
134! CHECK-NEXT:      omp.loop_nest (%[[ARG:.*]]) : {{.*}} {
135! CHECK:             fir.store %[[ARG]] to %[[OMP_LOOP_J_DECL]]#1 : !fir.ref<i32>
136! CHECK:             %[[COND:.*]] = arith.cmpi eq, %{{.*}}, %{{.*}}
137! CHECK:             %[[COND_XOR:.*]] = arith.xori %[[COND]], %{{.*}}
138! CHECK:             fir.if %[[COND_XOR]] {
139! CHECK:              @_FortranAioBeginExternalListOutput
140! CHECK:              %[[LOAD:.*]] = fir.load %[[OMP_LOOP_J_DECL]]#0 : !fir.ref<i32>
141! CHECK:              @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD]])
142! CHECK:             }
143! CHECK-NEXT:        omp.yield
144! CHECK-NEXT:      }
145! CHECK-NEXT:    }
146! CHECK:         omp.terminator
147! CHECK-NEXT:  }
148subroutine ss4(n) ! CYCLE in OpenMP wsloop constructs
149  !$omp parallel
150    do i = 1, 3
151      !$omp do
152        do j = 1, 3
153           if (j .eq. n) cycle
154           print*, 'ss4', j
155        enddo
156      !$omp end do
157    enddo
158  !$omp end parallel
159end
160
161! CHECK-LABEL: func @_QPss5() {
162! CHECK:  omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
163! CHECK:    omp.wsloop {
164! CHECK:      omp.loop_nest {{.*}} {
165! CHECK:        br ^[[BB1:.*]]
166! CHECK:      ^[[BB1]]:
167! CHECK:        br ^[[BB2:.*]]
168! CHECK:      ^[[BB2]]:
169! CHECK:        cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
170! CHECK:      ^[[BB3]]:
171! CHECK:        cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB3:.*]]
172! CHECK:      ^[[BB4]]:
173! CHECK:        br ^[[BB6]]
174! CHECK:      ^[[BB3]]:
175! CHECK:        br ^[[BB2]]
176! CHECK:      ^[[BB6]]:
177! CHECK:        omp.yield
178! CHECK:      }
179! CHECK:    }
180! CHECK:    omp.terminator
181! CHECK:  }
182subroutine ss5() ! EXIT inside OpenMP wsloop (inside parallel)
183  integer :: x
184  !$omp parallel private(x)
185    !$omp do
186      do j = 1, 3
187        x = j * i
188        do k = 1, 3
189          if (k .eq. n) exit
190          x = k
191          x = x + k
192        enddo
193        x = j - 222
194      enddo
195    !$omp end do
196  !$omp end parallel
197end
198
199! CHECK-LABEL: func @_QPss6() {
200! CHECK:  omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
201! CHECK:    br ^[[BB1_OUTER:.*]]
202! CHECK:  ^[[BB1_OUTER]]:
203! CHECK:    cond_br %{{.*}}, ^[[BB2_OUTER:.*]], ^[[BB3_OUTER:.*]]
204! CHECK:  ^[[BB2_OUTER]]:
205! CHECK:    omp.wsloop {
206! CHECK:      omp.loop_nest {{.*}} {
207! CHECK:        br ^[[BB1:.*]]
208! CHECK:      ^[[BB1]]:
209! CHECK:        br ^[[BB2:.*]]
210! CHECK:      ^[[BB2]]:
211! CHECK:        cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
212! CHECK:      ^[[BB3]]:
213! CHECK:        cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB5:.*]]
214! CHECK:      ^[[BB4]]:
215! CHECK:        br ^[[BB6]]
216! CHECK:      ^[[BB5]]
217! CHECK:        br ^[[BB2]]
218! CHECK:      ^[[BB6]]:
219! CHECK:        omp.yield
220! CHECK:      }
221! CHECK:    }
222! CHECK:    br ^[[BB1_OUTER]]
223! CHECK:  ^[[BB3_OUTER]]:
224! CHECK:    omp.terminator
225! CHECK:  }
226subroutine ss6() ! EXIT inside OpenMP wsloop in a do loop (inside parallel)
227  integer :: x
228  !$omp parallel private(x)
229    do i = 1, 3
230      !$omp do
231        do j = 1, 3
232          x = j * i
233          do k = 1, 3
234            if (k .eq. n) exit
235            x = k
236            x = x + k
237          enddo
238          x = j - 222
239        enddo
240      !$omp end do
241    enddo
242  !$omp end parallel
243end
244
245! CHECK-LABEL: func @_QPss7() {
246! CHECK: br ^[[BB1_OUTER:.*]]
247! CHECK: ^[[BB1_OUTER]]:
248! CHECK:   cond_br %{{.*}}, ^[[BB2_OUTER:.*]], ^[[BB3_OUTER:.*]]
249! CHECK-NEXT: ^[[BB2_OUTER:.*]]:
250! CHECK:   omp.parallel  {
251! CHECK:     omp.wsloop {
252! CHECK:       omp.loop_nest {{.*}} {
253! CHECK:         br ^[[BB1:.*]]
254! CHECK-NEXT:       ^[[BB1]]:
255! CHECK:         br ^[[BB2:.*]]
256! CHECK-NEXT:       ^[[BB2]]:
257! CHECK:         cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
258! CHECK-NEXT:       ^[[BB3]]:
259! CHECK:         cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB5:.*]]
260! CHECK-NEXT:       ^[[BB4]]:
261! CHECK:         br ^[[BB6]]
262! CHECK-NEXT:       ^[[BB5]]:
263! CHECK:         br ^[[BB2]]
264! CHECK-NEXT:       ^[[BB6]]:
265! CHECK:         omp.yield
266! CHECK:       }
267! CHECK:     }
268! CHECK:     omp.terminator
269! CHECK:   }
270! CHECK:   br ^[[BB1_OUTER]]
271! CHECK-NEXT: ^[[BB3_OUTER]]:
272! CHECK-NEXT:   return
273subroutine ss7() ! EXIT inside OpenMP parallel do (inside do loop)
274  integer :: x
275    do i = 1, 3
276      !$omp parallel do private(x)
277        do j = 1, 3
278          x = j * i
279          do k = 1, 3
280            if (k .eq. n) exit
281            x = k
282            x = x + k
283          enddo
284        enddo
285      !$omp end parallel do
286    enddo
287end
288
289! CHECK-LABEL: func @_QPss8() {
290! CHECK:  omp.parallel  {
291! CHECK:    omp.wsloop {
292! CHECK:      omp.loop_nest {{.*}} {
293! CHECK:        br ^[[BB1:.*]]
294! CHECK-NEXT:      ^[[BB1]]:
295! CHECK:        br ^[[BB2:.*]]
296! CHECK:      ^[[BB2]]:
297! CHECK:        cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB6:.*]]
298! CHECK:      ^[[BB3]]:
299! CHECK:        cond_br %{{.*}}, ^[[BB4:.*]], ^[[BB5:.*]]
300! CHECK:      ^[[BB4]]:
301! CHECK-NEXT:      br ^[[BB6]]
302! CHECK:      ^[[BB5]]:
303! CHECK:        br ^[[BB2]]
304! CHECK-NEXT:      ^[[BB6]]:
305! CHECK:        omp.yield
306! CHECK:      }
307! CHECK:    }
308! CHECK:    omp.terminator
309! CHECK:  }
310subroutine ss8() ! EXIT inside OpenMP parallel do
311  integer :: x
312      !$omp parallel do private(x)
313        do j = 1, 3
314          x = j * i
315          do k = 1, 3
316            if (k .eq. n) exit
317            x = k
318            x = x + k
319          enddo
320        enddo
321      !$omp end parallel do
322end
323
324! CHECK-LABEL: func @_QPss9() {
325! CHECK:    omp.parallel  {
326! CHECK-NEXT: omp.parallel private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
327! CHECK:      br ^[[BB1:.*]]
328! CHECK:         ^[[BB1]]:
329! CHECK:      cond_br %{{.*}}, ^[[BB2:.*]], ^[[BB5:.*]]
330! CHECK-NEXT:    ^[[BB2]]:
331! CHECK:      cond_br %{{.*}}, ^[[BB3:.*]], ^[[BB4:.*]]
332! CHECK-NEXT:    ^[[BB3]]:
333! CHECK-NEXT:    br ^[[BB5]]
334! CHECK-NEXT:    ^[[BB4]]:
335! CHECK:      br ^[[BB1]]
336! CHECK-NEXT:    ^[[BB5]]:
337! CHECK:      omp.terminator
338! CHECK-NEXT:    }
339! CHECK:    omp.terminator
340! CHECK-NEXT  }
341! CHECK: }
342subroutine ss9() ! EXIT inside OpenMP parallel (inside parallel)
343  integer :: x
344  !$omp parallel
345  !$omp parallel private(x)
346    do k = 1, 3
347      if (k .eq. n) exit
348      x = k
349      x = x + k
350    end do
351  !$omp end parallel
352  !$omp end parallel
353end
354
355! CHECK-LABEL: func @_QQmain
356program p
357  call ss1(2)
358  call ss2(2)
359  call ss3(2)
360  call ss4(2)
361  call ss5()
362  call ss6()
363  call ss7()
364  call ss8()
365  call ss9()
366end
367