diff --git a/flang/include/flang/Common/Fortran.h b/flang/include/flang/Common/Fortran.h index ac1973fdff667..2a53452a2774f 100644 --- a/flang/include/flang/Common/Fortran.h +++ b/flang/include/flang/Common/Fortran.h @@ -85,7 +85,8 @@ static constexpr int maxRank{15}; ENUM_CLASS(CUDASubprogramAttrs, Host, Device, HostDevice, Global, Grid_Global) // CUDA data attributes; mutually exclusive -ENUM_CLASS(CUDADataAttr, Constant, Device, Managed, Pinned, Shared, Texture) +ENUM_CLASS( + CUDADataAttr, Constant, Device, Managed, Pinned, Shared, Texture, Unified) // OpenACC device types ENUM_CLASS( diff --git a/flang/include/flang/Optimizer/Support/Utils.h b/flang/include/flang/Optimizer/Support/Utils.h index 7a8a34c25ce95..2b4fa50e0e421 100644 --- a/flang/include/flang/Optimizer/Support/Utils.h +++ b/flang/include/flang/Optimizer/Support/Utils.h @@ -158,6 +158,9 @@ getCUDADataAttribute(mlir::MLIRContext *mlirContext, case Fortran::common::CUDADataAttr::Texture: // Obsolete attribute return {}; + case Fortran::common::CUDADataAttr::Unified: + attr = fir::CUDADataAttribute::Unified; + break; } return fir::CUDADataAttributeAttr::get(mlirContext, attr); } diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index be59e3912a36f..574a95cf22afd 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -991,7 +991,7 @@ struct ComponentArraySpec { // access-spec | ALLOCATABLE | // CODIMENSION lbracket coarray-spec rbracket | // CONTIGUOUS | DIMENSION ( component-array-spec ) | POINTER | -// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE +// (CUDA) CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE | UNIFIED EMPTY_CLASS(Allocatable); EMPTY_CLASS(Pointer); EMPTY_CLASS(Contiguous); diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index 5186d3baa54c3..2bdb8e38db95d 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -703,13 +703,15 @@ TYPE_PARSER(construct(accessSpec) || extension( construct(Parser{}))) -// CUDA-data-attr -> CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE +// CUDA-data-attr -> +// CONSTANT | DEVICE | MANAGED | PINNED | SHARED | TEXTURE | UNIFIED TYPE_PARSER("CONSTANT" >> pure(common::CUDADataAttr::Constant) || "DEVICE" >> pure(common::CUDADataAttr::Device) || "MANAGED" >> pure(common::CUDADataAttr::Managed) || "PINNED" >> pure(common::CUDADataAttr::Pinned) || "SHARED" >> pure(common::CUDADataAttr::Shared) || - "TEXTURE" >> pure(common::CUDADataAttr::Texture)) + "TEXTURE" >> pure(common::CUDADataAttr::Texture) || + "UNIFIED" >> pure(common::CUDADataAttr::Unified)) // R804 object-name -> name constexpr auto objectName{name}; diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index b2de37759a061..824f1b6053ca3 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -988,6 +988,13 @@ void CheckHelper::CheckObjectEntity( symbol.name()); } break; + case common::CUDADataAttr::Unified: + if ((!subpDetails || inDeviceSubprogram) && !isComponent) { + messages_.Say( + "Object '%s' with ATTRIBUTES(UNIFIED) must be declared in a host subprogram"_err_en_US, + symbol.name()); + } + break; case common::CUDADataAttr::Texture: messages_.Say( "ATTRIBUTES(TEXTURE) is obsolete and no longer supported"_err_en_US); diff --git a/flang/test/Lower/CUDA/cuda-data-attribute.cuf b/flang/test/Lower/CUDA/cuda-data-attribute.cuf index 94aa62352c2a0..937c981bddd36 100644 --- a/flang/test/Lower/CUDA/cuda-data-attribute.cuf +++ b/flang/test/Lower/CUDA/cuda-data-attribute.cuf @@ -19,16 +19,20 @@ subroutine local_var_attrs real, device :: rd real, allocatable, managed :: rm real, allocatable, pinned :: rp + real, unified :: ru end subroutine ! CHECK-LABEL: func.func @_QMcuda_varPlocal_var_attrs() ! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFlocal_var_attrsErd"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMcuda_varFlocal_var_attrsErm"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) ! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMcuda_varFlocal_var_attrsErp"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFlocal_var_attrsEru"} : (!fir.ref) -> (!fir.ref, !fir.ref) + ! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFlocal_var_attrsErd"} : (!fir.ref) -> !fir.ref ! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMcuda_varFlocal_var_attrsErm"} : (!fir.ref>>) -> !fir.ref>> ! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMcuda_varFlocal_var_attrsErp"} : (!fir.ref>>) -> !fir.ref>> +! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFlocal_var_attrsEru"} : (!fir.ref) -> !fir.ref subroutine dummy_arg_device(dd) real, device :: dd @@ -51,4 +55,11 @@ end subroutine ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>> {fir.bindc_name = "dp", fir.cuda_attr = #fir.cuda}) { ! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMcuda_varFdummy_arg_pinnedEdp"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +subroutine dummy_arg_unified(du) + real, unified :: du +end subroutine +! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_unified( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "du", fir.cuda_attr = #fir.cuda}) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFdummy_arg_unifiedEdu"} : (!fir.ref) -> (!fir.ref, !fir.ref) + end module diff --git a/flang/test/Semantics/cuf03.cuf b/flang/test/Semantics/cuf03.cuf index 7384a104831d8..574add9faaade 100644 --- a/flang/test/Semantics/cuf03.cuf +++ b/flang/test/Semantics/cuf03.cuf @@ -1,6 +1,12 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 ! Exercise CUDA data attribute checks module m + type :: t1 + integer :: i + end type + type :: t2 + real, unified :: r(10) ! ok + end type real, constant :: mc ! ok real, constant :: mci = 1. ! ok !ERROR: Object 'mcl' with ATTRIBUTES(CONSTANT) may not be allocatable, pointer, or target @@ -48,6 +54,9 @@ module m real, texture, pointer :: mt !ERROR: 'bigint' has intrinsic type 'INTEGER(16)' that is not available on the device integer(16), device :: bigint + !ERROR: Object 'um' with ATTRIBUTES(UNIFIED) must be declared in a host subprogram + real, unified :: um + contains attributes(device) subroutine devsubr(n,da) integer, intent(in) :: n @@ -57,6 +66,8 @@ module m !WARNING: Pointer 'dp' may not be associated in a device subprogram real, device, pointer :: dp real, constant :: rc ! ok + !ERROR: Object 'u' with ATTRIBUTES(UNIFIED) must be declared in a host subprogram + real, unified :: u end subroutine subroutine host() @@ -70,4 +81,10 @@ module m rs = 1 ! ok end subroutine + subroutine host2() + real, unified :: ru ! ok + type(t1), unified :: tu ! ok + type(t2) :: t ! ok + end subroutine + end module