Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions mlir/include/mlir/Dialect/OpenACC/OpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ static constexpr StringLiteral getRoutineInfoAttrName() {
return StringLiteral("acc.routine_info");
}

static constexpr StringLiteral getVarNameAttrName() {
return VarNameAttr::name;
}

static constexpr StringLiteral getCombinedConstructsAttrName() {
return CombinedConstructsTypeAttr::name;
}
Expand Down
7 changes: 7 additions & 0 deletions mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,13 @@ def OpenACC_ConstructResource : Resource<"::mlir::acc::ConstructResource">;
// Define a resource for the OpenACC current device setting.
def OpenACC_CurrentDeviceIdResource : Resource<"::mlir::acc::CurrentDeviceIdResource">;

// Attribute for saving variable names - this can be attached to non-acc-dialect
// operations in order to ensure the name is preserved.
def OpenACC_VarNameAttr : OpenACC_Attr<"VarName", "var_name"> {
let parameters = (ins StringRefParameter<"">:$name);
let assemblyFormat = "`<` $name `>`";
}

// Used for data specification in data clauses (2.7.1).
// Either (or both) extent and upperbound must be specified.
def OpenACC_DataBoundsOp : OpenACC_Op<"bounds",
Expand Down
14 changes: 10 additions & 4 deletions mlir/include/mlir/Dialect/OpenACC/OpenACCTypeInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@ def OpenACC_PointerLikeTypeInterface : TypeInterface<"PointerLikeType"> {
InterfaceMethod<
/*description=*/[{
Generates allocation operations for the pointer-like type. It will create
an allocate that produces memory space for an instance of the current type.
an allocate operation that produces memory space for an instance of the
current type.

The `varName` parameter is optional and can be used to provide a name
for the allocated variable. If the current type is represented
in a way that it does not capture the pointee type, `varType` must be
passed in to provide the necessary type information.
for the allocated variable. When provided, it must be used by the
implementation; and if the implementing dialect does not have its own
way to save it, the discardable `acc.var_name` attribute from the acc
dialect will be used.

If the current type is represented in a way that it does not capture
the pointee type, `varType` must be passed in to provide the necessary
type information.

The `originalVar` parameter is optional but enables support for dynamic
types (e.g., dynamic memrefs). When provided, implementations can extract
Expand Down
20 changes: 17 additions & 3 deletions mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ static bool isScalarLikeType(Type type) {
return type.isIntOrIndexOrFloat() || isa<ComplexType>(type);
}

/// Helper function to attach the `VarName` attribute to an operation
/// if a variable name is provided.
static void attachVarNameAttr(Operation *op, OpBuilder &builder,
StringRef varName) {
if (!varName.empty()) {
auto varNameAttr = acc::VarNameAttr::get(builder.getContext(), varName);
op->setAttr(acc::getVarNameAttrName(), varNameAttr);
}
}

struct MemRefPointerLikeModel
: public PointerLikeType::ExternalModel<MemRefPointerLikeModel,
MemRefType> {
Expand Down Expand Up @@ -83,7 +93,9 @@ struct MemRefPointerLikeModel
// then we can generate an alloca operation.
if (memrefTy.hasStaticShape()) {
needsFree = false; // alloca doesn't need deallocation
return memref::AllocaOp::create(builder, loc, memrefTy).getResult();
auto allocaOp = memref::AllocaOp::create(builder, loc, memrefTy);
attachVarNameAttr(allocaOp, builder, varName);
return allocaOp.getResult();
}

// For dynamic memrefs, extract sizes from the original variable if
Expand All @@ -103,8 +115,10 @@ struct MemRefPointerLikeModel
// Static dimensions are handled automatically by AllocOp
}
needsFree = true; // alloc needs deallocation
return memref::AllocOp::create(builder, loc, memrefTy, dynamicSizes)
.getResult();
auto allocOp =
memref::AllocOp::create(builder, loc, memrefTy, dynamicSizes);
attachVarNameAttr(allocOp, builder, varName);
return allocOp.getResult();
}

// TODO: Unranked not yet supported.
Expand Down
4 changes: 2 additions & 2 deletions mlir/test/Dialect/OpenACC/pointer-like-interface-alloc.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
func.func @test_static_memref_alloc() {
%0 = memref.alloca() {test.ptr} : memref<10x20xf32>
// CHECK: Successfully generated alloc for operation: %[[ORIG:.*]] = memref.alloca() {test.ptr} : memref<10x20xf32>
// CHECK: Generated: %{{.*}} = memref.alloca() : memref<10x20xf32>
// CHECK: Generated: %{{.*}} = memref.alloca() {acc.var_name = #acc.var_name<"test_alloc">} : memref<10x20xf32>
return
}

Expand All @@ -19,6 +19,6 @@ func.func @test_dynamic_memref_alloc() {
// CHECK: Generated: %[[DIM0:.*]] = memref.dim %[[ORIG]], %[[C0]] : memref<?x?xf32>
// CHECK: Generated: %[[C1:.*]] = arith.constant 1 : index
// CHECK: Generated: %[[DIM1:.*]] = memref.dim %[[ORIG]], %[[C1]] : memref<?x?xf32>
// CHECK: Generated: %{{.*}} = memref.alloc(%[[DIM0]], %[[DIM1]]) : memref<?x?xf32>
// CHECK: Generated: %{{.*}} = memref.alloc(%[[DIM0]], %[[DIM1]]) {acc.var_name = #acc.var_name<"test_alloc">} : memref<?x?xf32>
return
}
10 changes: 5 additions & 5 deletions mlir/test/Dialect/OpenACC/recipe-populate-firstprivate.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// CHECK: acc.firstprivate.recipe @firstprivate_scalar : memref<f32> init {
// CHECK: ^bb0(%{{.*}}: memref<f32>):
// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<f32>
// CHECK: %[[ALLOC:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"scalar">} : memref<f32>
// CHECK: acc.yield %[[ALLOC]] : memref<f32>
// CHECK: } copy {
// CHECK: ^bb0(%[[SRC:.*]]: memref<f32>, %[[DST:.*]]: memref<f32>):
Expand All @@ -20,7 +20,7 @@ func.func @test_scalar() {

// CHECK: acc.firstprivate.recipe @firstprivate_static_2d : memref<10x20xf32> init {
// CHECK: ^bb0(%{{.*}}: memref<10x20xf32>):
// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<10x20xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"static_2d">} : memref<10x20xf32>
// CHECK: acc.yield %[[ALLOC]] : memref<10x20xf32>
// CHECK: } copy {
// CHECK: ^bb0(%[[SRC:.*]]: memref<10x20xf32>, %[[DST:.*]]: memref<10x20xf32>):
Expand All @@ -42,7 +42,7 @@ func.func @test_static_2d() {
// CHECK: %[[DIM0:.*]] = memref.dim %[[ARG]], %[[C0]] : memref<?x?xf32>
// CHECK: %[[C1:.*]] = arith.constant 1 : index
// CHECK: %[[DIM1:.*]] = memref.dim %[[ARG]], %[[C1]] : memref<?x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM0]], %[[DIM1]]) : memref<?x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM0]], %[[DIM1]]) {acc.var_name = #acc.var_name<"dynamic_2d">} : memref<?x?xf32>
// CHECK: acc.yield %[[ALLOC]] : memref<?x?xf32>
// CHECK: } copy {
// CHECK: ^bb0(%[[SRC:.*]]: memref<?x?xf32>, %[[DST:.*]]: memref<?x?xf32>):
Expand All @@ -65,7 +65,7 @@ func.func @test_dynamic_2d(%arg0: index, %arg1: index) {
// CHECK: ^bb0(%[[ARG:.*]]: memref<10x?xf32>):
// CHECK: %[[C1:.*]] = arith.constant 1 : index
// CHECK: %[[DIM1:.*]] = memref.dim %[[ARG]], %[[C1]] : memref<10x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM1]]) : memref<10x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM1]]) {acc.var_name = #acc.var_name<"mixed_dims">} : memref<10x?xf32>
// CHECK: acc.yield %[[ALLOC]] : memref<10x?xf32>
// CHECK: } copy {
// CHECK: ^bb0(%[[SRC:.*]]: memref<10x?xf32>, %[[DST:.*]]: memref<10x?xf32>):
Expand All @@ -86,7 +86,7 @@ func.func @test_mixed_dims(%arg0: index) {

// CHECK: acc.firstprivate.recipe @firstprivate_scalar_int : memref<i32> init {
// CHECK: ^bb0(%{{.*}}: memref<i32>):
// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<i32>
// CHECK: %[[ALLOC:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"scalar_int">} : memref<i32>
// CHECK: acc.yield %[[ALLOC]] : memref<i32>
// CHECK: } copy {
// CHECK: ^bb0(%[[SRC:.*]]: memref<i32>, %[[DST:.*]]: memref<i32>):
Expand Down
10 changes: 5 additions & 5 deletions mlir/test/Dialect/OpenACC/recipe-populate-private.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// CHECK: acc.private.recipe @private_scalar : memref<f32> init {
// CHECK: ^bb0(%{{.*}}: memref<f32>):
// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<f32>
// CHECK: %[[ALLOC:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"scalar">} : memref<f32>
// CHECK: acc.yield %[[ALLOC]] : memref<f32>
// CHECK: }
// CHECK-NOT: destroy
Expand All @@ -16,7 +16,7 @@ func.func @test_scalar() {

// CHECK: acc.private.recipe @private_static_2d : memref<10x20xf32> init {
// CHECK: ^bb0(%{{.*}}: memref<10x20xf32>):
// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<10x20xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"static_2d">} : memref<10x20xf32>
// CHECK: acc.yield %[[ALLOC]] : memref<10x20xf32>
// CHECK: }
// CHECK-NOT: destroy
Expand All @@ -34,7 +34,7 @@ func.func @test_static_2d() {
// CHECK: %[[DIM0:.*]] = memref.dim %[[ARG]], %[[C0]] : memref<?x?xf32>
// CHECK: %[[C1:.*]] = arith.constant 1 : index
// CHECK: %[[DIM1:.*]] = memref.dim %[[ARG]], %[[C1]] : memref<?x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM0]], %[[DIM1]]) : memref<?x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM0]], %[[DIM1]]) {acc.var_name = #acc.var_name<"dynamic_2d">} : memref<?x?xf32>
// CHECK: acc.yield %[[ALLOC]] : memref<?x?xf32>
// CHECK: } destroy {
// CHECK: ^bb0(%{{.*}}: memref<?x?xf32>, %[[VAL:.*]]: memref<?x?xf32>):
Expand All @@ -53,7 +53,7 @@ func.func @test_dynamic_2d(%arg0: index, %arg1: index) {
// CHECK: ^bb0(%[[ARG:.*]]: memref<10x?xf32>):
// CHECK: %[[C1:.*]] = arith.constant 1 : index
// CHECK: %[[DIM1:.*]] = memref.dim %[[ARG]], %[[C1]] : memref<10x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM1]]) : memref<10x?xf32>
// CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM1]]) {acc.var_name = #acc.var_name<"mixed_dims">} : memref<10x?xf32>
// CHECK: acc.yield %[[ALLOC]] : memref<10x?xf32>
// CHECK: } destroy {
// CHECK: ^bb0(%{{.*}}: memref<10x?xf32>, %[[VAL:.*]]: memref<10x?xf32>):
Expand All @@ -70,7 +70,7 @@ func.func @test_mixed_dims(%arg0: index) {

// CHECK: acc.private.recipe @private_scalar_int : memref<i32> init {
// CHECK: ^bb0(%{{.*}}: memref<i32>):
// CHECK: %[[ALLOC:.*]] = memref.alloca() : memref<i32>
// CHECK: %[[ALLOC:.*]] = memref.alloca() {acc.var_name = #acc.var_name<"scalar_int">} : memref<i32>
// CHECK: acc.yield %[[ALLOC]] : memref<i32>
// CHECK: }
// CHECK-NOT: destroy
Expand Down