Skip to content

Commit

Permalink
[flang][cuda] Move CUDA Fortran operations to a CUF dialect (llvm#92317)
Browse files Browse the repository at this point in the history
The number of operations dedicated to CUF grew and where all still in
FIR. In order to have a better organization, the CUF operations,
attributes and code is moved into their specific dialect and files. CUF
dialect is tightly coupled with HLFIR/FIR and their types.

The CUF attributes are bundled into their own library since some
HLFIR/FIR operations depend on them and the CUF dialect depends on the
FIR types. Without having the attributes into a separate library there
would be a dependency cycle.
  • Loading branch information
clementval authored May 17, 2024
1 parent d90159a commit 45daa4f
Show file tree
Hide file tree
Showing 56 changed files with 1,184 additions and 817 deletions.
10 changes: 7 additions & 3 deletions flang/include/flang/Lower/ConvertVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
#include "mlir/IR/Value.h"
#include "llvm/ADT/DenseMap.h"

namespace cuf {
class DataAttributeAttr;
}

namespace fir {
class ExtendedValue;
class FirOpBuilder;
Expand Down Expand Up @@ -146,9 +150,9 @@ translateSymbolAttributes(mlir::MLIRContext *mlirContext,

/// Translate the CUDA Fortran attributes of \p sym into the FIR CUDA attribute
/// representation.
fir::CUDADataAttributeAttr
translateSymbolCUDADataAttribute(mlir::MLIRContext *mlirContext,
const Fortran::semantics::Symbol &sym);
cuf::DataAttributeAttr
translateSymbolCUFDataAttribute(mlir::MLIRContext *mlirContext,
const Fortran::semantics::Symbol &sym);

/// Map a symbol to a given fir::ExtendedValue. This will generate an
/// hlfir.declare when lowering to HLFIR and map the hlfir.declare result to the
Expand Down
4 changes: 2 additions & 2 deletions flang/include/flang/Optimizer/Builder/FIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,13 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
mlir::StringAttr linkage = {},
mlir::Attribute value = {}, bool isConst = false,
bool isTarget = false,
fir::CUDADataAttributeAttr cudaAttr = {});
cuf::DataAttributeAttr dataAttr = {});

fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type,
llvm::StringRef name, bool isConst, bool isTarget,
std::function<void(FirOpBuilder &)> bodyBuilder,
mlir::StringAttr linkage = {},
fir::CUDADataAttributeAttr cudaAttr = {});
cuf::DataAttributeAttr dataAttr = {});

/// Create a global constant (read-only) value.
fir::GlobalOp createGlobalConstant(mlir::Location loc, mlir::Type type,
Expand Down
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Builder/HLFIRTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
const fir::ExtendedValue &exv, llvm::StringRef name,
fir::FortranVariableFlagsAttr flags,
mlir::Value dummyScope = nullptr,
fir::CUDADataAttributeAttr cudaAttr = {});
cuf::DataAttributeAttr dataAttr = {});

/// Generate an hlfir.associate to build a variable from an expression value.
/// The type of the variable must be provided so that scalar logicals are
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
add_subdirectory(CUF)

# This replicates part of the add_mlir_dialect cmake function from MLIR that
# cannot be used her because it expects to be run inside MLIR directory which
# is not the case for FIR.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
set(LLVM_TARGET_DEFINITIONS CUFAttr.td)
mlir_tablegen(CUFEnumAttr.h.inc -gen-enum-decls)
mlir_tablegen(CUFEnumAttr.cpp.inc -gen-enum-defs)
mlir_tablegen(CUFAttr.h.inc --gen-attrdef-decls)
mlir_tablegen(CUFAttr.cpp.inc -gen-attrdef-defs)

add_public_tablegen_target(CUFAttrsIncGen)
106 changes: 106 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//===-- Optimizer/Dialect/CUF/Attributes/CUFAttr.h -- CUF attributes ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_DIALECT_CUF_CUFATTR_H
#define FORTRAN_OPTIMIZER_DIALECT_CUF_CUFATTR_H

#include "flang/Common/Fortran.h"
#include "mlir/IR/BuiltinAttributes.h"

namespace llvm {
class StringRef;
}

#include "flang/Optimizer/Dialect/CUF/Attributes/CUFEnumAttr.h.inc"

#define GET_ATTRDEF_CLASSES
#include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h.inc"

