11#include " comet/Conversion/PrepareGpuHost/PrepareGpuHostPass.h"
2+ #include " mlir/Dialect/Func/IR/FuncOps.h"
3+ #include " mlir/IR/Attributes.h"
4+ #include " mlir/IR/Builders.h"
5+ #include " mlir/IR/BuiltinAttributes.h"
6+ #include " mlir/IR/Operation.h"
27#include " mlir/Pass/Pass.h"
38#include " mlir/Dialect/GPU/IR/GPUDialect.h"
49#include " mlir/Dialect/LLVMIR/LLVMDialect.h"
@@ -26,24 +31,28 @@ class PrepareGpuHost
2631
2732 std::map<std::string, Value> funcs;
2833 std::map<std::string, std::string> gpu_to_triton_kernel;
34+ std::map<std::string, func::FuncOp> gpu_name_to_funcOp;
2935 std::map<std::string, triton::FuncOp> triton_name_to_triton_func_op;
3036 auto gpuModules = modOp.getOps <gpu::GPUModuleOp>();
3137 for (auto gpuModuleOp: gpuModules)
3238 {
3339 auto funcOps = gpuModuleOp.getOps <mlir::func::FuncOp>();
3440 for (func::FuncOp funcOp: llvm::make_early_inc_range (funcOps))
3541 {
42+ std::map<size_t , std::vector<Attribute>> argsToSet;
3643 if (!funcOp->hasAttr (gpu::GPUDialect::getKernelFuncAttrName ()))
3744 {
3845 continue ;
3946 }
4047 builder.setInsertionPoint (funcOp);
4148 SmallVector<Type, 4 > newTypes;
42- for (auto argType : funcOp.getArgumentTypes ())
49+ for (auto arg : funcOp.getArguments ())
4350 {
51+ auto argType = arg.getType ();
4452 newTypes.push_back (argType);
4553 if (MemRefType rankedType = dyn_cast<mlir::MemRefType>(argType))
4654 {
55+ argsToSet[newTypes.size () - 1 ] = {funcOp.getArgAttr (arg.getArgNumber (), " gpu.read" ), funcOp.getArgAttr (arg.getArgNumber (), " gpu.write" )};
4756 if (rankedType.hasRank ())
4857 {
4958 newTypes.push_back (builder.getIndexType ());
@@ -71,6 +80,18 @@ class PrepareGpuHost
7180 builder.create <func::ReturnOp>(funcOp.getLoc ());
7281 newFunc->setAttr (gpu::GPUDialect::getKernelFuncAttrName (),
7382 builder.getUnitAttr ());
83+ for (auto [argNumber, attrs]: argsToSet)
84+ {
85+ if (attrs[0 ])
86+ {
87+ newFunc.setArgAttr (argNumber, " gpu.read" , attrs[0 ]);
88+ }
89+ if (attrs[1 ])
90+ {
91+ newFunc.setArgAttr (argNumber, " gpu.write" , attrs[1 ]);
92+ }
93+ }
94+ gpu_name_to_funcOp[funcOp.getName ().str ()] = newFunc;
7495 funcOp->erase ();
7596 }
7697 }
@@ -185,14 +206,24 @@ class PrepareGpuHost
185206 if (mlir::gpu::LaunchFuncOp launchOp =
186207 dyn_cast<mlir::gpu::LaunchFuncOp>(use.getOwner ())) {
187208 builder.setInsertionPoint (launchOp);
188- builder.create <mlir::gpu::MemcpyOp>(launchOp->getLoc (), TypeRange (),
189- ValueRange (),
190- gpuAlloc.getMemref (), alloc);
209+ int offset = launchOp->getNumOperands () - launchOp.getNumKernelOperands ();
210+ int operNum = use.getOperandNumber () - offset;
211+ if (gpu_name_to_funcOp[launchOp.getKernelName ().str ()].getArgAttr (operNum, " gpu.read" ))
212+ {
213+ auto gpuMemCpy = builder.create <mlir::gpu::MemcpyOp>(launchOp->getLoc (), TypeRange (),
214+ ValueRange (),
215+ gpuAlloc.getMemref (), alloc);
216+ gpuMemCpy->setAttr (" gpu.read" , builder.getUnitAttr ());
217+ }
191218 use.set (gpuAlloc.getMemref ());
192219 builder.setInsertionPointAfter (launchOp);
193- builder.create <mlir::gpu::MemcpyOp>(launchOp->getLoc (), TypeRange (),
194- ValueRange (), alloc,
195- gpuAlloc.getMemref ());
220+ if (gpu_name_to_funcOp[launchOp.getKernelName ().str ()].getArgAttr (operNum, " gpu.write" ))
221+ {
222+ auto gpuMemCpy = builder.create <mlir::gpu::MemcpyOp>(launchOp->getLoc (), TypeRange (),
223+ ValueRange (), alloc,
224+ gpuAlloc.getMemref ());
225+ gpuMemCpy->setAttr (" gpu.write" , builder.getUnitAttr ());
226+ }
196227 }
197228 }
198229 }
@@ -214,11 +245,82 @@ class PrepareGpuHost
214245 gpuAllocs.push_back (gpuAllocOp);
215246 });
216247
217- std::vector<mlir::gpu::MemcpyOp> gpuCopies;
218- modOp->walk ([&gpuCopies](mlir::gpu::MemcpyOp gpuCopy) {
219- gpuCopies.push_back (gpuCopy);
248+
249+ std::map<void *, std::vector<Operation*>> memEffects;
250+ modOp->walk ([&uniqueGpuAllocs, &memEffects](Operation* memEffect) {
251+ for (auto op: memEffect->getOperands ())
252+ {
253+ if (uniqueGpuAllocs.find (op) != uniqueGpuAllocs.end ())
254+ {
255+ memEffects[op.getAsOpaquePointer ()].push_back (memEffect);
256+ }
257+ }
220258 });
221259
260+ for (auto & [memref, effects]: memEffects)
261+ {
262+ bool copyIn = true ;
263+ std::vector<Operation*> copyDelete;
264+ for (size_t i = 0 ; i < effects.size (); i++)
265+ {
266+ if (mlir::gpu::MemcpyOp gpuCopy = mlir::dyn_cast<mlir::gpu::MemcpyOp>(effects[i]))
267+ {
268+ if (!copyIn & gpuCopy->hasAttr (" gpu.read" ))
269+ {
270+ gpuCopy->erase ();
271+ }
272+ else if (gpuCopy->hasAttr (" gpu.read" ))
273+ {
274+ copyIn = false ;
275+ }
276+ else if (gpuCopy->hasAttr (" gpu.write" ))
277+ {
278+ copyIn = false ;
279+ copyDelete.push_back (gpuCopy);
280+ }
281+ }
282+ else if (mlir::memref::StoreOp store = mlir::dyn_cast<mlir::memref::StoreOp>(effects[i]))
283+ {
284+ copyIn = true ;
285+ if (!copyDelete.empty ())
286+ {
287+ copyDelete.pop_back ();
288+ }
289+ }
290+ else if (mlir::memref::CopyOp copy = mlir::dyn_cast<mlir::memref::CopyOp>(effects[i]))
291+ {
292+ if (copy.getTarget ().getAsOpaquePointer () == memref)
293+ {
294+ copyIn = true ;
295+ }
296+ }
297+ else if (mlir::memref::LoadOp load = mlir::dyn_cast<mlir::memref::LoadOp>(effects[i]))
298+ {
299+ if (!copyDelete.empty ())
300+ {
301+ copyDelete.pop_back ();
302+ }
303+ }
304+ else if (isa<memref::ExtractStridedMetadataOp, memref::DimOp, memref::RankOp>(effects[i]))
305+ {
306+ continue ;
307+ }
308+ else // Unknown operation, be conservative
309+ {
310+ copyIn = true ;
311+ if (!copyDelete.empty ())
312+ {
313+ copyDelete.pop_back ();
314+ }
315+ }
316+ }
317+
318+ for (auto toDelete: copyDelete)
319+ {
320+ toDelete->erase ();
321+ }
322+ }
323+
222324 }
223325};
224326
0 commit comments