From 569ad27f5ec86d5ef392ebb5f3b4a0dcaabf78b4 Mon Sep 17 00:00:00 2001 From: ergawy Date: Wed, 2 Jul 2025 02:49:45 -0500 Subject: [PATCH 1/2] [flang] Emit `fir.global` in the global address space Instead of emitting globals in the program/default address space, emit them in the global address space. This also requires changes how address of code-gen is handled, we need to cast to the default address space to prevent code-gen issues. --- .../flang/Optimizer/Builder/FIRBuilder.h | 4 ++ .../flang/Optimizer/CodeGen/FIROpPatterns.h | 3 + flang/lib/Optimizer/Builder/FIRBuilder.cpp | 14 +++++ flang/lib/Optimizer/CodeGen/CodeGen.cpp | 61 ++++++++++++++++--- flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp | 15 +++++ ...u-target-desc-cast-to-global-addrspace.f90 | 18 ++++++ 6 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 flang/test/Integration/amdgpu-target-desc-cast-to-global-addrspace.f90 diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index e1eaab3346901..f2c363e09e9e6 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -900,6 +900,10 @@ uint64_t getAllocaAddressSpace(const mlir::DataLayout *dataLayout); llvm::SmallVector deduceOptimalExtents(mlir::ValueRange extents1, mlir::ValueRange extents2); +uint64_t getGlobalAddressSpace(mlir::DataLayout *dataLayout); + +uint64_t getProgramAddressSpace(mlir::DataLayout *dataLayout); + /// Given array extents generate code that sets them all to zeroes, /// if the array is empty, e.g.: /// %false = arith.constant false diff --git a/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h b/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h index 7b1c14e4dfdc9..cbdcf6b501b8e 100644 --- a/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h +++ b/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h @@ -189,6 +189,9 @@ class ConvertFIRToLLVMPattern : public mlir::ConvertToLLVMPattern { unsigned getProgramAddressSpace(mlir::ConversionPatternRewriter &rewriter) const; + unsigned + getGlobalAddressSpace(mlir::ConversionPatternRewriter &rewriter) const; + const fir::FIRToLLVMPassOptions &options; using ConvertToLLVMPattern::matchAndRewrite; diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 6ac87067f6511..b5cabdb830e5c 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -1867,6 +1867,20 @@ fir::factory::deduceOptimalExtents(mlir::ValueRange extents1, return extents; } +uint64_t fir::factory::getGlobalAddressSpace(mlir::DataLayout *dataLayout) { + if (dataLayout) + if (mlir::Attribute addrSpace = dataLayout->getGlobalMemorySpace()) + return mlir::cast(addrSpace).getUInt(); + return 0; +} + +uint64_t fir::factory::getProgramAddressSpace(mlir::DataLayout *dataLayout) { + if (dataLayout) + if (mlir::Attribute addrSpace = dataLayout->getProgramMemorySpace()) + return mlir::cast(addrSpace).getUInt(); + return 0; +} + llvm::SmallVector fir::factory::updateRuntimeExtentsForEmptyArrays( fir::FirOpBuilder &builder, mlir::Location loc, mlir::ValueRange extents) { if (extents.size() <= 1) diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 2b018912b40e4..09038f6e4d3ae 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -137,6 +137,38 @@ addLLVMOpBundleAttrs(mlir::ConversionPatternRewriter &rewriter, } namespace { + +mlir::Value replaceWithAddrOfOrASCast(mlir::ConversionPatternRewriter &rewriter, + mlir::Location loc, + std::uint64_t globalAS, + std::uint64_t programAS, + llvm::StringRef symName, mlir::Type type, + mlir::Operation *replaceOp = nullptr) { + if (mlir::isa(type)) { + if (globalAS != programAS) { + auto llvmAddrOp = rewriter.create( + loc, getLlvmPtrType(rewriter.getContext(), globalAS), symName); + if (replaceOp) + return rewriter.replaceOpWithNewOp( + replaceOp, ::getLlvmPtrType(rewriter.getContext(), programAS), + llvmAddrOp); + return rewriter.create( + loc, getLlvmPtrType(rewriter.getContext(), programAS), llvmAddrOp); + } + + if (replaceOp) + return rewriter.replaceOpWithNewOp( + replaceOp, getLlvmPtrType(rewriter.getContext(), globalAS), symName); + return rewriter.create( + loc, getLlvmPtrType(rewriter.getContext(), globalAS), symName); + } + + if (replaceOp) + return rewriter.replaceOpWithNewOp(replaceOp, type, + symName); + return rewriter.create(loc, type, symName); +} + /// Lower `fir.address_of` operation to `llvm.address_of` operation. struct AddrOfOpConversion : public fir::FIROpConversion { using FIROpConversion::FIROpConversion; @@ -144,9 +176,15 @@ struct AddrOfOpConversion : public fir::FIROpConversion { llvm::LogicalResult matchAndRewrite(fir::AddrOfOp addr, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto ty = convertType(addr.getType()); - rewriter.replaceOpWithNewOp( - addr, ty, addr.getSymbol().getRootReference().getValue()); + auto global = addr->getParentOfType() + .lookupSymbol(addr.getSymbol()); + replaceWithAddrOfOrASCast( + rewriter, addr->getLoc(), + global ? global.getAddrSpace() : getGlobalAddressSpace(rewriter), + getProgramAddressSpace(rewriter), + global ? global.getSymName() + : addr.getSymbol().getRootReference().getValue(), + convertType(addr.getType()), addr); return mlir::success(); } }; @@ -1306,13 +1344,18 @@ getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter, ? fir::NameUniquer::getTypeDescriptorAssemblyName(recType.getName()) : fir::NameUniquer::getTypeDescriptorName(recType.getName()); mlir::Type llvmPtrTy = ::getLlvmPtrType(mod.getContext()); + mlir::DataLayout dataLayout(mod); if (auto global = mod.template lookupSymbol(name)) - return rewriter.create(loc, llvmPtrTy, - global.getSymName()); + return replaceWithAddrOfOrASCast( + rewriter, loc, fir::factory::getGlobalAddressSpace(&dataLayout), + fir::factory::getProgramAddressSpace(&dataLayout), global.getSymName(), + llvmPtrTy); // The global may have already been translated to LLVM. if (auto global = mod.template lookupSymbol(name)) - return rewriter.create(loc, llvmPtrTy, - global.getSymName()); + return replaceWithAddrOfOrASCast( + rewriter, loc, global.getAddrSpace(), + fir::factory::getProgramAddressSpace(&dataLayout), global.getSymName(), + llvmPtrTy); // Type info derived types do not have type descriptors since they are the // types defining type descriptors. if (options.ignoreMissingTypeDescriptors || @@ -3130,8 +3173,8 @@ struct GlobalOpConversion : public fir::FIROpConversion { mlir::SymbolRefAttr comdat; llvm::ArrayRef attrs; auto g = rewriter.create( - loc, tyAttr, isConst, linkage, global.getSymName(), initAttr, 0, 0, - false, false, comdat, attrs, dbgExprs); + loc, tyAttr, isConst, linkage, global.getSymName(), initAttr, 0, + getGlobalAddressSpace(rewriter), false, false, comdat, attrs, dbgExprs); if (global.getAlignment() && *global.getAlignment() > 0) g.setAlignment(*global.getAlignment()); diff --git a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp index 12021deb4bd97..5c9c9c34caac1 100644 --- a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp +++ b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp @@ -365,4 +365,19 @@ unsigned ConvertFIRToLLVMPattern::getProgramAddressSpace( return defaultAddressSpace; } +unsigned ConvertFIRToLLVMPattern::getGlobalAddressSpace( + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); + assert(parentOp != nullptr && + "expected insertion block to have parent operation"); + auto module = mlir::isa(parentOp) + ? mlir::cast(parentOp) + : parentOp->getParentOfType(); + if (module) + if (mlir::Attribute addrSpace = + mlir::DataLayout(module).getGlobalMemorySpace()) + return llvm::cast(addrSpace).getUInt(); + return defaultAddressSpace; +} + } // namespace fir diff --git a/flang/test/Integration/amdgpu-target-desc-cast-to-global-addrspace.f90 b/flang/test/Integration/amdgpu-target-desc-cast-to-global-addrspace.f90 new file mode 100644 index 0000000000000..249d403057b6c --- /dev/null +++ b/flang/test/Integration/amdgpu-target-desc-cast-to-global-addrspace.f90 @@ -0,0 +1,18 @@ +!REQUIRES: amdgpu-registered-target + +!RUN: %flang_fc1 -emit-llvm -triple amdgcn-amd-amdhsa -target-cpu gfx908 %s -o - | FileCheck %s + +subroutine maintest + implicit none + + type r1_t + end type r1_t + + type(r1_t), pointer :: A +end subroutine + +! CHECK: @[[TYPE_DESC:.*XdtXr1_t]] = linkonce_odr addrspace(1) constant %_QM__fortran_type_infoTderivedtype + +! CHECK: define void @maintest_() {{.*}} { +! CHECK: store { {{.*}} } { {{.*}}, ptr addrspacecast (ptr addrspace(1) @[[TYPE_DESC]] to ptr), {{.*}} }, {{.*}} +! CHECK: } From d451d6640d955ae8a519976064a45af1330f44b5 Mon Sep 17 00:00:00 2001 From: ergawy Date: Wed, 2 Jul 2025 04:04:14 -0500 Subject: [PATCH 2/2] simplify util --- flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp index 5c9c9c34caac1..75a54fd0ee14f 100644 --- a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp +++ b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/CodeGen/FIROpPatterns.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "llvm/Support/Debug.h" @@ -370,14 +371,8 @@ unsigned ConvertFIRToLLVMPattern::getGlobalAddressSpace( mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); assert(parentOp != nullptr && "expected insertion block to have parent operation"); - auto module = mlir::isa(parentOp) - ? mlir::cast(parentOp) - : parentOp->getParentOfType(); - if (module) - if (mlir::Attribute addrSpace = - mlir::DataLayout(module).getGlobalMemorySpace()) - return llvm::cast(addrSpace).getUInt(); - return defaultAddressSpace; + auto dataLayout = mlir::DataLayout::closest(parentOp); + return fir::factory::getGlobalAddressSpace(&dataLayout); } } // namespace fir