// RUN: fir-opt --split-input-file --cuf-convert --cuf-convert-late %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>>} { fir.global @_QMmod1Eadev {data_attr = #cuf.cuda} : !fir.array<10xi32> { %0 = fir.zero_bits !fir.array<10xi32> fir.has_value %0 : !fir.array<10xi32> } func.func @_QQmain() attributes {fir.bindc_name = "test"} { %c14_i32 = arith.constant 14 : i32 %c6_i32 = arith.constant 6 : i32 %c4 = arith.constant 4 : index %c1_i32 = arith.constant 1 : i32 %c0_i32 = arith.constant 0 : i32 %c10 = arith.constant 10 : index %1 = fir.shape %c10 : (index) -> !fir.shape<1> %3 = fir.address_of(@_QMmod1Eadev) : !fir.ref> %4 = fir.declare %3(%1) {data_attr = #cuf.cuda, uniq_name = "_QMmod1Eadev"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> %5 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} %6 = fir.declare %5 {uniq_name = "_QFEi"} : (!fir.ref) -> !fir.ref fir.store %c0_i32 to %6 : !fir.ref %7 = fir.array_coor %4(%1) %c4 : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref cuf.data_transfer %c1_i32 to %7 {transfer_kind = #cuf.cuda_transfer} : i32, !fir.ref return } } // CHECK-LABEL: func.func @_QQmain() // CHECK: fir.address_of(@_QMmod1Eadev) : !fir.ref> // CHECK: %[[ADDR:.*]] = fir.address_of(@_QMmod1Eadev) : !fir.ref> // CHECK: %[[ADDRPTR:.*]] = fir.convert %[[ADDR]] : (!fir.ref>) -> !fir.llvm_ptr // CHECK: %[[DEVICE_ADDR:.*]] = fir.call @_FortranACUFGetDeviceAddress(%[[ADDRPTR]], %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.ref, i32) -> !fir.llvm_ptr // CHECK: %[[DEVICE_ADDR_CONV:.*]] = fir.convert %[[DEVICE_ADDR]] : (!fir.llvm_ptr) -> !fir.ref> // CHECK: %[[DECL:.*]] = fir.declare %[[DEVICE_ADDR_CONV]](%{{.*}}) {data_attr = #cuf.cuda, uniq_name = "_QMmod1Eadev"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> // CHECK: %[[ARRAY_COOR:.*]] = fir.array_coor %[[DECL]](%{{.*}}) %c4{{.*}} : (!fir.ref>, !fir.shape<1>, index) -> !fir.ref // CHECK: %[[ARRAY_COOR_PTR:.*]] = fir.convert %[[ARRAY_COOR]] : (!fir.ref) -> !fir.llvm_ptr // CHECK: fir.call @_FortranACUFDataTransferPtrPtr(%[[ARRAY_COOR_PTR]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.llvm_ptr, !fir.llvm_ptr, i64, i32, !fir.ref, i32) -> () // ----- 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>>} { fir.global @_QMdevmodEdarray {data_attr = #cuf.cuda} : !fir.box>> { %c0 = arith.constant 0 : index %0 = fir.zero_bits !fir.heap> %1 = fir.shape %c0 : (index) -> !fir.shape<1> %2 = fir.embox %0(%1) {allocator_idx = 2 : i32} : (!fir.heap>, !fir.shape<1>) -> !fir.box>> fir.has_value %2 : !fir.box>> } func.func @_QQmain() attributes {fir.bindc_name = "arraysize"} { %0 = fir.address_of(@_QMiso_c_bindingECc_int) : !fir.ref %1 = fir.declare %0 {fortran_attrs = #fir.var_attrs, uniq_name = "_QMiso_c_bindingECc_int"} : (!fir.ref) -> !fir.ref %2 = fir.address_of(@_QMdevmodEdarray) : !fir.ref>>> %3 = fir.declare %2 {data_attr = #cuf.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMdevmodEdarray"} : (!fir.ref>>>) -> !fir.ref>>> %4 = fir.alloca i32 {bindc_name = "exp", uniq_name = "_QFEexp"} %5 = fir.declare %4 {uniq_name = "_QFEexp"} : (!fir.ref) -> !fir.ref %6 = fir.alloca i32 {bindc_name = "hsize", uniq_name = "_QFEhsize"} %7 = fir.declare %6 {uniq_name = "_QFEhsize"} : (!fir.ref) -> !fir.ref return } fir.global @_QMiso_c_bindingECc_int constant : i32 } // We cannot call _FortranACUFGetDeviceAddress on a constant global. // There is no symbol for it and the call would result into an unresolved reference. // CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "arraysize"} // CHECK-NOT: fir.call {{.*}}GetDeviceAddress // ----- 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>>} { fir.global @_QMmod1Eadev {data_attr = #cuf.cuda} : !fir.array<10xi32> { %0 = fir.zero_bits !fir.array<10xi32> fir.has_value %0 : !fir.array<10xi32> } func.func @_QQmain() attributes {fir.bindc_name = "test"} { %dim = arith.constant 1 : index gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %dim, %grid_y = %dim, %grid_z = %dim) threads(%tx, %ty, %tz) in (%block_x = %dim, %block_y = %dim, %block_z = %dim) { %c10 = arith.constant 10 : index %1 = fir.shape %c10 : (index) -> !fir.shape<1> %3 = fir.address_of(@_QMmod1Eadev) : !fir.ref> %4 = fir.declare %3(%1) {data_attr = #cuf.cuda, uniq_name = "_QMmod1Eadev"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> gpu.terminator } return } // CHECK-LABEL: func.func @_QQmain() // CHECK: gpu.launch // CHECK-NOT: fir.call {{.*}}GetDeviceAddress } // ----- // Check that we do not introduce call to _FortranACUFGetDeviceAddress when the // address_of is inside an acc.parallel region (OffloadRegionOpInterface). 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>>} { fir.global @_QMmod1Eadev_acc {data_attr = #cuf.cuda} : !fir.array<10xi32> { %0 = fir.zero_bits !fir.array<10xi32> fir.has_value %0 : !fir.array<10xi32> } func.func @_QQmain_acc() attributes {fir.bindc_name = "test_acc"} { acc.parallel { %c10 = arith.constant 10 : index %1 = fir.shape %c10 : (index) -> !fir.shape<1> %3 = fir.address_of(@_QMmod1Eadev_acc) : !fir.ref> %4 = fir.declare %3(%1) {data_attr = #cuf.cuda, uniq_name = "_QMmod1Eadev_acc"} : (!fir.ref>, !fir.shape<1>) -> !fir.ref> acc.yield } return } // CHECK-LABEL: func.func @_QQmain_acc() // CHECK: acc.parallel // CHECK-NOT: fir.call {{.*}}GetDeviceAddress } // ----- // Check that we do not introduce call to _FortranACUFGetDeviceAddress when the // value has no user. 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 @_QQmain() attributes {fir.bindc_name = "T"} { %0 = fir.dummy_scope : !fir.dscope %1 = fir.address_of(@_QMcon2Ezzz) : !fir.ref %2 = fir.declare %1 {data_attr = #cuf.cuda, uniq_name = "_QMcon2Ezzz"} : (!fir.ref) -> !fir.ref return } fir.global @_QMcon2Ezzz {data_attr = #cuf.cuda} : i32 } // CHECK-LABEL: func.func @_QQmain() // CHECK: fir.address_of(@_QMcon2Ezzz) : !fir.ref // CHECK-NOT: fir.call {{.*}}GetDeviceAddress