[flang-commits] [flang] [flang][cuda] Fix device-to-device transfers involving scalar CUDA constants (PR #219577)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Mon Aug 31 09:38:11 PDT 2026
================
@@ -293,33 +293,86 @@ struct CUFDataTransferOpConversion
return declareOp.getMemref().getDefiningOp<fir::AddrOfOp>();
return {};
};
+ // Address of the host shadow when val designates a scalar CUDA constant,
+ // null otherwise.
+ auto getShadowAddrOf = [&](mlir::Value val) -> fir::AddrOfOp {
+ fir::AddrOfOp addrOfOp = getAddrOf(val);
+ if (!addrOfOp)
+ return {};
+ auto global = symtab.lookup<fir::GlobalOp>(
+ addrOfOp.getSymbol().getRootReference().getValue());
+ if (!isScalarCudaConstantGlobal(global))
+ return {};
+ return addrOfOp;
+ };
if (op.getTransferKind() == cuf::DataTransferKind::DeviceHost) {
- if (fir::AddrOfOp addrOfOp = getAddrOf(src)) {
- auto global = symtab.lookup<fir::GlobalOp>(
- addrOfOp.getSymbol().getRootReference().getValue());
- if (isScalarCudaConstantGlobal(global) &&
- fir::isa_ref_type(dst.getType())) {
- mlir::Value hostValue = fir::LoadOp::create(builder, loc, src);
- hostValue = createConvertOp(rewriter, loc, dstTy, hostValue);
- fir::StoreOp::create(builder, loc, hostValue, dst);
- rewriter.eraseOp(op);
- return mlir::success();
- }
+ if (getShadowAddrOf(src) && fir::isa_ref_type(dst.getType())) {
+ mlir::Value hostValue = fir::LoadOp::create(builder, loc, src);
+ hostValue = createConvertOp(rewriter, loc, dstTy, hostValue);
+ fir::StoreOp::create(builder, loc, hostValue, dst);
+ rewriter.eraseOp(op);
+ return mlir::success();
}
}
if (op.getTransferKind() == cuf::DataTransferKind::HostDevice) {
- if (fir::AddrOfOp addrOfOp = getAddrOf(dst)) {
- auto global = symtab.lookup<fir::GlobalOp>(
- addrOfOp.getSymbol().getRootReference().getValue());
- if (isScalarCudaConstantGlobal(global)) {
- mlir::Value hostValue = src;
- if (fir::isa_ref_type(src.getType()))
- hostValue = fir::LoadOp::create(builder, loc, src);
- hostValue = createConvertOp(rewriter, loc, dstTy, hostValue);
- fir::StoreOp::create(builder, loc, hostValue, addrOfOp);
+ // A non-null shadow means the destination is a scalar constant. Keep
+ // its shadow up to date for later host reads, then aim the copy at the
+ // device symbol instead of the shadow.
+ if (fir::AddrOfOp addrOfOp = getShadowAddrOf(dst)) {
+ mlir::Value hostValue = src;
+ if (fir::isa_ref_type(src.getType()))
+ hostValue = fir::LoadOp::create(builder, loc, src);
+ hostValue = createConvertOp(rewriter, loc, dstTy, hostValue);
+ fir::StoreOp::create(builder, loc, hostValue, addrOfOp);
+ dst = cuf::DeviceAddressOp::create(rewriter, loc, dst.getType(),
+ addrOfOp.getSymbol());
+ }
+ }
+ if (op.getTransferKind() == cuf::DataTransferKind::DeviceDevice) {
+ // A scalar CUDA constant is designated by its host shadow, which lives
+ // in host memory and cannot take part in a device to device copy. Route
+ // the transfer through the shadow instead. There are three cases,
+ // depending on which side is a scalar constant.
----------------
clementval wrote:
We do have a global on the device side and it is registered. Is this a limitation because constant can only be initialized from the host?
https://github.com/llvm/llvm-project/pull/219577
More information about the flang-commits
mailing list