245 lines · plain
1// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s2 3omp.private {type = private} @simple_var.privatizer : i324 5llvm.func @target_map_single_private() attributes {fir.internal_name = "_QPtarget_map_single_private"} {6 %0 = llvm.mlir.constant(1 : i64) : i647 %1 = llvm.alloca %0 x i32 {bindc_name = "simple_var"} : (i64) -> !llvm.ptr8 %3 = llvm.alloca %0 x i32 {bindc_name = "a"} : (i64) -> !llvm.ptr9 %4 = llvm.mlir.constant(2 : i32) : i3210 llvm.store %4, %3 : i32, !llvm.ptr11 %5 = omp.map.info var_ptr(%3 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = "a"}12 omp.target map_entries(%5 -> %arg0 : !llvm.ptr) private(@simple_var.privatizer %1 -> %arg1 : !llvm.ptr) {13 %6 = llvm.mlir.constant(10 : i32) : i3214 %7 = llvm.load %arg0 : !llvm.ptr -> i3215 %8 = llvm.add %7, %6 : i3216 llvm.store %8, %arg1 : i32, !llvm.ptr17 omp.terminator18 }19 llvm.return20}21 22omp.private {type = private} @n.privatizer : f3223 24llvm.func @target_map_2_privates() attributes {fir.internal_name = "_QPtarget_map_2_privates"} {25 %0 = llvm.mlir.constant(1 : i64) : i6426 %1 = llvm.alloca %0 x i32 {bindc_name = "simple_var"} : (i64) -> !llvm.ptr27 %3 = llvm.alloca %0 x f32 {bindc_name = "n"} : (i64) -> !llvm.ptr28 %5 = llvm.alloca %0 x i32 {bindc_name = "a"} : (i64) -> !llvm.ptr29 %6 = llvm.mlir.constant(2 : i32) : i3230 llvm.store %6, %5 : i32, !llvm.ptr31 %7 = omp.map.info var_ptr(%5 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = "a"}32 omp.target map_entries(%7 -> %arg0 : !llvm.ptr) private(@simple_var.privatizer %1 -> %arg1, @n.privatizer %3 -> %arg2 : !llvm.ptr, !llvm.ptr) {33 %8 = llvm.mlir.constant(1.100000e+01 : f32) : f3234 %9 = llvm.mlir.constant(10 : i32) : i3235 %10 = llvm.load %arg0 : !llvm.ptr -> i3236 %11 = llvm.add %10, %9 : i3237 llvm.store %11, %arg1 : i32, !llvm.ptr38 %12 = llvm.load %arg1 : !llvm.ptr -> i3239 %13 = llvm.sitofp %12 : i32 to f3240 %14 = llvm.fadd %13, %8 {fastmathFlags = #llvm.fastmath<contract>} : f3241 llvm.store %14, %arg2 : f32, !llvm.ptr42 omp.terminator43 }44 llvm.return45}46 47 48// An entirely artifical privatizer that is meant to check multi-block49// privatizers. The idea here is to prove that we set the correct50// insertion points for the builder when generating, first, LLVM IR for the51// privatizer and then for the actual target region.52omp.private {type = private} @multi_block.privatizer : f32 init {53^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):54 llvm.br ^bb155 56^bb1:57 omp.yield(%arg1 : !llvm.ptr)58}59 60llvm.func @target_op_private_multi_block(%arg0: !llvm.ptr) {61 omp.target private(@multi_block.privatizer %arg0 -> %arg2 : !llvm.ptr) {62 %0 = llvm.load %arg2 : !llvm.ptr -> f3263 omp.terminator64 }65 llvm.return66}67 68// Descriptors are needed for CHARACTER arrays and their type is69// !fir.boxchar<KIND>. When such arrays are used in the private construct, the70// privatizer takes a !fir.boxchar<KIND> as input. This type is lowered to71// !llvm.struct<(ptr, i64)>. This is unique because with other types of data,72// typically, the privatizer funtion takes a !llvm.ptr. Now, on the host side,73// we map the descriptor using the map clause of the omp.target op. Map clauses74// take only !llvm.ptr types. This means, we have a case where the descriptor is75// mapped by its pointer whereas the privatizer function expects the descriptor76// by value. So, we have this test to ensure that the compiler correctly loads77// from the mapped pointer before passing that to the privatizer function.78omp.private {type = private} @_QFtarget_boxcharEchar_var_private_boxchar_c8xU : !llvm.struct<(ptr, i64)> init {79^bb0(%arg0: !llvm.struct<(ptr, i64)>, %arg1: !llvm.struct<(ptr, i64)>):80 %0 = llvm.extractvalue %arg0[0] : !llvm.struct<(ptr, i64)>81 %1 = llvm.extractvalue %arg0[1] : !llvm.struct<(ptr, i64)>82 %2 = llvm.mlir.constant(1 : i64) : i6483 %3 = llvm.alloca %1 x i8 {bindc_name = "char_var", pinned} : (i64) -> !llvm.ptr84 %4 = llvm.mlir.undef : !llvm.struct<(ptr, i64)>85 %5 = llvm.insertvalue %3, %4[0] : !llvm.struct<(ptr, i64)>86 %6 = llvm.insertvalue %1, %5[1] : !llvm.struct<(ptr, i64)>87 omp.yield(%6 : !llvm.struct<(ptr, i64)>)88}89llvm.func @target_boxchar_(%arg0: !llvm.ptr {fir.bindc_name = "l"}) attributes {fir.internal_name = "_QPtarget_boxchar"} {90 %0 = llvm.mlir.constant(1 : i64) : i6491 %1 = llvm.alloca %0 x i32 {bindc_name = "mapped_var"} : (i64) -> !llvm.ptr92 %3 = llvm.alloca %0 x !llvm.struct<(ptr, i64)> : (i64) -> !llvm.ptr93 %4 = llvm.mlir.constant(0 : i64) : i6494 %5 = llvm.load %arg0 : !llvm.ptr -> i6495 %6 = llvm.icmp "sgt" %5, %4 : i6496 %7 = llvm.select %6, %5, %4 : i1, i6497 %9 = llvm.alloca %7 x i8 {bindc_name = "char_var"} : (i64) -> !llvm.ptr98 %10 = llvm.mlir.undef : !llvm.struct<(ptr, i64)>99 %11 = llvm.insertvalue %9, %10[0] : !llvm.struct<(ptr, i64)>100 %12 = llvm.insertvalue %7, %11[1] : !llvm.struct<(ptr, i64)>101 %13 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "mapped_var"}102 llvm.store %12, %3 : !llvm.struct<(ptr, i64)>, !llvm.ptr103 %14 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.struct<(ptr, i64)>) map_clauses(to) capture(ByRef) -> !llvm.ptr104 omp.target map_entries(%13 -> %arg1, %14 -> %arg2 : !llvm.ptr, !llvm.ptr) private(@_QFtarget_boxcharEchar_var_private_boxchar_c8xU %12 -> %arg3 [map_idx=1] : !llvm.struct<(ptr, i64)>) {105 %15 = llvm.mlir.constant(0 : index) : i64106 %16 = llvm.mlir.constant(32 : i8) : i8107 %17 = llvm.mlir.constant(1 : index) : i64108 %18 = llvm.mlir.constant(false) : i1109 %19 = llvm.mlir.constant(5 : index) : i64110 %20 = llvm.mlir.constant(5 : i32) : i32111 %21 = llvm.extractvalue %arg3[0] : !llvm.struct<(ptr, i64)>112 %22 = llvm.extractvalue %arg3[1] : !llvm.struct<(ptr, i64)>113 llvm.store %20, %arg1 : i32, !llvm.ptr114 %23 = llvm.mlir.addressof @_QQclX68656C6C6F : !llvm.ptr115 %24 = llvm.icmp "slt" %22, %19 : i64116 %25 = llvm.select %24, %22, %19 : i1, i64117 llvm.call @llvm.memmove.p0.p0.i64(%21, %23, %25, %18) : (!llvm.ptr, !llvm.ptr, i64, i1) -> ()118 %26 = llvm.sub %22, %17 : i64119 %27 = llvm.mlir.undef : !llvm.array<1 x i8>120 %28 = llvm.insertvalue %16, %27[0] : !llvm.array<1 x i8>121 %29 = llvm.sub %26, %25 : i64122 %30 = llvm.add %29, %17 : i64123 llvm.br ^bb1(%25, %30 : i64, i64)124 ^bb1(%31: i64, %32: i64): // 2 preds: ^bb0, ^bb2125 %33 = llvm.icmp "sgt" %32, %15 : i64126 llvm.cond_br %33, ^bb2, ^bb3127 ^bb2: // pred: ^bb1128 %34 = llvm.getelementptr %21[%31] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<1 x i8>129 llvm.store %28, %34 : !llvm.array<1 x i8>, !llvm.ptr130 %35 = llvm.add %31, %17 : i64131 %36 = llvm.sub %32, %17 : i64132 llvm.br ^bb1(%35, %36 : i64, i64)133 ^bb3: // pred: ^bb1134 omp.terminator135 }136 llvm.return137}138llvm.mlir.global linkonce constant @_QQclX68656C6C6F() comdat(@__llvm_comdat::@_QQclX68656C6C6F) {addr_space = 0 : i32} : !llvm.array<5 x i8> {139 %0 = llvm.mlir.constant("hello") : !llvm.array<5 x i8>140 llvm.return %0 : !llvm.array<5 x i8>141}142llvm.comdat @__llvm_comdat {143 llvm.comdat_selector @_QQclX68656C6C6F any144}145llvm.func @llvm.memmove.p0.p0.i64(!llvm.ptr, !llvm.ptr, i64, i1) attributes {sym_visibility = "private"}146 147 148 149omp.private {type = firstprivate} @sf.firstprivate : f32 copy {150^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):151 %0 = llvm.load %arg0 : !llvm.ptr -> f32152 llvm.store %0, %arg1 : f32, !llvm.ptr153 omp.yield(%arg1 : !llvm.ptr)154}155omp.private {type = firstprivate} @sv.firstprivate : i32 copy {156^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):157 %0 = llvm.load %arg0 : !llvm.ptr -> i32158 llvm.store %0, %arg1 : i32, !llvm.ptr159 omp.yield(%arg1 : !llvm.ptr)160}161llvm.func @target_firstprivate_() attributes {fir.internal_name = "_QPtarget_firstprivate"} {162 %0 = llvm.mlir.constant(1 : i64) : i64163 %sv = llvm.alloca %0 x i32 {bindc_name = "sv"} : (i64) -> !llvm.ptr164 %sf = llvm.alloca %0 x f32 {bindc_name = "sf"} : (i64) -> !llvm.ptr165 %6 = omp.map.info var_ptr(%sv : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr166 %7 = omp.map.info var_ptr(%sf : !llvm.ptr, f32) map_clauses(to) capture(ByRef) -> !llvm.ptr167 omp.target map_entries(%6 -> %arg0, %7 -> %arg1 : !llvm.ptr, !llvm.ptr) private(@sv.firstprivate %sv -> %arg2 [map_idx=0], @sf.firstprivate %sf -> %arg3 [map_idx=1] : !llvm.ptr, !llvm.ptr) {168 %8 = llvm.mlir.constant(2.000000e+00 : f64) : f64169 %9 = llvm.mlir.constant(10 : i32) : i32170 %10 = llvm.load %arg2 : !llvm.ptr -> i32171 %11 = llvm.add %10, %9 : i32172 llvm.store %11, %arg2 : i32, !llvm.ptr173 %12 = llvm.load %arg3 : !llvm.ptr -> f32174 %13 = llvm.fpext %12 : f32 to f64175 %14 = llvm.fadd %13, %8 {fastmathFlags = #llvm.fastmath<contract>} : f64176 %15 = llvm.fptrunc %14 : f64 to f32177 llvm.store %15, %arg3 : f32, !llvm.ptr178 omp.terminator179 }180 llvm.return181}182// CHECK: define void @target_map_single_private() {183// CHECK: call void @__omp_offloading_[[MAP_SINGLE_PRIVATE_OFFLOADED_FUNCTION:.*]](ptr {{.*}})184// CHECK: define void @target_map_2_privates() {185// CHECK: call void @__omp_offloading_[[MAP_2_PRIVATES_OFFLOADED_FUNCTION:.*]](ptr {{.*}})186// CHECK: define void @target_op_private_multi_block187// CHECK: call void @__omp_offloading_[[PRIVATE_MULTI_BLOCK_OFFLOADED_FUNCTION:.*]]()188// CHECK: define void @target_boxchar_189// CHECK: call void @__omp_offloading_[[BOXCHAR_OFFLOADED_FUNCTION:.*]](ptr {{.*}}, ptr {{.*}})190// CHECK: define void @target_firstprivate_()191// CHECK: call void @__omp_offloading_[[SIMPLE_OFFLOADED_FUNCTION:.*]](ptr {{.*}}, ptr {{.*}})192 193// CHECK: define internal void @__omp_offloading_[[MAP_SINGLE_PRIVATE_OFFLOADED_FUNCTION]]194// CHECK: %[[PRIV_ALLOC:.*]] = alloca i32, align 4195// CHECK: %[[ADD:.*]] = add i32 {{.*}}, 10196// CHECK: store i32 %[[ADD]], ptr %[[PRIV_ALLOC]], align 4197 198 199 200 201// CHECK: define internal void @__omp_offloading_[[MAP_2_PRIVATES_OFFLOADED_FUNCTION]]202// CHECK: %[[PRIV_I32_ALLOC:.*]] = alloca i32, align 4203// CHECK: %[[PRIV_FLOAT_ALLOC:.*]] = alloca float, align 4204// CHECK: %[[ADD_I32:.*]] = add i32 {{.*}}, 10205// CHECK: store i32 %[[ADD_I32]], ptr %[[PRIV_I32_ALLOC]], align 4206// CHECK: %[[LOAD_I32_AGAIN:.*]] = load i32, ptr %[[PRIV_I32_ALLOC]], align 4207// CHECK: %[[CAST_TO_FLOAT:.*]] = sitofp i32 %[[LOAD_I32_AGAIN]] to float208// CHECK: %[[ADD_FLOAT:.*]] = fadd contract float %[[CAST_TO_FLOAT]], 1.100000e+01209// CHECK: store float %[[ADD_FLOAT]], ptr %[[PRIV_FLOAT_ALLOC]], align 4210 211// CHECK: define internal void @__omp_offloading_[[PRIVATE_MULTI_BLOCK_OFFLOADED_FUNCTION]]212// CHECK: %[[PRIV_ALLOC:.*]] = alloca float, align 4213// CHECK: %[[PHI_ALLOCA:.*]] = phi ptr [ %[[PRIV_ALLOC]], {{.*}} ]214// CHECK: %[[RESULT:.*]] = load float, ptr %[[PHI_ALLOCA]], align 4215 216 217// CHECK: define internal void @__omp_offloading_[[BOXCHAR_OFFLOADED_FUNCTION]](ptr %{{[^,]+}}, ptr %[[MAPPED_ARG:.*]]) {218// CHECK: %[[BOXCHAR:.*]] = load { ptr, i64 }, ptr %[[MAPPED_ARG]]219// CHECK: %[[BOXCHAR_PTR:.*]] = extractvalue { ptr, i64 } %[[BOXCHAR]], 0220// CHECK: %[[BOXCHAR_i64:.*]] = extractvalue { ptr, i64 } %[[BOXCHAR]], 1221// CHECK: %[[MEM_ALLOC:.*]] = alloca i8, i64 %[[BOXCHAR_i64]]222// CHECK: %[[PRIV_BOXCHAR0:.*]] = insertvalue { ptr, i64 } undef, ptr %[[MEM_ALLOC]], 0223// CHECK: %[[PRIV_BOXCHAR1:.*]] = insertvalue { ptr, i64 } %[[PRIV_BOXCHAR0]], i64 %[[BOXCHAR_i64]], 1224 225 226// CHECK: define internal void @__omp_offloading_[[SIMPLE_OFFLOADED_FUNCTION]](ptr %[[SV:.*]], ptr %[[SF:.*]])227// CHECK: entry:228// CHECK-NEXT: %[[SV_PRIV_ALLOCA:.*]] = alloca i32, align 4229// CHECK-NEXT: %[[SF_PRIV_ALLOCA:.*]] = alloca float, align 4230// CHECK: omp.private.copy:231// CHECK-NEXT: %[[INIT_SV:.*]] = load i32, ptr %[[SV]], align 4232// CHECK-NEXT: store i32 %[[INIT_SV]], ptr %[[SV_PRIV_ALLOCA]], align 4233// CHECK: %[[INIT_SF:.*]] = load float, ptr %[[SF]], align 4234// CHECK-NEXT store float %[[INIT_SF]], ptr %[[SF_PRIV_ALLOCA]], align 4235// CHECK: omp.target236// CHECK: %[[LOAD_SV:.*]] = load i32, ptr %[[SV_PRIV_ALLOCA]], align 4237// CHECK-NEXT: %[[ADD_SV:.*]] = add i32 %[[LOAD_SV]], 10238// CHECK-NEXT: store i32 %[[ADD_SV]], ptr %[[SV_PRIV_ALLOCA]], align 4239// CHECK: %[[LOAD_SF:.*]] = load float, ptr %[[SF_PRIV_ALLOCA]], align 4240// CHECK-NEXT: %[[SF_EXT:.*]] = fpext float %[[LOAD_SF]] to double241// CHECK-NEXT: %[[ADD_SF:.*]] = fadd contract double %[[SF_EXT]], 2.000000e+00242// CHECK-NEXT: %[[TRUNC_SF:.*]] = fptrunc double %[[ADD_SF]] to float243// CHECK-NEXT: store float %[[TRUNC_SF]], ptr %[[SF_PRIV_ALLOCA]], align 4244 245