| ! RUN: bbc -emit-hlfir -fopenacc -fcuda %s -o - | FileCheck %s |
| |
| ! Test CUDA Fortran data transfer using assignment statements. |
| |
| module mod1 |
| |
| real, parameter :: pi = 0.9189385332046727417803297 |
| real, constant :: rconst |
| real, constant :: csconst |
| |
| type :: t1 |
| integer :: i |
| end type |
| |
| type :: t2 |
| integer, device, allocatable, dimension(:) :: x |
| end type |
| |
| type :: s |
| real :: c(3) |
| end type |
| |
| type :: t3 |
| type(s), managed, allocatable :: spheres(:) |
| end type |
| |
| integer, device, dimension(11:20) :: cdev |
| |
| real(kind=8), device, allocatable, dimension(:) :: p |
| |
| real, constant :: c1 = 1.0 |
| real, device :: d1 = 1.0 |
| |
| interface |
| function __sum(a_d) result(res_h) |
| integer(4), managed, intent(in) :: a_d(:,:,:,:) |
| integer(4), allocatable, managed :: res_h(:,:,:) |
| end function |
| end interface |
| |
| interface |
| function somefunction(d, n) |
| integer :: n |
| real(8), device :: d(n,n) |
| real(8) :: somefunction(n) |
| end function |
| end interface |
| |
| |
| contains |
| function dev1(a) |
| integer, device :: a(:) |
| integer :: dev1 |
| dev1 = 1 |
| end function |
| end |
| |
| subroutine sub1() |
| use mod1 |
| integer, device :: m |
| integer, device :: adev(10) |
| integer :: i, ahost(10), bhost(10) |
| |
| m = 1 + i |
| |
| m = 1 |
| |
| adev = ahost |
| |
| adev = ahost + 1 |
| |
| adev(1:5) = ahost(1:5) |
| |
| adev = ahost + bhost |
| |
| adev = 10 |
| |
| cdev = 0 |
| end |
| |
| ! CHECK-LABEL: func.func @_QPsub1() |
| |
| ! CHECK: %[[ADEV:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub1Eadev"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub1Eahost"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[I:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFsub1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) |
| ! CHECK: %[[M:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub1Em"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) |
| |
| ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 |
| ! CHECK: %[[LOADED_I:.*]] = fir.load %[[I]]#0 : !fir.ref<i32> |
| ! CHECK: %[[ADD:.*]] = arith.addi %[[C1]], %[[LOADED_I]] : i32 |
| ! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[ADD]] {uniq_name = ".cuf_host_tmp"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) |
| ! CHECK: cuf.data_transfer %[[ASSOC]]#0 to %[[M]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<i32>, !fir.ref<i32> |
| ! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<i32>, i1 |
| |
| ! CHECK: cuf.data_transfer %c1{{.*}} to %[[M]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : i32, !fir.ref<i32> |
| |
| ! CHECK: cuf.data_transfer %[[AHOST]]#0 to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> |
| |
| ! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { |
| ! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[ELEMENTAL]](%{{.*}}) {uniq_name = ".cuf_host_tmp"} : (!hlfir.expr<10xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, i1) |
| ! CHECK: cuf.data_transfer %[[ASSOC]]#0 to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> |
| ! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<!fir.array<10xi32>>, i1 |
| |
| ! CHECK: %[[DES_AHOST:.*]] = hlfir.designate %[[AHOST]]#0 (%c1{{.*}}:%c5{{.*}}:%c1{{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>> |
| ! CHECK: %[[DES_ADEV:.*]] = hlfir.designate %[[ADEV]]#0 (%c1{{.*}}:%c5{{.*}}:%c1{{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>> |
| ! CHECK: cuf.data_transfer %[[DES_AHOST]] to %[[DES_ADEV]] {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<5xi32>>, !fir.ref<!fir.array<5xi32>> |
| |
| ! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> |
| ! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[ELEMENTAL]](%{{.*}}) {uniq_name = ".cuf_host_tmp"} : (!hlfir.expr<10xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, i1) |
| ! CHECK: cuf.data_transfer %[[ASSOC]]#0 to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> |
| ! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<!fir.array<10xi32>>, i1 |
| |
| ! CHECK: cuf.data_transfer %c10{{.*}} to %[[ADEV]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : i32, !fir.ref<!fir.array<10xi32>> |
| |
| ! CHECK: cuf.data_transfer %c0{{.*}} to %{{.*}}#1, %{{.*}} : !fir.shapeshift<1> {transfer_kind = #cuf.cuda_transfer<host_device>} : i32, !fir.ref<!fir.array<10xi32>> |
| |
| subroutine sub2() |
| integer, device :: m |
| integer, device :: adev(10), bdev(10) |
| integer :: i, ahost(10), bhost(10) |
| |
| ahost = adev |
| |
| i = m |
| |
| ahost(1:5) = adev(1:5) |
| |
| bdev = adev |
| |
| ! Implicit data transfer of adev before evaluation. |
| bhost = ahost + adev |
| |
| end |
| |
| ! CHECK-LABEL: func.func @_QPsub2() |
| ! CHECK: %[[ADEV:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub2Eadev"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub2Eahost"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[BDEV:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub2Ebdev"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[BHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub2Ebhost"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[I:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFsub2Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) |
| ! CHECK: %[[M:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub2Em"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) |
| ! CHECK: cuf.data_transfer %[[ADEV]]#0 to %[[AHOST]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> |
| ! CHECK: cuf.data_transfer %[[M]]#0 to %[[I]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<i32>, !fir.ref<i32> |
| |
| ! CHECK: %[[DES_ADEV:.*]] = hlfir.designate %[[ADEV]]#0 (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>> |
| ! CHECK: %[[DES_AHOST:.*]] = hlfir.designate %[[AHOST]]#0 (%{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>> |
| ! CHECK: cuf.data_transfer %[[DES_ADEV]] to %[[DES_AHOST]] {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<5xi32>>, !fir.ref<!fir.array<5xi32>> |
| |
| ! CHECK: cuf.data_transfer %[[ADEV]]#0 to %[[BDEV]]#0 {transfer_kind = #cuf.cuda_transfer<device_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> |
| |
| ! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<10xi32> {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: %[[DECL_TEMP:.*]]:2 = hlfir.declare %[[TEMP]](%{{.*}}) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<10xi32>>, !fir.heap<!fir.array<10xi32>>) |
| ! CHECK: %[[ADEV_TEMP:.*]]:2 = hlfir.declare %[[DECL_TEMP]]#0(%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub2Eadev"} : (!fir.heap<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<10xi32>>, !fir.heap<!fir.array<10xi32>>) |
| ! CHECK: cuf.data_transfer %[[ADEV]]#0 to %[[DECL_TEMP]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<10xi32>>, !fir.heap<!fir.array<10xi32>> |
| ! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> |
| ! CHECK: hlfir.assign %[[ELEMENTAL]] to %[[BHOST]]#0 : !hlfir.expr<10xi32>, !fir.ref<!fir.array<10xi32>> |
| ! CHECK: fir.freemem %[[TEMP]] : !fir.heap<!fir.array<10xi32>> |
| |
| subroutine sub3() |
| use mod1 |
| type(t1), device :: t |
| integer :: ahost(10), bhost(10) |
| |
| bhost = ahost + t%i |
| end |
| |
| ! CHECK-LABEL: func.func @_QPsub3() |
| ! CHECK: %[[TMP:.*]] = fir.alloca !fir.type<_QMmod1Tt1{i:i32}> {bindc_name = ".tmp"} |
| ! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub3Eahost"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[BHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub3Ebhost"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[T:.*]]:2 = hlfir.declare %{{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub3Et"} : (!fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>) -> (!fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>, !fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>) |
| ! CHECK: %[[TMP_DECL:.*]]:2 = hlfir.declare %0 {uniq_name = ".tmp"} : (!fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>) -> (!fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>, !fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>) |
| ! CHECK: cuf.data_transfer %[[T]]#0 to %[[TMP_DECL]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.type<_QMmod1Tt1{i:i32}>>, !fir.ref<!fir.type<_QMmod1Tt1{i:i32}>> |
| |
| |
| ! Check that cuf.data_transfer are not generated within cuf kernel |
| subroutine sub4() |
| integer, parameter :: n = 10 |
| real, device :: adev(n) |
| real :: ahost(n) |
| real, managed :: b |
| integer :: i |
| |
| adev = ahost |
| !$cuf kernel do <<<*,*>>> |
| do i = 1, n |
| adev(i) = adev(i) + b |
| enddo |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub4() |
| ! CHECK: cuf.data_transfer |
| ! CHECK: cuf.kernel<<<*, *>>> |
| ! CHECK-NOT: cuf.data_transfer |
| ! CHECK: hlfir.assign |
| |
| attributes(global) subroutine sub5(a) |
| integer, device :: a |
| integer :: i |
| a = i |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub5 |
| ! CHECK-NOT: cuf.data_transfer |
| |
| attributes(host,device) subroutine sub6(a) |
| integer, device :: a |
| integer :: i |
| a = i |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub6 |
| ! CHECK: cuf.data_transfer |
| |
| subroutine sub7(a, b, c) |
| integer, device, allocatable :: a(:), c(:) |
| integer, allocatable :: b(:) |
| b = a |
| |
| a = b |
| |
| c = a |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub7( |
| ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "c"}) { |
| ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} arg {{[0-9]+}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Ea"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) |
| ! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{.*}} arg {{[0-9]+}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Eb"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) |
| ! CHECK: %[[C:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %0 arg {{[0-9]+}} {data_attr = #cuf.cuda<device>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFsub7Ec"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.dscope) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) |
| ! CHECK: cuf.data_transfer %[[A]]#0 to %[[B]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> |
| ! CHECK: cuf.data_transfer %[[B]]#0 to %[[A]]#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> |
| ! CHECK: cuf.data_transfer %[[A]]#0 to %[[C]]#0 {transfer_kind = #cuf.cuda_transfer<device_device>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> |
| |
| subroutine sub8(a, b, n) |
| integer :: n |
| integer, device :: a(n) |
| integer :: b(10) |
| b = a |
| a = b |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub8( |
| ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xi32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<!fir.array<10xi32>> {fir.bindc_name = "b"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) |
| ! CHECK: %[[B:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFsub8Eb"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub8Ea"} : (!fir.ref<!fir.array<?xi32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.ref<!fir.array<?xi32>>) |
| ! CHECK: cuf.data_transfer %[[A]]#1 to %[[B]]#0, %{{.*}} : !fir.shape<1> {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<?xi32>>, !fir.ref<!fir.array<10xi32>> |
| ! CHECK: cuf.data_transfer %[[B]]#0 to %[[A]]#1, %{{.*}} : !fir.shape<1> {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<?xi32>> |
| |
| subroutine sub9(a) |
| integer, pinned, allocatable :: a(:) |
| do concurrent (i = 1 : 10) |
| a(i) = 10 + a(i) |
| end do |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub9 |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub10(a, b) |
| integer, device :: a |
| integer, allocatable, pinned :: b |
| integer :: res |
| |
| res = a + b |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub10( |
| ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a"} |
| |
| ! CHECK: %[[A:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %1 {{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub10Ea"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) |
| ! CHECK: cuf.data_transfer %[[A]]#0 to %{{.*}}#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<i32>, !fir.ref<i32> |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub11(n) |
| integer :: n |
| real, dimension(10) :: h |
| real, dimension(n), device :: d |
| do i=1,10 |
| h(i) = d(i) |
| end do |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub11 |
| ! CHECK: %[[RHS:.*]] = hlfir.designate %{{.*}} (%{{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> |
| ! CHECK: %[[LHS:.*]] = hlfir.designate %{{.*}} (%{{.*}}) : (!fir.ref<!fir.array<10xf32>>, i64) -> !fir.ref<f32> |
| ! CHECK: cuf.data_transfer %[[RHS]] to %[[LHS]] {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<f32>, !fir.ref<f32> |
| |
| subroutine sub12() |
| use mod1 |
| integer, device :: a(10) |
| integer :: x |
| x = dev1(a) |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub12 |
| ! CHECK: %{{.*}} = fir.call @_QMmod1Pdev1 |
| ! CHECK: hlfir.assign |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub13(a, b, n) |
| integer :: n |
| integer :: a(n) |
| integer, allocatable, device :: b(:) |
| integer :: res(10) |
| |
| res = a + b |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub13 |
| ! CHECK: %[[TEMP:.*]] = fir.allocmem !fir.array<?xi32>, %14#1 {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: cuf.data_transfer |
| ! CHECK: fir.freemem %[[TEMP]] : !fir.heap<!fir.array<?xi32>> |
| |
| subroutine sub14() |
| logical(4), device :: log(10) |
| log = .true. |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub14() |
| ! CHECK: %[[TRUE:.*]] = arith.constant true |
| ! CHECK: cuf.data_transfer %[[TRUE]] to %{{.*}}#0 {transfer_kind = #cuf.cuda_transfer<host_device>} : i1, !fir.ref<!fir.array<10x!fir.logical<4>>> |
| |
| subroutine sub15(a_dev, a_host, n, m) |
| integer, intent(in) :: n, m |
| real, device :: a_dev(n*m) |
| real :: a_host(n*m) |
| |
| a_dev = a_host |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub15( |
| ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?xf32>> {cuf.data_attr = #cuf.cuda<device>, fir.bindc_name = "a_dev"}, %[[ARG1:.*]]: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a_host"} |
| ! CHECK: %[[ADEV:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub15Ea_dev"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) |
| ! CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> |
| ! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %[[ARG1]](%{{.*}}) dummy_scope %{{.*}} {{.*}} {uniq_name = "_QFsub15Ea_host"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>) |
| ! CHECK: cuf.data_transfer %[[AHOST]]#1 to %[[ADEV]]#1, %[[SHAPE]] : !fir.shape<1> {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.ref<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>> |
| |
| ! Check that cuf.data_transfer are not generated within OpenACC region |
| subroutine sub16() |
| integer, parameter :: n = 10 |
| real, device :: adev(n) |
| real :: ahost(n) |
| real, managed :: b |
| integer :: i |
| |
| adev = ahost |
| !$acc parallel loop deviceptr(adev) |
| do i = 1, n |
| adev(i) = adev(i) + b |
| enddo |
| |
| !$acc kernels deviceptr(adev) |
| do i = 1, n |
| adev(i) = adev(i) + b |
| enddo |
| !$acc end kernels |
| |
| |
| !$acc serial deviceptr(adev) |
| do i = 1, n |
| adev(i) = adev(i) + b |
| enddo |
| !$acc end serial |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub16() |
| ! CHECK: cuf.data_transfer |
| ! CHECK: acc.parallel |
| ! CHECK-NOT: cuf.data_transfer |
| ! CHECK: hlfir.assign |
| |
| ! CHECK: acc.kernels |
| ! CHECK-NOT: cuf.data_transfer |
| ! CHECK: hlfir.assign |
| |
| ! CHECK: acc.serial |
| ! CHECK-NOT: cuf.data_transfer |
| ! CHECK: hlfir.assign |
| |
| ! Check that cuf.data_transfer are not generated within cuf kernel and do not |
| ! trigger semantic error. |
| subroutine sub17() |
| integer, parameter :: n = 10 |
| real, device :: adev(n) |
| real, device :: bdev(n) |
| real :: ahost |
| real, managed :: b |
| integer :: i |
| |
| adev = ahost |
| !$cuf kernel do <<<*,*>>> |
| do i = 1, n |
| ahost = adev(i) * bdev(i) + b |
| enddo |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub17() |
| ! CHECK: cuf.kernel<<<*, *>>> |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub18(o) |
| integer, device, optional, allocatable :: o(:) |
| integer, device, allocatable :: a(:) |
| integer, device, pointer :: p(:) |
| integer :: b |
| integer :: s(1) |
| logical :: l |
| |
| b = size(a) |
| b = lbound(a, dim=1) |
| b = ubound(a, dim=1) |
| s = shape(a) |
| l = allocated(a) |
| l = associated(p) |
| b = kind(a) |
| l = present(o) |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub18 |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub19() |
| integer, device :: adev(10) |
| integer :: ahost(10) |
| ! Implicit data transfer of adev and then addition on the host |
| ahost = adev + 2 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub19() |
| ! CHECK: %[[ADEV_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub19Eadev"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) |
| ! CHECK: %[[ALLOC_TMP:.*]] = fir.allocmem !fir.array<10xi32> {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: %[[TMP:.*]]:2 = hlfir.declare %[[ALLOC_TMP]](%{{.*}}) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.heap<!fir.array<10xi32>>, !fir.heap<!fir.array<10xi32>>) |
| ! CHECK: cuf.data_transfer %[[ADEV_DECL]]#0 to %[[TMP]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<10xi32>>, !fir.heap<!fir.array<10xi32>> |
| ! CHECK: hlfir.assign |
| |
| subroutine sub20() |
| integer, managed :: a(10) |
| a = a + 2 ! ok. No data transfer. Assignment on the host. |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub20() |
| ! CHECK-NOT: cuf.data_transfer |
| ! CHECK: hlfir.assign |
| |
| subroutine sub21() |
| real, allocatable,device:: a(:,:), b(:,:) |
| real:: s |
| integer:: i,j,N=16 |
| allocate(a(N,N),b(N,N)) |
| do concurrent(i=1:N, j=1:N) reduce(+:s) |
| b(i,j)=a(i,j)**2 |
| s=s+b(i,j) |
| end do |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub21() |
| ! CHECK: fir.do_concurrent.loop |
| ! CHECK-NOT: cuf.data_transfer |
| ! CHECK: hlfir.assign |
| |
| |
| subroutine sub22() |
| use mod1 |
| type(t2) :: a |
| integer :: b(100) |
| allocate(a%x(100)) |
| |
| b = a%x |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub22() |
| ! CHECK: cuf.data_transfer |
| |
| subroutine sub23(n) |
| use mod1 |
| integer :: n |
| real(8), device :: d(n,n), x(n) |
| x = somefunction(d,2) ! Was triggering Unsupported CUDA data transfer |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub23 |
| |
| subroutine sub24() |
| real, managed :: m |
| real, device :: d(4) |
| m = d(1) |
| end |
| |
| ! CHECK-LABEL: func.func @_QPsub24() |
| ! CHECK: %[[D:.*]]:2 = hlfir.declare %1(%2) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub24Ed"} : (!fir.ref<!fir.array<4xf32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<4xf32>>, !fir.ref<!fir.array<4xf32>>) |
| ! CHECK: %[[M:.*]]:2 = hlfir.declare %4 {data_attr = #cuf.cuda<managed>, uniq_name = "_QFsub24Em"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) |
| ! CHECK: %[[D1:.*]] = hlfir.designate %[[D]]#0 (%c1{{.*}}) : (!fir.ref<!fir.array<4xf32>>, index) -> !fir.ref<f32> |
| ! CHECK: cuf.data_transfer %[[D1]] to %[[M]]#0 {hasManagedOrUnifedSymbols, transfer_kind = #cuf.cuda_transfer<device_device>} : !fir.ref<f32>, !fir.ref<f32> |
| |
| subroutine sub25() |
| use mod1 |
| integer :: i |
| real(8) :: c |
| |
| do i = 1, 10 |
| c = c + p(i) |
| end do |
| end |
| |
| ! CHECK-LABEL: func.func @_QPsub25() |
| ! CHECK: fir.allocmem !fir.array<?xf64>, %{{.*}} {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: cuf.data_transfer %{{.*}} to %{{.*}} {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, !fir.box<!fir.array<?xf64>> |
| ! CHECK: hlfir.assign %{{.*}} to %{{.*}} : f64, !fir.ref<f64> |
| ! CHECK: fir.freemem %{{.*}} : !fir.heap<!fir.array<?xf64>> |
| |
| subroutine sub26(i, j, k) |
| integer :: i, j, k |
| real(2), dimension(i,j,k), device :: d |
| real(4), dimension(i,j,k) :: hd |
| |
| hd = d |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub26 |
| ! CHECK: %[[ALLOC_D:.*]] = cuf.alloc !fir.array<?x?x?xf16>, %{{.*}}, %{{.*}}, %{{.*}} : index, index, index {bindc_name = "d", data_attr = #cuf.cuda<device>, uniq_name = "_QFsub26Ed"} -> !fir.ref<!fir.array<?x?x?xf16>> |
| ! CHECK: %[[D:.*]]:2 = hlfir.declare %[[ALLOC_D]](%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub26Ed"} : (!fir.ref<!fir.array<?x?x?xf16>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x?xf16>>, !fir.ref<!fir.array<?x?x?xf16>>) |
| ! CHECK: %[[HD:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub26Ehd"} : (!fir.ref<!fir.array<?x?x?xf32>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x?xf32>>, !fir.ref<!fir.array<?x?x?xf32>>) |
| ! CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<?x?x?xf16>, %8, %13, %18 {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: %[[TEMP:.*]]:2 = hlfir.declare %[[ALLOC]](%{{.*}}) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?x?x?xf16>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x?xf16>>, !fir.heap<!fir.array<?x?x?xf16>>) |
| ! CHECK: cuf.data_transfer %[[D]]#0 to %[[TEMP]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.box<!fir.array<?x?x?xf16>>, !fir.box<!fir.array<?x?x?xf16>> |
| ! CHECK: %[[ELE:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<3>) -> !hlfir.expr<?x?x?xf32> { |
| ! CHECK: ^bb0(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index): |
| ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[TEMP]]#0 (%{{.*}}, %{{.*}}, %{{.*}}) : (!fir.box<!fir.array<?x?x?xf16>>, index, index, index) -> !fir.ref<f16> |
| ! CHECK: %[[LOAD:.*]] = fir.load %[[DESIGNATE]] : !fir.ref<f16> |
| ! CHECK: %[[CONV:.*]] = fir.convert %[[LOAD]] : (f16) -> f32 |
| ! CHECK: hlfir.yield_element %[[CONV]] : f32 |
| ! CHECK: } |
| ! CHECK: hlfir.assign %[[ELE]] to %[[HD]]#0 : !hlfir.expr<?x?x?xf32>, !fir.box<!fir.array<?x?x?xf32>> |
| |
| subroutine sub27() |
| real(2), dimension(10, 20, 30), device :: d |
| real(4), dimension(10, 20, 30) :: hd |
| |
| hd = d |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub27() |
| ! CHECK: %[[ALLOC_D:.*]] = cuf.alloc !fir.array<10x20x30xf16> {bindc_name = "d", data_attr = #cuf.cuda<device>, uniq_name = "_QFsub27Ed"} -> !fir.ref<!fir.array<10x20x30xf16>> |
| ! CHECK: %[[D:.*]]:2 = hlfir.declare %[[ALLOC_D]](%{{.*}}) {data_attr = #cuf.cuda<device>, uniq_name = "_QFsub27Ed"} : (!fir.ref<!fir.array<10x20x30xf16>>, !fir.shape<3>) -> (!fir.ref<!fir.array<10x20x30xf16>>, !fir.ref<!fir.array<10x20x30xf16>>) |
| ! CHECK: %[[ALLOC_HD:.*]] = fir.alloca !fir.array<10x20x30xf32> {bindc_name = "hd", uniq_name = "_QFsub27Ehd"} |
| ! CHECK: %[[HD:.*]]:2 = hlfir.declare %[[ALLOC_HD]](%{{.*}}) {uniq_name = "_QFsub27Ehd"} : (!fir.ref<!fir.array<10x20x30xf32>>, !fir.shape<3>) -> (!fir.ref<!fir.array<10x20x30xf32>>, !fir.ref<!fir.array<10x20x30xf32>>) |
| ! CHECK: %[[ALLOC_TEMP:.*]] = fir.allocmem !fir.array<10x20x30xf16> {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: %[[TEMP:.*]]:2 = hlfir.declare %[[ALLOC_TEMP]](%{{.*}}) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<10x20x30xf16>>, !fir.shape<3>) -> (!fir.heap<!fir.array<10x20x30xf16>>, !fir.heap<!fir.array<10x20x30xf16>>) |
| ! CHECK: cuf.data_transfer %[[D]]#0 to %[[TEMP]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.ref<!fir.array<10x20x30xf16>>, !fir.heap<!fir.array<10x20x30xf16>> |
| ! CHECK: %[[ELE:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<3>) -> !hlfir.expr<10x20x30xf32> { |
| ! CHECK: ^bb0(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index): |
| ! CHECK: %[[DESIGNATE:.*]] = hlfir.designate %[[TEMP]]#0 (%{{.*}}, %{{.*}}, %{{.*}}) : (!fir.heap<!fir.array<10x20x30xf16>>, index, index, index) -> !fir.ref<f16> |
| ! CHECK: %[[LOAD:.*]] = fir.load %[[DESIGNATE]] : !fir.ref<f16> |
| ! CHECK: %[[CONV:.*]] = fir.convert %[[LOAD]] : (f16) -> f32 |
| ! CHECK: hlfir.yield_element %[[CONV]] : f32 |
| ! CHECK: } |
| ! CHECKL: hlfir.assign %[[ELE]] to %[[HD]]#0 : !hlfir.expr<10x20x30xf32>, !fir.ref<!fir.array<10x20x30xf32>> |
| |
| subroutine sub28(N1,N2,N3,N4) |
| use mod1 |
| integer(4), managed :: a(N1,N2,N3,N4) |
| integer(4), managed :: bres(N1,N2,N3) |
| bres = __sum(a) |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub28 |
| ! CHECK: fir.call @_QP__sum |
| ! CHECK: cuf.data_transfer |
| |
| ! Data transfer with conversion with more complex elemental |
| ! Check that the data transfer is placed before the elemental op. |
| subroutine sub29() |
| real(2), device, allocatable :: a(:) |
| real(4), allocatable :: ha(:) |
| allocate(a(10)) |
| allocate(ha(10)) |
| ha = a |
| deallocate(a) |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub29() |
| ! CHECK: %[[TMP:.*]] = fir.allocmem !fir.array<?xf16>, %{{.*}}#1 {bindc_name = ".tmp", uniq_name = ""} |
| ! CHECK: %[[TMP_BUFFER:.*]]:2 = hlfir.declare %[[TMP]](%{{.*}}) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<?xf16>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf16>>, !fir.heap<!fir.array<?xf16>>) |
| ! CHECK: cuf.data_transfer %{{.*}} to %[[TMP_BUFFER]]#0 {transfer_kind = #cuf.cuda_transfer<device_host>} : !fir.box<!fir.heap<!fir.array<?xf16>>>, !fir.box<!fir.array<?xf16>> |
| ! CHECK: hlfir.elemental |
| |
| subroutine sub30() |
| use mod1 |
| type(t3), managed :: t |
| t%spheres(1) = s([0.0, 0.0, -1.0]) |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub30() |
| ! CHECK: %{{.*}} = cuf.alloc !fir.type<_QMmod1Tt3{spheres:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMmod1Ts{c:!fir.array<3xf32>}>>>>}> {bindc_name = "t", data_attr = #cuf.cuda<managed>, uniq_name = "_QFsub30Et"} -> !fir.ref<!fir.type<_QMmod1Tt3{spheres:!fir.box<!fir.heap<!fir.array<?x!fir.type<_QMmod1Ts{c:!fir.array<3xf32>}>>>>}>> |
| ! CHECK: hlfir.assign |
| ! CHECK-NOT: cuf.data_transfer |
| |
| ! Test that assigment with only managed variables on both rhs and lhs is done |
| ! on the host. |
| |
| subroutine sub31() |
| type :: t30 |
| real, managed, allocatable :: q(:) |
| end type |
| type(t30), managed, allocatable :: x(:) |
| x(4)%q = x(3)%q |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub31() |
| ! CHECK: cuf.alloc !fir.box<!fir.heap<!fir.array<?x!fir.type<_QFsub31Tt30{q:!fir.box<!fir.heap<!fir.array<?xf32>>>}>>>> |
| ! CHECK: hlfir.assign |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub32() |
| integer, managed :: adev(10) |
| integer :: a |
| |
| adev = a |
| |
| adev = 0 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub32() |
| ! CHECK-COUNT-2: cuf.data_transfer |
| |
| subroutine sub33(m, n) |
| integer :: m, n |
| real(2), managed :: dc(m,n) |
| real(4) :: c(m,n) |
| |
| c = (dc) |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub33 |
| ! CHECK-NOT: cuf.data_transfer |
| |
| ! A section reference is assigned on the host even when it covers the whole array: |
| ! what matters is the form of the reference, not the extent it happens to cover |
| ! (CUDA Fortran Programming Guide 3.4.1). |
| subroutine sub34(n) |
| integer :: n |
| real(2), managed, allocatable :: dx(:) |
| allocate(dx(1:n)) |
| dx(1:n) = 7.0_2 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub34 |
| ! CHECK-NOT: cuf.data_transfer |
| |
| module managed_mod |
| integer, managed :: marray(10) |
| end module |
| |
| subroutine sub35() |
| use managed_mod |
| integer :: host_arr(10) |
| marray = host_arr |
| marray = 0 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub35() |
| ! CHECK-NOT: cuf.data_transfer |
| |
| ! Test that host_var = managed_module_var generates a cuf.data_transfer: |
| ! reading a whole managed array variable is a synchronous data transfer. |
| subroutine sub36() |
| use managed_mod |
| integer :: host_arr(10) |
| host_arr = marray |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub36() |
| ! CHECK: cuf.data_transfer %{{.*}} to %{{.*}} {hasManagedOrUnifedSymbols, transfer_kind = #cuf.cuda_transfer<device_host>} |
| |
| ! Test that device_var = managed_module_var DOES generate cuf.data_transfer |
| ! (device memory requires explicit cudaMemcpy). |
| subroutine sub37() |
| use managed_mod |
| integer, device :: dev_arr(10) |
| dev_arr = marray |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub37() |
| ! CHECK: cuf.data_transfer |
| |
| subroutine sub38() |
| type :: bar |
| integer, device, allocatable :: m(:) |
| end type |
| type(bar), unified :: a |
| type(bar), managed :: ma |
| integer :: lm(5) |
| |
| |
| lm(1:5) = a%m(1:5) |
| lm(1:5) = ma%m(1:5) |
| end subroutine |
| |
| subroutine sub39() |
| type :: foo |
| integer, device, allocatable :: m(:) |
| end type |
| type :: bar |
| type(foo) :: f |
| end type |
| type(bar) :: a |
| integer :: lm(5) |
| |
| lm(1:5) = a%f%m(1:5) |
| end subroutine |
| |
| function sub40_call(x, y, n) result(z) |
| integer :: n |
| real, device :: x(n) |
| real, device :: y(n) |
| real :: z |
| z = 0.0 |
| end function |
| |
| subroutine sub40() |
| real, device :: x(10) |
| real, device :: y(10) |
| real :: res |
| res = sub40_call(x, y, 10) |
| end subroutine |
| |
| subroutine sub41() |
| type :: bar |
| integer, device, allocatable :: m(:) |
| end type |
| type(bar), managed :: a |
| integer, managed :: lm(5) |
| |
| lm(1:5) = a%m(1:5) |
| end subroutine |
| |
| subroutine sub42() |
| use mod1 |
| real :: a |
| a = c1 * c1 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub42() |
| ! CHECK: %[[RES:.*]] = arith.mulf |
| ! CHECK: fir.store %[[RES]] to %{{.*}} : !fir.ref<f32> |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub43() |
| use mod1 |
| real :: a |
| a = d1 * d1 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub43() |
| ! CHECK: %[[RES:.*]] = arith.mulf |
| ! CHECK: fir.store %[[RES]] to %{{.*}} : !fir.ref<f32> |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub44() |
| use mod1 |
| real :: a |
| a = -d1 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub44() |
| ! CHECK: arith.negf |
| ! CHECK-NOT: cuf.data_transfer |
| |
| subroutine sub45(c0_d, n) |
| implicit none |
| integer :: n |
| complex(8), device :: c0_d(:,:) |
| complex(8), allocatable :: cx(:,:) |
| call compute(cx) |
| contains |
| subroutine compute(cx) |
| complex(8), intent(inout) :: cx(:,:) |
| c0_d = cx |
| end subroutine |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub45 |
| ! CHECK-LABEL: @_QFsub45Pcompute |
| ! CHECK: cuf.data_transfer %{{.*}} to %{{.*}} {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.box<!fir.array<?x?xcomplex<f64>>>, !fir.box<!fir.array<?x?xcomplex<f64>>> |
| |
| subroutine sub46() |
| use mod1 |
| csconst = rconst * pi/6 |
| end subroutine |
| |
| ! CHECK-LABEL: func.func @_QPsub46() |
| ! CHECK: cuf.data_transfer |
| ! CHECK: arith.mulf |
| ! CHECK: arith.constant |
| ! CHECK: arith.divf |
| ! CHECK: hlfir.assign |
| ! CHECK: cuf.data_transfer |