|
| 1 | +// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s |
| 2 | + |
| 3 | +llvm.func @free(!llvm.ptr) |
| 4 | +llvm.func @malloc(i64) -> !llvm.ptr |
| 5 | +omp.private {type = private} @box.heap_privatizer0 : !llvm.ptr alloc { |
| 6 | +^bb0(%arg0: !llvm.ptr): |
| 7 | + %0 = llvm.mlir.constant(1 : i32) : i32 |
| 8 | + %10 = llvm.getelementptr %arg0[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 9 | + %1 = llvm.load %10 : !llvm.ptr -> i64 |
| 10 | + %7 = llvm.alloca %0 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> : (i32) -> !llvm.ptr |
| 11 | + %17 = llvm.call @malloc(%1) {fir.must_be_heap = true, in_type = i32} : (i64) -> !llvm.ptr |
| 12 | + %22 = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 13 | + %37 = llvm.insertvalue %17, %22[0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 14 | + llvm.store %37, %7 : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, !llvm.ptr |
| 15 | + omp.yield(%7 : !llvm.ptr) |
| 16 | +} dealloc { |
| 17 | +^bb0(%arg0: !llvm.ptr): |
| 18 | + %6 = llvm.mlir.constant(0 : i64) : i64 |
| 19 | + %8 = llvm.getelementptr %arg0[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 20 | + %9 = llvm.load %8 : !llvm.ptr -> !llvm.ptr |
| 21 | + llvm.call @free(%9) : (!llvm.ptr) -> () |
| 22 | + omp.yield |
| 23 | +} |
| 24 | +omp.private {type = private} @box.heap_privatizer1 : !llvm.ptr alloc { |
| 25 | +^bb0(%arg0: !llvm.ptr): |
| 26 | + %0 = llvm.mlir.constant(1 : i32) : i32 |
| 27 | + %10 = llvm.getelementptr %arg0[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 28 | + %1 = llvm.load %10 : !llvm.ptr -> i64 |
| 29 | + %7 = llvm.alloca %0 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> : (i32) -> !llvm.ptr |
| 30 | + %17 = llvm.call @malloc(%1) {fir.must_be_heap = true, in_type = i32} : (i64) -> !llvm.ptr |
| 31 | + %22 = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 32 | + %37 = llvm.insertvalue %17, %22[0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 33 | + llvm.store %37, %7 : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, !llvm.ptr |
| 34 | + omp.yield(%7 : !llvm.ptr) |
| 35 | +} dealloc { |
| 36 | +^bb0(%arg0: !llvm.ptr): |
| 37 | + %6 = llvm.mlir.constant(0 : i64) : i64 |
| 38 | + %8 = llvm.getelementptr %arg0[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 39 | + %9 = llvm.load %8 : !llvm.ptr -> !llvm.ptr |
| 40 | + llvm.call @free(%9) : (!llvm.ptr) -> () |
| 41 | + omp.yield |
| 42 | +} |
| 43 | +llvm.func @target_allocatable_(%arg0: !llvm.ptr {fir.bindc_name = "lb"}, %arg1: !llvm.ptr {fir.bindc_name = "ub"}, %arg2: !llvm.ptr {fir.bindc_name = "l"}) attributes {fir.internal_name = "_QPtarget_allocatable"} { |
| 44 | + %6 = llvm.mlir.constant(1 : i64) : i64 |
| 45 | + %7 = llvm.alloca %6 x i32 {bindc_name = "mapped_var"} : (i64) -> !llvm.ptr |
| 46 | + %13 = llvm.alloca %6 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> {bindc_name = "alloc_var0"} : (i64) -> !llvm.ptr |
| 47 | + %14 = llvm.alloca %6 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> {bindc_name = "alloc_var1"} : (i64) -> !llvm.ptr |
| 48 | + %53 = omp.map.info var_ptr(%7 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "mapped_var"} |
| 49 | + %54 = omp.map.info var_ptr(%13 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(to) capture(ByRef) -> !llvm.ptr |
| 50 | + %55 = omp.map.info var_ptr(%14 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(to) capture(ByRef) -> !llvm.ptr |
| 51 | + omp.target map_entries(%53 -> %arg3, %54 -> %arg4, %55 ->%arg5 : !llvm.ptr, !llvm.ptr, !llvm.ptr) private(@box.heap_privatizer0 %13 -> %arg6 [map_idx=1], @box.heap_privatizer1 %14 -> %arg7 [map_idx=2]: !llvm.ptr, !llvm.ptr) { |
| 52 | + %64 = llvm.mlir.constant(1 : i32) : i32 |
| 53 | + %65 = llvm.alloca %64 x !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> {alignment = 8 : i64} : (i32) -> !llvm.ptr |
| 54 | + %67 = llvm.alloca %64 x i32 : (i32) -> !llvm.ptr |
| 55 | + %66 = llvm.mlir.constant(19 : i32) : i32 |
| 56 | + %69 = llvm.mlir.constant(10 : i32) : i32 |
| 57 | + llvm.store %64, %arg3 : i32, !llvm.ptr |
| 58 | + llvm.store %69, %67 : i32, !llvm.ptr |
| 59 | + %75 = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 60 | + %90 = llvm.insertvalue %67, %75[0] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> |
| 61 | + llvm.store %90, %65 : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, !llvm.ptr |
| 62 | + %91 = llvm.mlir.zero : !llvm.ptr |
| 63 | + %92 = llvm.call @_FortranAAssign(%arg6, %65, %91, %66) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i32) -> !llvm.struct<()> |
| 64 | + %93 = llvm.call @_FortranAAssign(%arg7, %65, %91, %66) : (!llvm.ptr, !llvm.ptr, !llvm.ptr, i32) -> !llvm.struct<()> |
| 65 | + omp.terminator |
| 66 | + } |
| 67 | + llvm.return |
| 68 | +} |
| 69 | + |
| 70 | + |
| 71 | +llvm.func @_FortranAAssign(!llvm.ptr, !llvm.ptr, !llvm.ptr, i32) -> !llvm.struct<()> attributes {fir.runtime, sym_visibility = "private"} |
| 72 | + |
| 73 | +// The first set of checks ensure that we are calling the offloaded function |
| 74 | +// with the right arguments, especially the second argument which needs to |
| 75 | +// be a memory reference to the descriptor for the privatized allocatable |
| 76 | +// CHECK: define void @target_allocatable_ |
| 77 | +// CHECK-NOT: define internal void |
| 78 | +// CHECK: %[[DESC_ALLOC0:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1 |
| 79 | +// CHECK: %[[DESC_ALLOC1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1 |
| 80 | +// CHECK: call void @__omp_offloading_[[OFFLOADED_FUNCTION:.*]](ptr {{[^,]+}}, |
| 81 | +// CHECK-SAME: ptr %[[DESC_ALLOC0]], ptr %[[DESC_ALLOC1]]) |
| 82 | + |
| 83 | +// CHECK: define internal void @__omp_offloading_[[OFFLOADED_FUNCTION]] |
| 84 | +// CHECK-SAME: (ptr {{[^,]+}}, ptr %[[DESCRIPTOR_ARG0:[^,]+]], |
| 85 | +// CHECK-SAME: ptr %[[DESCRIPTOR_ARG1:.*]]) { |
| 86 | +// CHECK: %[[I0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8 }, |
| 87 | +// CHECK-SAME: ptr %[[DESCRIPTOR_ARG0]], i32 0, i32 1 |
| 88 | +// CHECK: %[[MALLOC_ARG0:.*]] = load i64, ptr %[[I0]] |
| 89 | +// CHECK: %[[PRIV_DESC0:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 } |
| 90 | +// CHECK: %[[HEAP_PTR0:.*]] = call ptr @malloc(i64 %[[MALLOC_ARG0]]) |
| 91 | +// CHECK: %[[TMP0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8 } |
| 92 | +// CHECK-SAME: undef, ptr %[[HEAP_PTR0]], 0 |
| 93 | +// CHECK: store { ptr, i64, i32, i8, i8, i8, i8 } %[[TMP0]], ptr %[[PRIV_DESC0]] |
| 94 | + |
| 95 | +// CHECK: %[[I1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8 }, |
| 96 | +// CHECK-SAME: ptr %[[DESCRIPTOR_ARG1]], i32 0, i32 1 |
| 97 | +// CHECK: %[[MALLOC_ARG1:.*]] = load i64, ptr %[[I1]] |
| 98 | +// CHECK: %[[PRIV_DESC1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 } |
| 99 | +// CHECK: %[[HEAP_PTR1:.*]] = call ptr @malloc(i64 %[[MALLOC_ARG1]]) |
| 100 | +// CHECK: %[[TMP1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8 } |
| 101 | +// CHECK-SAME: undef, ptr %[[HEAP_PTR1]], 0 |
| 102 | +// CHECK: store { ptr, i64, i32, i8, i8, i8, i8 } %[[TMP1]], ptr %[[PRIV_DESC1]] |
| 103 | + |
| 104 | +// CHECK: call {} @_FortranAAssign(ptr %[[PRIV_DESC0]] |
| 105 | +// CHECK: call {} @_FortranAAssign(ptr %[[PRIV_DESC1]] |
| 106 | + |
| 107 | +// CHECK: %[[PTR0:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8 }, |
| 108 | +// CHECK-SAME: ptr %[[PRIV_DESC0]], i32 0, i32 0 |
| 109 | +// CHECK: %[[HEAP_MEMREF0:.*]] = load ptr, ptr %[[PTR0]] |
| 110 | +// CHECK: call void @free(ptr %[[HEAP_MEMREF0]]) |
| 111 | +// CHECK: %[[PTR1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8 }, |
| 112 | +// CHECK-SAME: ptr %[[PRIV_DESC1]], i32 0, i32 0 |
| 113 | +// CHECK: %[[HEAP_MEMREF1:.*]] = load ptr, ptr %[[PTR1]] |
| 114 | +// CHECK: call void @free(ptr %[[HEAP_MEMREF1]]) |
0 commit comments