-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[MLIR][GPU-LLVM] Add in-pass signature update option for opencl kernels #105664
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 1 commit
2e8465c
9238460
7212344
1961dff
53baba2
4b18490
dfbcd23
b39e055
d5519a5
598f9b1
3fde4ae
71006c6
a1666d6
c2b22c7
a0a5a00
abb6ef9
0f79242
69ed255
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 |
---|---|---|
|
@@ -306,6 +306,51 @@ struct GPUShuffleConversion final : ConvertOpToLLVMPattern<gpu::ShuffleOp> { | |
} | ||
}; | ||
|
||
class MemorySpaceToOpenCLMemorySpaceConverter : public TypeConverter { | ||
public: | ||
explicit MemorySpaceToOpenCLMemorySpaceConverter() { | ||
kurapov-peter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
addConversion([](Type t) { return t; }); | ||
addConversion( | ||
[this](BaseMemRefType memRefType) -> std::optional<Type> { | ||
std::optional<gpu::AddressSpace> addrSpace = | ||
memorySpaceMap(memRefType.getMemorySpace()); | ||
if (!addrSpace) { | ||
LLVM_DEBUG( | ||
llvm::dbgs() | ||
<< "cannot convert " << memRefType | ||
<< " due to being unable to find address space in the map\n"); | ||
return std::nullopt; | ||
} | ||
auto addrSpaceAttr = | ||
gpu::AddressSpaceAttr::get(memRefType.getContext(), *addrSpace); | ||
if (auto rankedType = dyn_cast<MemRefType>(memRefType)) { | ||
return MemRefType::get(memRefType.getShape(), | ||
memRefType.getElementType(), | ||
rankedType.getLayout(), addrSpaceAttr); | ||
} | ||
return UnrankedMemRefType::get(memRefType.getElementType(), | ||
addrSpaceAttr); | ||
}); | ||
addConversion([this](FunctionType type) { | ||
auto inputs = llvm::map_to_vector( | ||
type.getInputs(), [this](Type ty) { return convertType(ty); }); | ||
auto results = llvm::map_to_vector( | ||
type.getResults(), [this](Type ty) { return convertType(ty); }); | ||
return FunctionType::get(type.getContext(), inputs, results); | ||
}); | ||
} | ||
|
||
private: | ||
std::optional<gpu::AddressSpace> memorySpaceMap(Attribute memSpaceAttr) { | ||
if (!memSpaceAttr) | ||
return gpu::AddressSpace::Global; | ||
auto gpuAddrSpace = dyn_cast<gpu::AddressSpaceAttr>(memSpaceAttr); | ||
if (!gpuAddrSpace) | ||
return std::nullopt; | ||
return gpuAddrSpace.getValue(); | ||
} | ||
kurapov-peter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
|
||
//===----------------------------------------------------------------------===// | ||
// GPU To LLVM-SPV Pass. | ||
//===----------------------------------------------------------------------===// | ||
|
@@ -325,6 +370,20 @@ struct GPUToLLVMSPVConversionPass final | |
LLVMTypeConverter converter(context, options); | ||
LLVMConversionTarget target(*context); | ||
|
||
if (forceOpenclAddressSpaces) { | ||
MemorySpaceToOpenCLMemorySpaceConverter converter; | ||
AttrTypeReplacer replacer; | ||
replacer.addReplacement([&converter](BaseMemRefType origType) | ||
-> std::optional<BaseMemRefType> { | ||
return converter.convertType<BaseMemRefType>(origType); | ||
}); | ||
|
||
replacer.recursivelyReplaceElementsIn(getOperation(), | ||
/*replaceAttrs=*/true, | ||
/*replaceLocs=*/false, | ||
/*replaceTypes=*/true); | ||
} | ||
|
||
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. This looks like an overkill, isn't there another way? 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. I tried a natural way - putting additional conversion to the llvm converter but it didn't work out. First, it expects a legal value as the output, so I can't just add a memref. I tried to run So instead, I added this. It doesn't have to think about legality and all since it's not an llvm converter. 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. I took a look into this once more. It seems like if I were to reuse 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. True, conversion to LLVM assumes memspace |
||
target.addIllegalOp<gpu::BarrierOp, gpu::BlockDimOp, gpu::BlockIdOp, | ||
gpu::GPUFuncOp, gpu::GlobalIdOp, gpu::GridDimOp, | ||
gpu::ReturnOp, gpu::ShuffleOp, gpu::ThreadIdOp>(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
// RUN: | FileCheck --check-prefixes=CHECK-64,CHECK %s | ||
// RUN: mlir-opt -pass-pipeline="builtin.module(gpu.module(convert-gpu-to-llvm-spv{index-bitwidth=32}))" -split-input-file -verify-diagnostics %s \ | ||
// RUN: | FileCheck --check-prefixes=CHECK-32,CHECK %s | ||
// RUN: mlir-opt -pass-pipeline="builtin.module(gpu.module(convert-gpu-to-llvm-spv{force-opencl-address-spaces}))" -split-input-file -verify-diagnostics %s \ | ||
// RUN: | FileCheck --check-prefixes=OPENCL %s | ||
kurapov-peter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
gpu.module @builtins { | ||
// CHECK-64: llvm.func spir_funccc @_Z14get_num_groupsj(i32) -> i64 attributes { | ||
|
@@ -515,3 +517,15 @@ gpu.module @kernels { | |
gpu.return | ||
} | ||
} | ||
|
||
// ----- | ||
|
||
gpu.module @kernels { | ||
// OPENCL-LABEL: llvm.func spir_funccc @no_address_spaces( | ||
// OPENCL-SAME: %{{[a-zA-Z_][a-zA-Z0-9_]*}}: !llvm.ptr<1> | ||
// OPENCL-SAME: %{{[a-zA-Z_][a-zA-Z0-9_]*}}: !llvm.ptr<1> | ||
// OPENCL-SAME: %{{[a-zA-Z_][a-zA-Z0-9_]*}}: !llvm.ptr<1> | ||
gpu.func @no_address_spaces(%arg0: memref<f32>, %arg1: memref<f32, #gpu.address_space<global>>, %arg2: memref<f32>) { | ||
gpu.return | ||
} | ||
} | ||
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 you add additional and more complex tests? 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. I added an example. I had to add func to llvm and finalize memref to llvm into the pass so that the signature and loads/stores are lowered correctly. The function should have a spir_func attribute though. I think it'd be easiest to just go through all of them after func to llvm and attach it to those that don't have it. Kernels will have those set correctly, so we can always assume it's not a kernel. |
Uh oh!
There was an error while loading. Please reload this page.