namespace cuf {

/// Attribute to mark Fortran entities with the CUDA attribute.
static constexpr llvm::StringRef getDataAttrName() { return "cuf.data_attr"; }
static constexpr llvm::StringRef getProcAttrName() { return "cuf.proc_attr"; }

/// Attribute to carry CUDA launch_bounds values.
static constexpr llvm::StringRef getLaunchBoundsAttrName() {
return "cuf.launch_bounds";
}

/// Attribute to carry CUDA cluster_dims values.
static constexpr llvm::StringRef getClusterDimsAttrName() {
return "cuf.cluster_dims";
}

inline cuf::DataAttributeAttr
getDataAttribute(mlir::MLIRContext *mlirContext,
std::optional<Fortran::common::CUDADataAttr> cudaAttr) {
if (cudaAttr) {
cuf::DataAttribute attr;
switch (*cudaAttr) {
case Fortran::common::CUDADataAttr::Constant:
attr = cuf::DataAttribute::Constant;
break;
case Fortran::common::CUDADataAttr::Device:
attr = cuf::DataAttribute::Device;
break;
case Fortran::common::CUDADataAttr::Managed:
attr = cuf::DataAttribute::Managed;
break;
case Fortran::common::CUDADataAttr::Pinned:
attr = cuf::DataAttribute::Pinned;
break;
case Fortran::common::CUDADataAttr::Shared:
attr = cuf::DataAttribute::Shared;
break;
case Fortran::common::CUDADataAttr::Texture:
// Obsolete attribute
return {};
case Fortran::common::CUDADataAttr::Unified:
attr = cuf::DataAttribute::Unified;
break;
}
return cuf::DataAttributeAttr::get(mlirContext, attr);
}
return {};
}

inline cuf::ProcAttributeAttr
getProcAttribute(mlir::MLIRContext *mlirContext,
std::optional<Fortran::common::CUDASubprogramAttrs> cudaAttr) {
if (cudaAttr) {
cuf::ProcAttribute attr;
switch (*cudaAttr) {
case Fortran::common::CUDASubprogramAttrs::Host:
attr = cuf::ProcAttribute::Host;
break;
case Fortran::common::CUDASubprogramAttrs::Device:
attr = cuf::ProcAttribute::Device;
break;
case Fortran::common::CUDASubprogramAttrs::HostDevice:
attr = cuf::ProcAttribute::HostDevice;
break;
case Fortran::common::CUDASubprogramAttrs::Global:
attr = cuf::ProcAttribute::Global;
break;
case Fortran::common::CUDASubprogramAttrs::Grid_Global:
attr = cuf::ProcAttribute::GridGlobal;
break;
}
return cuf::ProcAttributeAttr::get(mlirContext, attr);
}
return {};
}

} // namespace cuf

#endif // FORTRAN_OPTIMIZER_DIALECT_CUF_CUFATTR_H
100 changes: 100 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//===- CUFAttr.td - CUF Attributes -------------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the CUF dialect attributes.
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_DIALECT_CUF_CUFATTRS
#define FORTRAN_DIALECT_CUF_CUFATTRS

include "flang/Optimizer/Dialect/CUF/CUFDialect.td"
include "mlir/IR/EnumAttr.td"

class cuf_Attr<string name> : AttrDef<CUFDialect, name>;

def cuf_DataAttribute : I32EnumAttr<
"DataAttribute",
"CUDA Fortran variable attributes",
[
I32EnumAttrCase<"Constant", 0, "constant">,
I32EnumAttrCase<"Device", 1, "device">,
I32EnumAttrCase<"Managed", 2, "managed">,
I32EnumAttrCase<"Pinned", 3, "pinned">,
I32EnumAttrCase<"Shared", 4, "shared">,
I32EnumAttrCase<"Unified", 5, "unified">,
// Texture is omitted since it is obsolete and rejected by semantic.
]> {
let genSpecializedAttr = 0;
let cppNamespace = "::cuf";
}

def cuf_DataAttributeAttr :
EnumAttr<CUFDialect, cuf_DataAttribute, "cuda"> {
let assemblyFormat = [{ ```<` $value `>` }];
}

def cuf_ProcAttribute : I32EnumAttr<
"ProcAttribute", "CUDA Fortran procedure attributes",
[
I32EnumAttrCase<"Host", 0, "host">,
I32EnumAttrCase<"Device", 1, "device">,
I32EnumAttrCase<"HostDevice", 2, "host_device">,
I32EnumAttrCase<"Global", 3, "global">,
I32EnumAttrCase<"GridGlobal", 4, "grid_global">,
]> {
let genSpecializedAttr = 0;
let cppNamespace = "::cuf";
}

def cuf_ProcAttributeAttr :
EnumAttr<CUFDialect, cuf_ProcAttribute, "cuda_proc"> {
let assemblyFormat = [{ ```<` $value `>` }];
}

