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