brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.1 KiB · d46bfa5 Raw
308 lines · plain
1// Test code-gen for `omp.parallel` ops with delayed privatizers (i.e. using2// `omp.private` ops).3 4// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s5 6llvm.func @parallel_op_1_private(%arg0: !llvm.ptr) {7  omp.parallel private(@x.privatizer %arg0 -> %arg2 : !llvm.ptr) {8    %0 = llvm.load %arg2 : !llvm.ptr -> f329    omp.terminator10  }11  llvm.return12}13 14// CHECK-LABEL: @parallel_op_1_private15// CHECK-SAME: (ptr %[[ORIG:.*]]) {16// CHECK: %[[OMP_PAR_ARG:.*]] = alloca { ptr }, align 817// CHECK: %[[ORIG_GEP:.*]] = getelementptr { ptr }, ptr %[[OMP_PAR_ARG]], i32 0, i32 018// CHECK: store ptr %[[ORIG]], ptr %[[ORIG_GEP]], align 819// CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 1, ptr @parallel_op_1_private..omp_par, ptr %[[OMP_PAR_ARG]])20// CHECK: }21 22// CHECK-LABEL: void @parallel_op_1_private..omp_par23// CHECK-SAME: (ptr noalias %{{.*}}, ptr noalias %{{.*}}, ptr %[[ARG:.*]])24// CHECK: %[[ORIG_PTR_PTR:.*]] = getelementptr { ptr }, ptr %[[ARG]], i32 0, i32 025// CHECK: %[[ORIG_PTR:.*]] = load ptr, ptr %[[ORIG_PTR_PTR]], align 826 27// Check that the privatizer alloc region was inlined properly.28// CHECK: %[[PRIV_ALLOC:.*]] = alloca float, align 429// CHECK: %[[ORIG_VAL:.*]] = load float, ptr %[[ORIG_PTR]], align 430// CHECK: store float %[[ORIG_VAL]], ptr %[[PRIV_ALLOC]], align 431// CHECK-NEXT: br32 33// Check that the privatized value is used (rather than the original one).34// CHECK: load float, ptr %[[PRIV_ALLOC]], align 435// CHECK: }36 37llvm.func @parallel_op_2_privates(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {38  omp.parallel private(@x.privatizer %arg0 -> %arg2, @y.privatizer %arg1 -> %arg3 : !llvm.ptr, !llvm.ptr) {39    %0 = llvm.load %arg2 : !llvm.ptr -> f3240    %1 = llvm.load %arg3 : !llvm.ptr -> i3241    omp.terminator42  }43  llvm.return44}45 46// CHECK-LABEL: @parallel_op_2_privates47// CHECK-SAME: (ptr %[[ORIG1:.*]], ptr %[[ORIG2:.*]]) {48// CHECK: %[[OMP_PAR_ARG:.*]] = alloca { ptr, ptr }, align 849// CHECK: %[[ORIG1_GEP:.*]] = getelementptr { ptr, ptr }, ptr %[[OMP_PAR_ARG]], i32 0, i32 050// CHECK: store ptr %[[ORIG1]], ptr %[[ORIG1_GEP]], align 851// CHECK: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 1, ptr @parallel_op_2_privates..omp_par, ptr %[[OMP_PAR_ARG]])52// CHECK: }53 54// CHECK-LABEL: void @parallel_op_2_privates..omp_par55// CHECK-SAME: (ptr noalias %{{.*}}, ptr noalias %{{.*}}, ptr %[[ARG:.*]])56// CHECK: %[[ORIG1_PTR_PTR:.*]] = getelementptr { ptr, ptr }, ptr %[[ARG]], i32 0, i32 057// CHECK: %[[ORIG1_PTR:.*]] = load ptr, ptr %[[ORIG1_PTR_PTR]], align 858// CHECK: %[[ORIG2_PTR_PTR:.*]] = getelementptr { ptr, ptr }, ptr %[[ARG]], i32 0, i32 159// CHECK: %[[ORIG2_PTR:.*]] = load ptr, ptr %[[ORIG2_PTR_PTR]], align 860 61// Check that the privatizer alloc region was inlined properly.62// CHECK: %[[PRIV1_ALLOC:.*]] = alloca float, align 463// CHECK: %[[PRIV2_ALLOC:.*]] = alloca i32, align 464// CHECK: %[[ORIG1_VAL:.*]] = load float, ptr %[[ORIG1_PTR]], align 465// CHECK: store float %[[ORIG1_VAL]], ptr %[[PRIV1_ALLOC]], align 466// CHECK: %[[ORIG2_VAL:.*]] = load i32, ptr %[[ORIG2_PTR]], align 467// CHECK: store i32 %[[ORIG2_VAL]], ptr %[[PRIV2_ALLOC]], align 468// CHECK-NEXT: br69 70// Check that the privatized value is used (rather than the original one).71// CHECK: load float, ptr %[[PRIV1_ALLOC]], align 472// CHECK: load i32, ptr %[[PRIV2_ALLOC]], align 473// CHECK: }74 75omp.private {type = private} @x.privatizer : f32 init {76^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):77  %c1 = llvm.mlir.constant(1 : i32) : i3278  %1 = llvm.load %arg0 : !llvm.ptr -> f3279  llvm.store %1, %arg1 : f32, !llvm.ptr80  omp.yield(%arg1 : !llvm.ptr)81}82 83omp.private {type = private} @y.privatizer : i32 init {84^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):85  %c1 = llvm.mlir.constant(1 : i32) : i3286  %1 = llvm.load %arg0 : !llvm.ptr -> i3287  llvm.store %1, %arg1 : i32, !llvm.ptr88  omp.yield(%arg1 : !llvm.ptr)89}90 91// -----92 93llvm.func @parallel_op_private_multi_block(%arg0: !llvm.ptr) {94  omp.parallel private(@multi_block.privatizer %arg0 -> %arg2 : !llvm.ptr) {95    %0 = llvm.load %arg2 : !llvm.ptr -> f3296    omp.terminator97  }98  llvm.return99}100 101// CHECK-LABEL: define internal void @parallel_op_private_multi_block..omp_par102// CHECK: omp.par.entry:103// CHECK:  %[[ORIG_PTR_PTR:.*]] = getelementptr { ptr }, ptr %{{.*}}, i32 0, i32 0104// CHECK:  %[[ORIG_PTR:.*]] = load ptr, ptr %[[ORIG_PTR_PTR]], align 8105// CHECK:  %[[PRIV_ALLOC:.*]] = alloca float, align 4106// CHECK-NEXT:   br label %[[PAR_REG:.*]]107 108// CHECK: [[PAR_REG]]:109// CHECK:  br label %omp.private.init110 111// CHECK: omp.private.init:112// CHECK:   br label %[[PRIV_BB1:.*]]113 114// Check contents of the first block in the `init` region.115// CHECK: [[PRIV_BB1]]:116// CHECK-NEXT:   br label %[[PRIV_BB2:.*]]117 118// Check contents of the second block in the `init` region.119// CHECK: [[PRIV_BB2]]:120// CHECK-NEXT:   %[[ORIG_PTR2:.*]] = phi ptr [ %[[ORIG_PTR]], %[[PRIV_BB1]] ]121// CHECK-NEXT:   %[[PRIV_ALLOC2:.*]] = phi ptr [ %[[PRIV_ALLOC]], %[[PRIV_BB1]] ]122// CHECK-NEXT:   %[[ORIG_VAL:.*]] = load float, ptr %[[ORIG_PTR2]], align 4123// CHECK-NEXT:   store float %[[ORIG_VAL]], ptr %[[PRIV_ALLOC2]], align 4124// CHECK-NEXT:   br label %[[PRIV_CONT:.*]]125 126// Check that the privatizer's continuation block yileds the private clone's127// address.128// CHECK: [[PRIV_CONT]]:129// CHECK-NEXT:   %[[PRIV_ALLOC3:.*]] = phi ptr [ %[[PRIV_ALLOC2]], %[[PRIV_BB2]] ]130// CHECK-NEXT:   br label %[[PAR_REG2:.*]]131 132// Check that the body of the parallel region loads from the private clone.133// CHECK: [[PAR_REG2]]:134// CHECK:        %{{.*}} = load float, ptr %[[PRIV_ALLOC3]], align 4135 136omp.private {type = private} @multi_block.privatizer : f32 init {137^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):138  llvm.br ^bb1(%arg0, %arg1 : !llvm.ptr, !llvm.ptr)139 140^bb1(%arg2: !llvm.ptr, %arg3: !llvm.ptr):141  %1 = llvm.load %arg2 : !llvm.ptr -> f32142  llvm.store %1, %arg3 : f32, !llvm.ptr143  omp.yield(%arg3 : !llvm.ptr)144}145 146// Tests fix for Fujitsu test suite test: 0007_0019.f90: the147// `llvm.mlir.addressof` op needs access to the parent module when lowering148// from the LLVM dialect to LLVM IR. If such op is used inside an `omp.private`149// op instance that was not created/cloned inside the module, we would get a150// seg fault due to trying to access a null pointer.151 152// CHECK-LABEL: define internal void @lower_region_with_addressof..omp_par153// CHECK:         omp.par.region:154// CHECK:           br label %[[PAR_REG_BEG:.*]]155// CHECK:         [[PAR_REG_BEG]]:156// CHECK:           call void @bar(ptr getelementptr (i8, ptr @_QQfoo, i64 888))157// CHECK:           call void @bar(ptr getelementptr (i8, ptr @_QQfoo, i64 1776))158llvm.func @lower_region_with_addressof() {159  %0 = llvm.mlir.constant(1 : i64) : i64160  %1 = llvm.alloca %0 x f64 {bindc_name = "u1"} : (i64) -> !llvm.ptr161  omp.parallel private(@_QFlower_region_with_addressof_privatizer %1 -> %arg0 : !llvm.ptr) {162    %c0 = llvm.mlir.constant(111 : i64) : i64163    %2 = llvm.getelementptr %arg0[%c0] : (!llvm.ptr, i64) -> !llvm.ptr, f64164    llvm.call @bar(%2) : (!llvm.ptr) -> ()165 166    %c1 = llvm.mlir.constant(222 : i64) : i64167    %3 = llvm.mlir.addressof @_QQfoo: !llvm.ptr168    %4 = llvm.getelementptr %3[%c1] : (!llvm.ptr, i64) -> !llvm.ptr, f64169    llvm.call @bar(%4) : (!llvm.ptr) -> ()170    omp.terminator171  }172 173  llvm.return174}175 176omp.private {type = private} @_QFlower_region_with_addressof_privatizer : !llvm.ptr init {177^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):178  %0 = llvm.mlir.addressof @_QQfoo: !llvm.ptr179  omp.yield(%0 : !llvm.ptr)180}181 182llvm.mlir.global linkonce constant @_QQfoo() {addr_space = 0 : i32} : !llvm.array<3 x i8> {183  %0 = llvm.mlir.constant("foo") : !llvm.array<3 x i8>184  llvm.return %0 : !llvm.array<3 x i8>185}186 187llvm.func @bar(!llvm.ptr)188 189 190// Tests fix for Fujitsu test suite test: 0275_0032.f90. The MLIR to LLVM191// translation logic assumed that reduction arguments to an `omp.parallel`192// op are always the last set of arguments to the op. However, this is a193// wrong assumption since private args come afterward. This tests the fix194// that we access the different sets of args properly.195 196// CHECK-LABEL: define internal void @private_and_reduction_..omp_par197// CHECK-DAG:    %[[PRV_ALLOC:.*]] = alloca float, align 4198// CHECK-DAG:     %[[RED_ALLOC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, i64 1, align 8199 200// CHECK:         omp.par.region:201// CHECK:           br label %omp.reduction.init202// CHECK:         omp.reduction.init:203// CHECK:           br label %[[PAR_REG_BEG:.*]]204// CHECK:         [[PAR_REG_BEG]]:205// CHECK-NEXT:      %{{.*}} = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[RED_ALLOC]], align 8206// CHECK-NEXT:      store float 8.000000e+00, ptr %[[PRV_ALLOC]], align 4207 208llvm.func @private_and_reduction_() attributes {fir.internal_name = "_QPprivate_and_reduction", frame_pointer = #llvm.framePointerKind<all>, target_cpu = "x86-64"} {209  %0 = llvm.mlir.constant(1 : i64) : i64210  %1 = llvm.alloca %0 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> : (i64) -> !llvm.ptr211  %2 = llvm.alloca %0 x f32 {bindc_name = "to_priv"} : (i64) -> !llvm.ptr212  omp.parallel private(@privatizer.part %2 -> %arg1 : !llvm.ptr) reduction(byref @reducer.part %1 -> %arg0 : !llvm.ptr) {213    %3 = llvm.load %arg0 : !llvm.ptr -> !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>214    %4 = llvm.mlir.constant(8.000000e+00 : f32) : f32215    llvm.store %4, %arg1 : f32, !llvm.ptr216    omp.terminator217  }218  llvm.return219}220 221omp.private {type = private} @privatizer.part : f32222 223omp.declare_reduction @reducer.part : !llvm.ptr alloc {224  %0 = llvm.mlir.constant(1 : i64) : i64225  %1 = llvm.alloca %0 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> : (i64) -> !llvm.ptr226  omp.yield(%1 : !llvm.ptr)227} init {228^bb0(%mold: !llvm.ptr, %alloc: !llvm.ptr):229  omp.yield(%alloc : !llvm.ptr)230} combiner {231^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):232  omp.yield(%arg0 : !llvm.ptr)233}  cleanup {234^bb0(%arg0: !llvm.ptr):235  omp.yield236}237 238// -----239 240llvm.func @_QPequivalence() {241  %0 = llvm.mlir.constant(1 : i64) : i64242  %1 = llvm.alloca %0 x !llvm.array<4 x i8> : (i64) -> !llvm.ptr243  %2 = llvm.mlir.constant(0 : index) : i64244  %3 = llvm.getelementptr %1[0, %2] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<4 x i8>245  omp.parallel private(@_QFequivalenceEx_firstprivate_ptr_f32 %3 -> %arg0 : !llvm.ptr) {246    %4 = llvm.mlir.constant(3.140000e+00 : f32) : f32247    llvm.store %4, %arg0 : f32, !llvm.ptr248    omp.terminator249  }250  llvm.return251}252 253omp.private {type = firstprivate} @_QFequivalenceEx_firstprivate_ptr_f32 : f32 copy {254^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):255  %0 = llvm.load %arg0 : !llvm.ptr -> f32256  llvm.store %0, %arg1 : f32, !llvm.ptr257  omp.yield(%arg1 : !llvm.ptr)258}259 260// CHECK: define internal void @_QPequivalence..omp_par261// CHECK-NOT: define {{.*}} @{{.*}}262// CHECK:   %[[PRIV_ALLOC:.*]] = alloca float, align 4263// CHECK:   %[[HOST_VAL:.*]] = load float, ptr %{{.*}}, align 4264// Test that we initialize the firstprivate variable.265// CHECK:   store float %[[HOST_VAL]], ptr %[[PRIV_ALLOC]], align 4266// Test that we inlined the body of the parallel region.267// CHECK:   store float 0x{{.*}}, ptr %[[PRIV_ALLOC]], align 4268 269// -----270 271omp.private {type = private} @_QFEi_private_i32 : i32272llvm.func @_QPprivate_alloc_with_switch() {273  %0 = llvm.mlir.constant(1 : i32) : i32274  %1 = llvm.mlir.constant(30 : i32) : i32275  %2 = llvm.mlir.constant(1 : i64) : i64276  %3 = llvm.alloca %2 x i32 {bindc_name = "n"} : (i64) -> !llvm.ptr277  %4 = llvm.alloca %2 x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr278  llvm.store %0, %3 : i32, !llvm.ptr279  %5 = llvm.load %3 : !llvm.ptr -> i32280  llvm.switch %5 : i32, ^bb1 [281    1: ^bb1,282    2: ^bb2283  ]284^bb1:  // 2 preds: ^bb0, ^bb0285  omp.simd private(@_QFEi_private_i32 %4 -> %arg0 : !llvm.ptr) {286    omp.loop_nest (%arg1) : i32 = (%0) to (%1) inclusive step (%0) {287      llvm.store %arg1, %arg0 : i32, !llvm.ptr288      omp.yield289    }290  }291  llvm.br ^bb2292^bb2:  // 2 preds: ^bb0, ^bb1293  llvm.return294}295 296// CHECK-LABEL: define void @_QPprivate_alloc_with_switch() {297// CHECK:   br label %[[AFTER_ALLOCA_BLOCK:.*]]298// CHECK: [[AFTER_ALLOCA_BLOCK]]:299// CHECK:   switch i32 %{{.*}}, label %[[PRIVATE_INIT_BLOCK:.*]] [300// CHECK:     i32 1, label %[[PRIVATE_INIT_BLOCK]]301// CHECK:     i32 2, label %[[EXIT_BLOCK:.*]]302// CHECK:   ]303// CHECK: [[PRIVATE_INIT_BLOCK]]:304// CHECK: omp.private.init:305// CHECK: omp.simd.region:306// CHECK: [[EXIT_BLOCK]]:307// CHECK:   ret void308