-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[mlir][acc] Extend PointerLikeType to provide alloc, dealloc, copy #162328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
e70a67d
b17b289
809abd1
d1abaf5
0251f47
e6d71e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,6 +70,86 @@ def OpenACC_PointerLikeTypeInterface : TypeInterface<"PointerLikeType"> { | |
return ::mlir::acc::VariableTypeCategory::uncategorized; | ||
}] | ||
>, | ||
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. | ||
|
||
The `varName` parameter is optional and can be used to provide a name | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be ignored if it is present? I suppose the answer is yes, since your memref implementation does that. Maybe mention that in the description? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Being fixed here: #163861 |
||
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. | ||
|
||
The `originalVar` parameter is optional but enables support for dynamic | ||
types (e.g., dynamic memrefs). When provided, implementations can extract | ||
runtime dimension information from the original variable to create | ||
allocations with matching dynamic sizes. | ||
|
||
Returns a Value representing the result of the allocation. If no value | ||
is returned, it means the allocation was not successfully generated. | ||
}], | ||
/*retTy=*/"::mlir::Value", | ||
/*methodName=*/"genAllocate", | ||
/*args=*/(ins "::mlir::OpBuilder &":$builder, | ||
"::mlir::Location":$loc, | ||
"::llvm::StringRef":$varName, | ||
"::mlir::Type":$varType, | ||
"::mlir::Value":$originalVar), | ||
/*methodBody=*/"", | ||
/*defaultImplementation=*/[{ | ||
return {}; | ||
}] | ||
>, | ||
InterfaceMethod< | ||
/*description=*/[{ | ||
Generates deallocation operations for the pointer-like type. It deallocates | ||
the instance provided. | ||
|
||
The `varPtr` parameter is required and must represent an instance that was | ||
previously allocated. 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. Nothing is generated in case the allocate | ||
is `alloca`-like. | ||
|
||
Returns true if deallocation was successfully generated or successfully | ||
deemed as not needed to be generated, false otherwise. | ||
}], | ||
/*retTy=*/"bool", | ||
/*methodName=*/"genFree", | ||
/*args=*/(ins "::mlir::OpBuilder &":$builder, | ||
"::mlir::Location":$loc, | ||
"::mlir::TypedValue<::mlir::acc::PointerLikeType>":$varPtr, | ||
"::mlir::Type":$varType), | ||
/*methodBody=*/"", | ||
/*defaultImplementation=*/[{ | ||
return false; | ||
}] | ||
>, | ||
InterfaceMethod< | ||
/*description=*/[{ | ||
Generates copy operations for the pointer-like type. It copies the memory | ||
from the source to the destination. Typically used to initialize one | ||
variable of this type from another. | ||
|
||
The `destination` and `source` parameters represent the target and source | ||
instances respectively. 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. | ||
|
||
Returns true if copy was successfully generated, false otherwise. | ||
}], | ||
/*retTy=*/"bool", | ||
/*methodName=*/"genCopy", | ||
/*args=*/(ins "::mlir::OpBuilder &":$builder, | ||
"::mlir::Location":$loc, | ||
"::mlir::TypedValue<::mlir::acc::PointerLikeType>":$destination, | ||
"::mlir::TypedValue<::mlir::acc::PointerLikeType>":$source, | ||
"::mlir::Type":$varType), | ||
/*methodBody=*/"", | ||
/*defaultImplementation=*/[{ | ||
return false; | ||
}] | ||
>, | ||
]; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// RUN: mlir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=alloc}))" 2>&1 | FileCheck %s | ||
|
||
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> | ||
return | ||
} | ||
|
||
// ----- | ||
|
||
func.func @test_dynamic_memref_alloc() { | ||
%c10 = arith.constant 10 : index | ||
%c20 = arith.constant 20 : index | ||
%orig = memref.alloc(%c10, %c20) {test.ptr} : memref<?x?xf32> | ||
|
||
// CHECK: Successfully generated alloc for operation: %[[ORIG:.*]] = memref.alloc(%[[C10:.*]], %[[C20:.*]]) {test.ptr} : memref<?x?xf32> | ||
// CHECK: Generated: %[[C0:.*]] = arith.constant 0 : index | ||
// 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> | ||
return | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// RUN: mlir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=copy}))" 2>&1 | FileCheck %s | ||
|
||
func.func @test_copy_static() { | ||
%src = memref.alloca() {test.src_ptr} : memref<10x20xf32> | ||
%dest = memref.alloca() {test.dest_ptr} : memref<10x20xf32> | ||
|
||
// CHECK: Successfully generated copy from source: %[[SRC:.*]] = memref.alloca() {test.src_ptr} : memref<10x20xf32> to destination: %[[DEST:.*]] = memref.alloca() {test.dest_ptr} : memref<10x20xf32> | ||
// CHECK: Generated: memref.copy %[[SRC]], %[[DEST]] : memref<10x20xf32> to memref<10x20xf32> | ||
return | ||
} | ||
|
||
// ----- | ||
|
||
func.func @test_copy_dynamic() { | ||
%c10 = arith.constant 10 : index | ||
%c20 = arith.constant 20 : index | ||
%src = memref.alloc(%c10, %c20) {test.src_ptr} : memref<?x?xf32> | ||
%dest = memref.alloc(%c10, %c20) {test.dest_ptr} : memref<?x?xf32> | ||
|
||
// CHECK: Successfully generated copy from source: %[[SRC:.*]] = memref.alloc(%[[C10:.*]], %[[C20:.*]]) {test.src_ptr} : memref<?x?xf32> to destination: %[[DEST:.*]] = memref.alloc(%[[C10]], %[[C20]]) {test.dest_ptr} : memref<?x?xf32> | ||
// CHECK: Generated: memref.copy %[[SRC]], %[[DEST]] : memref<?x?xf32> to memref<?x?xf32> | ||
return | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// RUN: mlir-opt %s --split-input-file --pass-pipeline="builtin.module(func.func(test-acc-pointer-like-interface{test-mode=free}))" 2>&1 | FileCheck %s | ||
|
||
func.func @test_static_memref_free() { | ||
%0 = memref.alloca() {test.ptr} : memref<10x20xf32> | ||
// CHECK: Successfully generated free for operation: %[[ORIG:.*]] = memref.alloca() {test.ptr} : memref<10x20xf32> | ||
// CHECK-NOT: Generated | ||
return | ||
} | ||
|
||
// ----- | ||
|
||
func.func @test_dynamic_memref_free() { | ||
%c10 = arith.constant 10 : index | ||
%c20 = arith.constant 20 : index | ||
%orig = memref.alloc(%c10, %c20) {test.ptr} : memref<?x?xf32> | ||
|
||
// CHECK: Successfully generated free for operation: %[[ORIG:.*]] = memref.alloc(%[[C10:.*]], %[[C20:.*]]) {test.ptr} : memref<?x?xf32> | ||
// CHECK: Generated: memref.dealloc %[[ORIG]] : memref<?x?xf32> | ||
return | ||
} | ||
|
||
// ----- | ||
|
||
func.func @test_cast_walking_free() { | ||
%0 = memref.alloca() : memref<10x20xf32> | ||
%1 = memref.cast %0 {test.ptr} : memref<10x20xf32> to memref<?x?xf32> | ||
|
||
// CHECK: Successfully generated free for operation: %[[CAST:.*]] = memref.cast %[[ALLOCA:.*]] {test.ptr} : memref<10x20xf32> to memref<?x?xf32> | ||
// CHECK-NOT: Generated | ||
return | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
add_mlir_library(MLIROpenACCTestPasses | ||
TestOpenACC.cpp | ||
TestPointerLikeTypeInterface.cpp | ||
|
||
EXCLUDE_FROM_LIBMLIR | ||
) | ||
mlir_target_link_libraries(MLIROpenACCTestPasses PUBLIC | ||
MLIRIR | ||
MLIRArithDialect | ||
MLIRFuncDialect | ||
MLIRMemRefDialect | ||
MLIROpenACCDialect | ||
MLIRPass | ||
MLIRSupport | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//===- TestOpenACC.cpp - OpenACC Test Registration ------------------------===// | ||
// | ||
// 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 contains unified registration for all OpenACC test passes. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
namespace mlir { | ||
namespace test { | ||
|
||
// Forward declarations of individual test pass registration functions | ||
void registerTestPointerLikeTypeInterfacePass(); | ||
|
||
// Unified registration function for all OpenACC tests | ||
void registerTestOpenACC() { registerTestPointerLikeTypeInterfacePass(); } | ||
|
||
} // namespace test | ||
} // namespace mlir |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing
allocate
used as a noun is somehow jarring to me. Is this idiomatic in a way I'm just not familiar with?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Being fixed here: #163861
Thank you!