Skip to content

Commit

Permalink
[flang][cuda] Add UNIFIED data attribute (#88171)
Browse files Browse the repository at this point in the history
Latest version of the specification introduced the `UNIFIED` attribute
for data.


https://docs.nvidia.com/hpc-sdk/compilers/cuda-fortran-prog-guide/#cfref-var-attr-unified-data

This patch adds the attribute to parsing, semantic and lowering. 

The matching rules for dummy/actual arguments is not part of this patch.
  • Loading branch information
clementval committed Apr 9, 2024
1 parent a8ec1eb commit e953c86
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 4 deletions.
3 changes: 2 additions & 1 deletion flang/include/flang/Common/Fortran.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/Support/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 4 additions & 2 deletions flang/lib/Parser/Fortran-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,13 +703,15 @@ TYPE_PARSER(construct<AttrSpec>(accessSpec) ||
extension<LanguageFeature::CUDA>(
construct<AttrSpec>(Parser<common::CUDADataAttr>{})))

// 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};
Expand Down
7 changes: 7 additions & 0 deletions flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions flang/test/Lower/CUDA/cuda-data-attribute.cuf
Original file line number Diff line number Diff line change
Expand Up @@ -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<device>, uniq_name = "_QMcuda_varFlocal_var_attrsErd"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErm"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)
! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<unified>, uniq_name = "_QMcuda_varFlocal_var_attrsEru"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)


! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<device>, uniq_name = "_QMcuda_varFlocal_var_attrsErd"} : (!fir.ref<f32>) -> !fir.ref<f32>
! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErm"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<f32>>>
! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFlocal_var_attrsErp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> !fir.ref<!fir.box<!fir.heap<f32>>>
! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda<unified>, uniq_name = "_QMcuda_varFlocal_var_attrsEru"} : (!fir.ref<f32>) -> !fir.ref<f32>

subroutine dummy_arg_device(dd)
real, device :: dd
Expand All @@ -51,4 +55,11 @@ end subroutine
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<f32>>> {fir.bindc_name = "dp", fir.cuda_attr = #fir.cuda<pinned>}) {
! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda<pinned>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMcuda_varFdummy_arg_pinnedEdp"} : (!fir.ref<!fir.box<!fir.heap<f32>>>) -> (!fir.ref<!fir.box<!fir.heap<f32>>>, !fir.ref<!fir.box<!fir.heap<f32>>>)

subroutine dummy_arg_unified(du)
real, unified :: du
end subroutine
! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_unified(
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<f32> {fir.bindc_name = "du", fir.cuda_attr = #fir.cuda<unified>})
! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda<unified>, uniq_name = "_QMcuda_varFdummy_arg_unifiedEdu"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)

end module
17 changes: 17 additions & 0 deletions flang/test/Semantics/cuf03.cuf
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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

0 comments on commit e953c86

Please sign in to comment.