diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index 5384f6e8121ec..f50dacd327a7c 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -230,12 +230,14 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener { llvm::StringRef name, mlir::StringAttr linkage = {}, mlir::Attribute value = {}, bool isConst = false, - bool isTarget = false); + bool isTarget = false, + fir::CUDAAttributeAttr cudaAttr = {}); fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst, bool isTarget, std::function bodyBuilder, - mlir::StringAttr linkage = {}); + mlir::StringAttr linkage = {}, + fir::CUDAAttributeAttr cudaAttr = {}); /// Create a global constant (read-only) value. fir::GlobalOp createGlobalConstant(mlir::Location loc, mlir::Type type, diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index b954a0cc74d0e..d505fedd6e641 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -2737,7 +2737,8 @@ def fir_GlobalOp : fir_Op<"global", [IsolatedFromAbove, Symbol]> { OptionalAttr:$initVal, OptionalAttr:$constant, OptionalAttr:$target, - OptionalAttr:$linkName + OptionalAttr:$linkName, + OptionalAttr:$cuda_attr ); let regions = (region AtMostRegion<1>:$region); diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index f14267f123421..2f23757f497ea 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -138,7 +138,8 @@ static bool isConstant(const Fortran::semantics::Symbol &sym) { static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter, const Fortran::lower::pft::Variable &var, llvm::StringRef globalName, - mlir::StringAttr linkage); + mlir::StringAttr linkage, + fir::CUDAAttributeAttr cudaAttr = {}); static mlir::Location genLocation(Fortran::lower::AbstractConverter &converter, const Fortran::semantics::Symbol &sym) { @@ -462,7 +463,8 @@ void Fortran::lower::createGlobalInitialization( static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter, const Fortran::lower::pft::Variable &var, llvm::StringRef globalName, - mlir::StringAttr linkage) { + mlir::StringAttr linkage, + fir::CUDAAttributeAttr cudaAttr) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); const Fortran::semantics::Symbol &sym = var.getSymbol(); mlir::Location loc = genLocation(converter, sym); @@ -500,8 +502,9 @@ static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter, } } if (!global) - global = builder.createGlobal(loc, symTy, globalName, linkage, - mlir::Attribute{}, isConst, var.isTarget()); + global = + builder.createGlobal(loc, symTy, globalName, linkage, mlir::Attribute{}, + isConst, var.isTarget(), cudaAttr); if (Fortran::semantics::IsAllocatableOrPointer(sym) && !Fortran::semantics::IsProcedure(sym)) { const auto *details = @@ -2219,7 +2222,10 @@ void Fortran::lower::defineModuleVariable( // Do nothing. Mapping will be done on user side. } else { std::string globalName = converter.mangleName(sym); - defineGlobal(converter, var, globalName, linkage); + fir::CUDAAttributeAttr cudaAttr = + Fortran::lower::translateSymbolCUDAAttribute( + converter.getFirOpBuilder().getContext(), sym); + defineGlobal(converter, var, globalName, linkage, cudaAttr); } } diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 141f8fcd3ab5f..68fe8de550bb0 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -271,19 +271,24 @@ mlir::Value fir::FirOpBuilder::createHeapTemporary( /// Create a global variable in the (read-only) data section. A global variable /// must have a unique name to identify and reference it. -fir::GlobalOp fir::FirOpBuilder::createGlobal(mlir::Location loc, - mlir::Type type, - llvm::StringRef name, - mlir::StringAttr linkage, - mlir::Attribute value, - bool isConst, bool isTarget) { +fir::GlobalOp fir::FirOpBuilder::createGlobal( + mlir::Location loc, mlir::Type type, llvm::StringRef name, + mlir::StringAttr linkage, mlir::Attribute value, bool isConst, + bool isTarget, fir::CUDAAttributeAttr cudaAttr) { auto module = getModule(); auto insertPt = saveInsertionPoint(); if (auto glob = module.lookupSymbol(name)) return glob; setInsertionPoint(module.getBody(), module.getBody()->end()); - auto glob = - create(loc, name, isConst, isTarget, type, value, linkage); + llvm::SmallVector attrs; + if (cudaAttr) { + auto globalOpName = mlir::OperationName(fir::GlobalOp::getOperationName(), + module.getContext()); + attrs.push_back(mlir::NamedAttribute( + fir::GlobalOp::getCudaAttrAttrName(globalOpName), cudaAttr)); + } + auto glob = create(loc, name, isConst, isTarget, type, value, + linkage, attrs); restoreInsertionPoint(insertPt); return glob; } @@ -291,7 +296,7 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal(mlir::Location loc, fir::GlobalOp fir::FirOpBuilder::createGlobal( mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst, bool isTarget, std::function bodyBuilder, - mlir::StringAttr linkage) { + mlir::StringAttr linkage, fir::CUDAAttributeAttr cudaAttr) { auto module = getModule(); auto insertPt = saveInsertionPoint(); if (auto glob = module.lookupSymbol(name)) diff --git a/flang/test/Lower/CUDA/cuda-data-attribute.cuf b/flang/test/Lower/CUDA/cuda-data-attribute.cuf index b02701bf3aea5..7596c6b21efb0 100644 --- a/flang/test/Lower/CUDA/cuda-data-attribute.cuf +++ b/flang/test/Lower/CUDA/cuda-data-attribute.cuf @@ -3,6 +3,18 @@ ! Test lowering of CUDA attribute on variables. +module cuda_var + real, constant :: mod_a_rc +! CHECK: fir.global @_QMcuda_varEmod_a_rc {cuda_attr = #fir.cuda} : f32 + real, device :: mod_b_ra +! CHECK: fir.global @_QMcuda_varEmod_b_ra {cuda_attr = #fir.cuda} : f32 + real, allocatable, managed :: mod_c_rm +! CHECK: fir.global @_QMcuda_varEmod_c_rm {cuda_attr = #fir.cuda} : !fir.box> + real, allocatable, pinned :: mod_d_rp +! CHECK: fir.global @_QMcuda_varEmod_d_rp {cuda_attr = #fir.cuda} : !fir.box> + +contains + subroutine local_var_attrs real, constant :: rc real, device :: rd @@ -10,46 +22,43 @@ subroutine local_var_attrs real, allocatable, pinned :: rp end subroutine -! CHECK-LABEL: func.func @_QPlocal_var_attrs() -! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QFlocal_var_attrsErc"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QFlocal_var_attrsErd"} : (!fir.ref) -> (!fir.ref, !fir.ref) -! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_var_attrsErm"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) -! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_var_attrsErp"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK-LABEL: func.func @_QMcuda_varPlocal_var_attrs() +! CHECK: %{{.*}}:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFlocal_var_attrsErc"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! 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>>) -! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QFlocal_var_attrsErc"} : (!fir.ref) -> !fir.ref -! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QFlocal_var_attrsErd"} : (!fir.ref) -> !fir.ref -! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_var_attrsErm"} : (!fir.ref>>) -> !fir.ref>> -! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFlocal_var_attrsErp"} : (!fir.ref>>) -> !fir.ref>> +! FIR: %{{.*}} = fir.declare %{{.*}} {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFlocal_var_attrsErc"} : (!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>> subroutine dummy_arg_constant(dc) real, constant :: dc end subroutine -! CHECK-LABEL: func.func @_QPdummy_arg_constant( +! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_constant( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "dc", fir.cuda_attr = #fir.cuda} -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, uniq_name = "_QFdummy_arg_constantEdc"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFdummy_arg_constantEdc"} : (!fir.ref) -> (!fir.ref, !fir.ref) subroutine dummy_arg_device(dd) real, device :: dd end subroutine -! CHECK-LABEL: func.func @_QPdummy_arg_device( +! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_device( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "dd", fir.cuda_attr = #fir.cuda}) { -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, uniq_name = "_QFdummy_arg_deviceEdd"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, uniq_name = "_QMcuda_varFdummy_arg_deviceEdd"} : (!fir.ref) -> (!fir.ref, !fir.ref) subroutine dummy_arg_managed(dm) real, allocatable, managed :: dm end subroutine -! CHECK-LABEL: func.func @_QPdummy_arg_managed( +! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_managed( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref>> {fir.bindc_name = "dm", fir.cuda_attr = #fir.cuda}) { -! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QFdummy_arg_managedEdm"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) +! CHECK: %{{.*}}:2 = hlfir.declare %[[ARG0]] {cuda_attr = #fir.cuda, fortran_attrs = #fir.var_attrs, uniq_name = "_QMcuda_varFdummy_arg_managedEdm"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) subroutine dummy_arg_pinned(dp) real, allocatable, pinned :: dp end subroutine -! CHECK-LABEL: func.func @_QPdummy_arg_pinned( +! CHECK-LABEL: func.func @_QMcuda_varPdummy_arg_pinned( ! 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 = "_QFdummy_arg_pinnedEdp"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) - - - - +! 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>>) +end module