xref: /llvm-project/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 (revision 12ba74e181bd6641b532e271f3bfabf53066b1c0)
1! RUN: %flang_fc1 -fopenmp -emit-llvm %s -o - | FileCheck %s
2
3! Combinational testing of control flow graph and builder insertion points
4! in mlir-to-llvm conversion:
5!   - mixing multiple delayed privatizations and multiple reductions
6!   - multiple blocks in the private alloc region
7!   - private alloc region has to read from the mold variable
8!   - firstprivate
9!   - multiple blocks in the private copy region
10!   - multiple blocks in the reduction init region
11!   - reduction init region has to read from the mold variable
12!   - re-used omp.private ops
13!   - re-used omp.reduction.declare ops
14!   - unstructured code inside of the parallel region
15!   - needs private dealloc region, and this has multiple blocks
16!   - needs reduction cleanup region, and this has multiple blocks
17
18! This maybe belongs in the mlir tests, but what we are doing here is complex
19! enough that I find the kind of minimised mlir code preferred by mlir reviewers
20! hard to read without some fortran here for reference. Nothing like this would
21! be generated by other upstream users of the MLIR OpenMP dialect.
22
23subroutine worst_case(a, b, c, d)
24  real, allocatable :: a(:), b(:), c(:), d(:)
25  integer i
26
27  !$omp parallel firstprivate(a,b) reduction(+:c,d)
28  if (sum(a) == 1) stop 1
29  !$omp end parallel
30end subroutine
31
32! CHECK-LABEL: define internal void @worst_case_..omp_par
33! CHECK-NEXT:  omp.par.entry:
34!                [reduction alloc regions inlined here]
35! CHECK:         br label %omp.private.latealloc
36
37! CHECK:       omp.private.latealloc:                            ; preds = %omp.par.entry
38! CHECK-NEXT:  br label %omp.private.alloc5
39
40! CHECK:       omp.private.alloc5:                               ; preds = %omp.private.latealloc
41!                [begin private alloc for first var]
42!                [read the length from the mold argument]
43!                [if it is non-zero...]
44! CHECK:         br i1 {{.*}}, label %omp.private.alloc6, label %omp.private.alloc7
45
46! CHECK:       omp.private.alloc7:                               ; preds = %omp.private.alloc5
47!                [finish private alloc for first var with zero extent]
48! CHECK:         br label %omp.private.alloc8
49
50! CHECK:       omp.private.alloc8:                               ; preds = %omp.private.alloc6, %omp.private.alloc7
51! CHECK-NEXT:    br label %omp.region.cont4
52
53! CHECK:       omp.region.cont4:                                 ; preds = %omp.private.alloc8
54! CHECK-NEXT:    %{{.*}} = phi ptr
55! CHECK-NEXT:    br label %omp.private.alloc
56
57! CHECK:       omp.private.alloc:                                ; preds = %omp.region.cont4
58!                [begin private alloc for first var]
59!                [read the length from the mold argument]
60!                [if it is non-zero...]
61! CHECK:         br i1 %{{.*}}, label %omp.private.alloc1, label %omp.private.alloc2
62
63! CHECK:       omp.private.alloc2:                               ; preds = %omp.private.alloc
64!                [finish private alloc for second var with zero extent]
65! CHECK:         br label %omp.private.alloc3
66
67! CHECK:       omp.private.alloc3:                               ; preds = %omp.private.alloc1, %omp.private.alloc2
68! CHECK-NEXT:    br label %omp.region.cont
69
70! CHECK:       omp.region.cont:                                  ; preds = %omp.private.alloc3
71! CHECK-NEXT:    %{{.*}} = phi ptr
72! CHECK-NEXT:    br label %omp.private.copy
73
74! CHECK:       omp.private.copy:                                 ; preds = %omp.region.cont
75! CHECK-NEXT:    br label %omp.private.copy10
76
77! CHECK:       omp.private.copy10:                               ; preds = %omp.private.copy
78!                [begin firstprivate copy for first var]
79!                [read the length, is it non-zero?]
80! CHECK:         br i1 %{{.*}}, label %omp.private.copy11, label %omp.private.copy12
81
82! CHECK:       omp.private.copy12:                               ; preds = %omp.private.copy11, %omp.private.copy10
83! CHECK-NEXT:    br label %omp.region.cont9
84
85! CHECK:       omp.region.cont9:                                 ; preds = %omp.private.copy12
86! CHECK-NEXT:    %{{.*}} = phi ptr
87! CHECK-NEXT:    br label %omp.private.copy14
88
89! CHECK:       omp.private.copy14:                               ; preds = %omp.region.cont9
90!                [begin firstprivate copy for second var]
91!                [read the length, is it non-zero?]
92! CHECK:         br i1 %{{.*}}, label %omp.private.copy15, label %omp.private.copy16
93
94! CHECK:       omp.private.copy16:                               ; preds = %omp.private.copy15, %omp.private.copy14
95! CHECK-NEXT:    br label %omp.region.cont13
96
97! CHECK:       omp.region.cont13:                                ; preds = %omp.private.copy16
98! CHECK-NEXT:    %{{.*}} = phi ptr
99! CHECK-NEXT:    br label %omp.region.after_alloca
100
101! CHECK:       omp.region.after_alloca:
102! CHECK-NEXT:    br label %omp.par.region
103
104! CHECK:       omp.par.region:                                   ; preds = %omp.region.after_alloca
105! CHECK-NEXT:    br label %omp.reduction.init
106
107! CHECK:       omp.reduction.init:                               ; preds = %omp.par.region
108!                [deffered stores for results of reduction alloc regions]
109! CHECK:         br label %[[VAL_96:.*]]
110
111! CHECK:       omp.reduction.neutral:                            ; preds = %omp.reduction.init
112!                [start of reduction initialization region]
113!                [null check:]
114! CHECK:         br i1 %{{.*}}, label %omp.reduction.neutral18, label %omp.reduction.neutral19
115
116! CHECK:       omp.reduction.neutral19:                          ; preds = %omp.reduction.neutral
117!                [malloc and assign the default value to the reduction variable]
118! CHECK:         br label %omp.reduction.neutral20
119
120! CHECK:       omp.reduction.neutral20:                          ; preds = %omp.reduction.neutral18, %omp.reduction.neutral19
121! CHECK-NEXT:    br label %omp.region.cont17
122
123! CHECK:       omp.region.cont17:                                ; preds = %omp.reduction.neutral20
124! CHECK-NEXT:    %{{.*}} = phi ptr
125! CHECK-NEXT:    br label %omp.reduction.neutral22
126
127! CHECK:       omp.reduction.neutral22:                          ; preds = %omp.region.cont17
128!                [start of reduction initialization region]
129!                [null check:]
130! CHECK:         br i1 %{{.*}}, label %omp.reduction.neutral23, label %omp.reduction.neutral24
131
132! CHECK:       omp.reduction.neutral24:                          ; preds = %omp.reduction.neutral22
133!                [malloc and assign the default value to the reduction variable]
134! CHECK:         br label %omp.reduction.neutral25
135
136! CHECK:       omp.reduction.neutral25:                          ; preds = %omp.reduction.neutral23, %omp.reduction.neutral24
137! CHECK-NEXT:    br label %omp.region.cont21
138
139! CHECK:       omp.region.cont21:                                ; preds = %omp.reduction.neutral25
140! CHECK-NEXT:    %{{.*}} = phi ptr
141! CHECK-NEXT:    br label %omp.par.region27
142
143! CHECK:       omp.par.region27:                                 ; preds = %omp.region.cont21
144!                [call SUM runtime function]
145!                [if (sum(a) == 1)]
146! CHECK:         br i1 %{{.*}}, label %omp.par.region28, label %omp.par.region29
147
148! CHECK:       omp.par.region29:                                 ; preds = %omp.par.region27
149! CHECK-NEXT:    br label %omp.region.cont26
150
151! CHECK:       omp.region.cont26:                                ; preds = %omp.par.region28, %omp.par.region29
152!                [omp parallel region done, call into the runtime to complete reduction]
153! CHECK:         %[[VAL_233:.*]] = call i32 @__kmpc_reduce(
154! CHECK:         switch i32 %[[VAL_233]], label %reduce.finalize [
155! CHECK-NEXT:      i32 1, label %reduce.switch.nonatomic
156! CHECK-NEXT:      i32 2, label %reduce.switch.atomic
157! CHECK-NEXT:    ]
158
159! CHECK:       reduce.switch.atomic:                             ; preds = %omp.region.cont26
160! CHECK-NEXT:    unreachable
161
162! CHECK:       reduce.switch.nonatomic:                          ; preds = %omp.region.cont26
163! CHECK-NEXT:    %[[red_private_value_0:.*]] = load ptr, ptr %{{.*}}, align 8
164! CHECK-NEXT:    br label %omp.reduction.nonatomic.body
165
166!              [various blocks implementing the reduction]
167
168! CHECK:       omp.region.cont35:                                ; preds =
169! CHECK-NEXT:    %{{.*}} = phi ptr
170! CHECK-NEXT:    call void @__kmpc_end_reduce(
171! CHECK-NEXT:    br label %reduce.finalize
172
173! CHECK:       reduce.finalize:                                  ; preds =
174! CHECK-NEXT:    br label %omp.par.pre_finalize
175
176! CHECK:       omp.par.pre_finalize:                             ; preds = %reduce.finalize
177! CHECK-NEXT:    %{{.*}} = load ptr, ptr
178! CHECK-NEXT:    br label %omp.reduction.cleanup
179
180! CHECK:       omp.reduction.cleanup:                            ; preds = %omp.par.pre_finalize
181!                [null check]
182! CHECK:         br i1 %{{.*}}, label %omp.reduction.cleanup41, label %omp.reduction.cleanup42
183
184! CHECK:       omp.reduction.cleanup42:                          ; preds = %omp.reduction.cleanup41, %omp.reduction.cleanup
185! CHECK-NEXT:    br label %omp.region.cont40
186
187! CHECK:       omp.region.cont40:                                ; preds = %omp.reduction.cleanup42
188! CHECK-NEXT:    %{{.*}} = load ptr, ptr
189! CHECK-NEXT:    br label %omp.reduction.cleanup44
190
191! CHECK:       omp.reduction.cleanup44:                          ; preds = %omp.region.cont40
192!                [null check]
193! CHECK:         br i1 %{{.*}}, label %omp.reduction.cleanup45, label %omp.reduction.cleanup46
194
195! CHECK:       omp.reduction.cleanup46:                          ; preds = %omp.reduction.cleanup45, %omp.reduction.cleanup44
196! CHECK-NEXT:    br label %omp.region.cont43
197
198! CHECK:       omp.region.cont43:                                ; preds = %omp.reduction.cleanup46
199! CHECK-NEXT:    br label %omp.private.dealloc
200
201! CHECK:       omp.private.dealloc:                              ; preds = %omp.region.cont43
202!                [null check]
203! CHECK:         br i1 %{{.*}}, label %omp.private.dealloc48, label %omp.private.dealloc49
204
205! CHECK:       omp.private.dealloc49:                            ; preds = %omp.private.dealloc48, %omp.private.dealloc
206! CHECK-NEXT:    br label %omp.region.cont47
207
208! CHECK:       omp.region.cont47:                                ; preds = %omp.private.dealloc49
209! CHECK-NEXT:    br label %omp.private.dealloc51
210
211! CHECK:       omp.private.dealloc51:                            ; preds = %omp.region.cont47
212!                [null check]
213! CHECK:         br i1 %{{.*}}, label %omp.private.dealloc52, label %omp.private.dealloc53
214
215! CHECK:       omp.private.dealloc53:                            ; preds = %omp.private.dealloc52, %omp.private.dealloc51
216! CHECK-NEXT:    br label %omp.region.cont50
217
218! CHECK:       omp.region.cont50:                                ; preds = %omp.private.dealloc53
219! CHECK-NEXT:    br label %omp.par.outlined.exit.exitStub
220
221! CHECK:       omp.private.dealloc52:                            ; preds = %omp.private.dealloc51
222!                [dealloc memory]
223! CHECK:         br label %omp.private.dealloc53
224
225! CHECK:       omp.private.dealloc48:                            ; preds = %omp.private.dealloc
226!                [dealloc memory]
227! CHECK:         br label %omp.private.dealloc49
228
229! CHECK:       omp.reduction.cleanup45:                          ; preds = %omp.reduction.cleanup44
230! CHECK-NEXT:    call void @free(
231! CHECK-NEXT:    br label %omp.reduction.cleanup46
232
233! CHECK:       omp.reduction.cleanup41:                          ; preds = %omp.reduction.cleanup
234! CHECK-NEXT:    call void @free(
235! CHECK-NEXT:    br label %omp.reduction.cleanup42
236
237! CHECK:       omp.par.region28:                                 ; preds = %omp.par.region27
238! CHECK-NEXT:    call void @_FortranAStopStatement
239
240! CHECK:       omp.reduction.neutral23:                          ; preds = %omp.reduction.neutral22
241!                [source length was zero: finish initializing array]
242! CHECK:         br label %omp.reduction.neutral25
243
244! CHECK:       omp.reduction.neutral18:                          ; preds = %omp.reduction.neutral
245!                [source length was zero: finish initializing array]
246! CHECK:         br label %omp.reduction.neutral20
247
248! CHECK:       omp.private.copy15:                               ; preds = %omp.private.copy14
249!                [source length was non-zero: call assign runtime]
250! CHECK:         br label %omp.private.copy16
251
252! CHECK:       omp.private.copy11:                               ; preds = %omp.private.copy10
253!                [source length was non-zero: call assign runtime]
254! CHECK:         br label %omp.private.copy12
255
256! CHECK:       omp.private.alloc1:                               ; preds = %omp.private.alloc
257!                [var extent was non-zero: malloc a private array]
258! CHECK:         br label %omp.private.alloc3
259
260! CHECK:       omp.private.alloc6:                               ; preds = %omp.private.alloc5
261!                [var extent was non-zero: malloc a private array]
262! CHECK:         br label %omp.private.alloc8
263
264! CHECK:       omp.par.outlined.exit.exitStub:                   ; preds = %omp.region.cont50
265! CHECK-NEXT:    ret void
266