// RUN: fir-opt --cuf-convert --cuf-allocation-convert %s | FileCheck %s module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry, dense<64> : vector<4xi64>>, #dlti.dl_entry, dense<32> : vector<4xi64>>, #dlti.dl_entry, dense<32> : vector<4xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<2xi64>>, #dlti.dl_entry : vector<4xi64>>, #dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>>} { func.func @_QPsub1() { %0 = cuf.alloc i32 {bindc_name = "idev", data_attr = #cuf.cuda, uniq_name = "_QFsub1Eidev"} -> !fir.ref %1:2 = hlfir.declare %0 {data_attr = #cuf.cuda, uniq_name = "_QFsub1Eidev"} : (!fir.ref) -> (!fir.ref, !fir.ref) cuf.free %1#1 : !fir.ref {data_attr = #cuf.cuda} return } // CHECK-LABEL: func.func @_QPsub1() // CHECK: %[[BYTES:.*]] = fir.convert %c4{{.*}} : (index) -> i64 // CHECK: %[[ALLOC:.*]] = fir.call @_FortranACUFMemAlloc(%[[BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: %[[CONV:.*]] = fir.convert %3 : (!fir.llvm_ptr) -> !fir.ref // CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[CONV]] {data_attr = #cuf.cuda, uniq_name = "_QFsub1Eidev"} : (!fir.ref) -> (!fir.ref, !fir.ref) // CHECK: %[[DEVPTR:.*]] = fir.convert %[[DECL]]#1 : (!fir.ref) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFMemFree(%[[DEVPTR]], %c0{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, i32, !fir.ref, i32) -> () func.func @_QPsub2() { %0 = cuf.alloc !fir.array<10xf32> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QMcuda_varFcuda_alloc_freeEa"} -> !fir.ref> cuf.free %0 : !fir.ref> {data_attr = #cuf.cuda} return } // CHECK-LABEL: func.func @_QPsub2() // CHECK: %[[BYTES:.*]] = arith.muli %c10{{.*}}, %c4{{.*}} : index // CHECK: %[[CONV_BYTES:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[CONV_BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFMemFree func.func @_QPsub3(%arg0: !fir.ref {fir.bindc_name = "n"}, %arg1: !fir.ref {fir.bindc_name = "m"}) { %0 = fir.dummy_scope : !fir.dscope %1:2 = hlfir.declare %arg0 dummy_scope %0 {uniq_name = "_QFsub3En"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) %2:2 = hlfir.declare %arg1 dummy_scope %0 {uniq_name = "_QFsub3Em"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) %3 = fir.load %1#0 : !fir.ref %4 = fir.convert %3 : (i32) -> i64 %5 = fir.convert %4 : (i64) -> index %c0 = arith.constant 0 : index %6 = arith.cmpi sgt, %5, %c0 : index %7 = arith.select %6, %5, %c0 : index %8 = fir.load %2#0 : !fir.ref %9 = fir.convert %8 : (i32) -> i64 %10 = fir.convert %9 : (i64) -> index %c0_0 = arith.constant 0 : index %11 = arith.cmpi sgt, %10, %c0_0 : index %12 = arith.select %11, %10, %c0_0 : index %13 = cuf.alloc !fir.array, %7, %12 : index, index {bindc_name = "idev", data_attr = #cuf.cuda, uniq_name = "_QFsub3Eidev"} -> !fir.ref> %14 = fir.shape %7, %12 : (index, index) -> !fir.shape<2> %15:2 = hlfir.declare %13(%14) {data_attr = #cuf.cuda, uniq_name = "_QFsub3Eidev"} : (!fir.ref>, !fir.shape<2>) -> (!fir.box>, !fir.ref>) cuf.free %15#1 : !fir.ref> {data_attr = #cuf.cuda} return } // CHECK-LABEL: func.func @_QPsub3 // CHECK: %[[N:.*]] = arith.select // CHECK: %[[M:.*]] = arith.select // CHECK: %[[NBELEM:.*]] = arith.muli %[[N]], %[[M]] : index // CHECK: %[[BYTES:.*]] = arith.muli %[[NBELEM]], %c4{{.*}} : index // CHECK: %[[CONV_BYTES:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[CONV_BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFMemFree func.func @_QPtest_type() { %0 = cuf.alloc !fir.type<_QMbarTcmplx{id:i32,c:complex}> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFtest_typeEa"} -> !fir.ref}>> %1 = fir.declare %0 {data_attr = #cuf.cuda, uniq_name = "_QFtest_typeEa"} : (!fir.ref}>>) -> !fir.ref}>> cuf.free %1 : !fir.ref}>> {data_attr = #cuf.cuda} return } // CHECK-LABEL: func.func @_QPtest_type() // CHECK: %[[BYTES:.*]] = arith.constant 12 : index // CHECK: %[[CONV_BYTES:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: fir.call @_FortranACUFMemAlloc(%[[CONV_BYTES]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr gpu.module @cuda_device_mod { gpu.func @_QMalloc() kernel { %0 = cuf.alloc !fir.box>> {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QMallocEa"} -> !fir.ref>>> gpu.return } } // CHECK-LABEL: gpu.func @_QMalloc() kernel // CHECK: fir.alloca !fir.box>> {bindc_name = "a", cuf.data_attr = #cuf.cuda, uniq_name = "_QMallocEa"} func.func @_QQalloc_char() attributes {fir.bindc_name = "alloc_char"} { %c1 = arith.constant 1 : index %0 = cuf.alloc !fir.array<10x!fir.char<1>>(%c1 : index) {bindc_name = "a", data_attr = #cuf.cuda, uniq_name = "_QFEa"} -> !fir.ref>> return } // CHECK-LABEL: func.func @_QQalloc_char() // CHECK: %[[BYTES:.*]] = arith.muli %c10{{.*}}, %c1{{.*}} : index // CHECK: %[[BYTES_CONV:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: fir.call @_FortranACUFMemAlloc(%[[BYTES_CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr func.func @_QQalloc_char2() { %c4 = arith.constant 4 : index %1 = cuf.alloc !fir.char<1,4>(%c4 : index) {bindc_name = "b", data_attr = #cuf.cuda, uniq_name = "_QFsub1Eb"} -> !fir.ref> %2 = cuf.alloc !fir.char<2,4>(%c4 : index) {bindc_name = "c", data_attr = #cuf.cuda, uniq_name = "_QFsub1Ec"} -> !fir.ref> %c10 = arith.constant 4 : index %3 = cuf.alloc !fir.char<4,10>(%c10 : index) {bindc_name = "d", data_attr = #cuf.cuda, uniq_name = "_QFsub1Ed"} -> !fir.ref> return } // CHECK-LABEL: func.func @_QQalloc_char2() // CHECK: %[[BYTES_4:.*]] = fir.convert %c4{{.*}} : (index) -> i64 // CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[BYTES_4]], %{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: %[[BYTES_8:.*]] = fir.convert %c8{{.*}} : (index) -> i64 // CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[BYTES_8]], %{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: %[[BYTES_40:.*]] = fir.convert %c40{{.*}} : (index) -> i64 // CHECK: %{{.*}} = fir.call @_FortranACUFMemAlloc(%[[BYTES_40]], %{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} : (i64, i32, !fir.ref, i32) -> !fir.llvm_ptr // Test that cuf.alloc with mixed constant and dynamic extents includes // the constant extents in the allocation size. For dimension(n, 4, m), // size must be n * m * 4(constant) * 4(bytes), not n * m * 4(bytes). func.func @_QPsub_mixed(%arg0: !fir.ref, %arg1: !fir.ref) { %0 = fir.load %arg0 : !fir.ref %1 = fir.convert %0 : (i32) -> index %c0 = arith.constant 0 : index %2 = arith.cmpi sgt, %1, %c0 : index %n = arith.select %2, %1, %c0 : index %3 = fir.load %arg1 : !fir.ref %4 = fir.convert %3 : (i32) -> index %5 = arith.cmpi sgt, %4, %c0 : index %m = arith.select %5, %4, %c0 : index %6 = cuf.alloc !fir.array, %n, %m : index, index {bindc_name = "arr", data_attr = #cuf.cuda, uniq_name = "_QFsub_mixedEarr"} -> !fir.ref> cuf.free %6 : !fir.ref> {data_attr = #cuf.cuda} return } // CHECK-LABEL: func.func @_QPsub_mixed // CHECK: %[[N:.*]] = arith.select // CHECK: %[[M:.*]] = arith.select // CHECK: %[[NM:.*]] = arith.muli %[[N]], %[[M]] : index // CHECK: %[[NM4:.*]] = arith.muli %[[NM]], %c4{{.*}} : index // CHECK: %[[BYTES:.*]] = arith.muli %[[NM4]], %c4{{.*}} : index // CHECK: %[[CONV:.*]] = fir.convert %[[BYTES]] : (index) -> i64 // CHECK: fir.call @_FortranACUFMemAlloc(%[[CONV]], %c0{{.*}}, %{{.*}}, %{{.*}}) {cuf.data_attr = #cuf.cuda} // CHECK: fir.call @_FortranACUFMemFree } // end module