def cuf_LaunchBoundsAttr : cuf_Attr<"LaunchBounds"> {
let mnemonic = "launch_bounds";

let parameters = (ins
"mlir::IntegerAttr":$maxTPB,
"mlir::IntegerAttr":$minBPM,
OptionalParameter<"mlir::IntegerAttr">:$upperBoundClusterSize
);

let assemblyFormat = "`<` struct(params) `>`";
}

def cuf_ClusterDimsAttr : cuf_Attr<"ClusterDims"> {
let mnemonic = "cluster_dims";

let parameters = (ins
"mlir::IntegerAttr":$x,
"mlir::IntegerAttr":$y,
"mlir::IntegerAttr":$z
);

let assemblyFormat = "`<` struct(params) `>`";
}

def cuf_DataTransferKind : I32EnumAttr<
"DataTransferKind", "CUDA Fortran data transfer kind",
[
I32EnumAttrCase<"DeviceHost", 0, "device_host">,
I32EnumAttrCase<"HostDevice", 1, "host_device">,
I32EnumAttrCase<"DeviceDevice", 2, "device_device">,
]> {
let genSpecializedAttr = 0;
let cppNamespace = "::cuf";
}

def cuf_DataTransferKindAttr :
EnumAttr<CUFDialect, cuf_DataTransferKind, "cuda_transfer"> {
let assemblyFormat = [{ ```<` $value `>` }];
}

#endif // FORTRAN_DIALECT_CUF_CUFATTRS
11 changes: 11 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CUF/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_subdirectory(Attributes)

set(LLVM_TARGET_DEFINITIONS CUFDialect.td)
mlir_tablegen(CUFDialect.h.inc -gen-dialect-decls -dialect=cuf)
mlir_tablegen(CUFDialect.cpp.inc -gen-dialect-defs -dialect=cuf)

set(LLVM_TARGET_DEFINITIONS CUFOps.td)
mlir_tablegen(CUFOps.h.inc -gen-op-decls)
mlir_tablegen(CUFOps.cpp.inc -gen-op-defs)

add_public_tablegen_target(CUFOpsIncGen)
26 changes: 26 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CUF/CUFDialect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Optimizer/Dialect/CUFDialect.h -- CUF dialect -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_DIALECT_CUF_CUFDIALECT_H
#define FORTRAN_OPTIMIZER_DIALECT_CUF_CUFDIALECT_H

#include "mlir/Bytecode/BytecodeOpInterface.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "mlir/Interfaces/FunctionInterfaces.h"
#include "mlir/Interfaces/LoopLikeInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"

#include "flang/Optimizer/Dialect/CUF/CUFDialect.h.inc"

#endif // FORTRAN_OPTIMIZER_DIALECT_CUF_CUFDIALECT_H
43 changes: 43 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CUF/CUFDialect.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- CUFDialect.td - CUF dialect base definitions -------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Definition of the CUDA Fortran dialect
///
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_DIALECT_CUF_CUFDIALECT
#define FORTRAN_DIALECT_CUF_CUFDIALECT

include "mlir/IR/AttrTypeBase.td"
include "mlir/IR/EnumAttr.td"
include "mlir/IR/OpBase.td"

def CUFDialect : Dialect {
let name = "cuf";

let summary = "CUDA Fortran dialect";

let description = [{
This dialect models CUDA Fortran operations. The CUF dialect operations use
the FIR types and are tightly coupled with FIR and HLFIR.
}];

let useDefaultAttributePrinterParser = 1;
let usePropertiesForAttributes = 1;
let cppNamespace = "::cuf";
let dependentDialects = ["fir::FIROpsDialect"];

let extraClassDeclaration = [{
private:
// Register the CUF Attributes.
void registerAttributes();
}];
}

#endif // FORTRAN_DIALECT_CUF_CUFDIALECT
20 changes: 20 additions & 0 deletions flang/include/flang/Optimizer/Dialect/CUF/CUFOps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Optimizer/Dialect/CUF/CUFOps.h - CUF operations ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_DIALECT_CUF_CUFOPS_H
#define FORTRAN_OPTIMIZER_DIALECT_CUF_CUFOPS_H

#include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h"
#include "flang/Optimizer/Dialect/CUF/CUFDialect.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "mlir/IR/OpDefinition.h"

#define GET_OP_CLASSES
#include "flang/Optimizer/Dialect/CUF/CUFOps.h.inc"

#endif // FORTRAN_OPTIMIZER_DIALECT_CUF_CUFOPS_H
Loading

0 comments on commit 45daa4f

Please sign in to comment.