[flang-commits] [flang] [flang][cuda] Size managed globals with descriptor components via LLVM Type (PR #209577)

Vijay Kandiah via flang-commits flang-commits at lists.llvm.org
Tue Jul 14 10:53:30 PDT 2026


https://github.com/VijayKandiah created https://github.com/llvm/llvm-project/pull/209577

When we do `-cuda -gpu=unified` (or `managed`) on a derived type with an
allocatable/pointer component, recent change https://github.com/llvm/llvm-project/pull/209292 implicitly
attributed the component making lowering place the enclosing derived-type global
in CUF managed memory. `CUFAddConstructor` then sizes that global via
`getTypeSizeAndAlignmentOrCrash`, which has no case for the descriptor component
(`!fir.box<...>`) and aborts.

With this change, instead of aborting, we fall back to converting the global to its LLVM type which
inlines the fixed-size descriptors, and query the data layout, in a similar fashion to what
`CUFAllocationConversion` already does.

>From 526c9262e905bdbbbd2385c066caa66be4d03ef9 Mon Sep 17 00:00:00 2001
From: Vijay Kandiah <vkandiah at nvidia.com>
Date: Tue, 14 Jul 2026 10:44:10 -0700
Subject: [PATCH] [flang][cuda] Size managed globals with descriptor components
 via LLVM type

---
 .../Transforms/CUDA/CUFAddConstructor.cpp     | 24 +++++++++++++++++++
 .../cuda-managed-descriptor-component.fir     | 17 +++++++++++++
 2 files changed, 41 insertions(+)
 create mode 100644 flang/test/Fir/CUDA/cuda-managed-descriptor-component.fir

diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp
index 97f1c0c8762e8..3d60ab09daa0d 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp
@@ -116,6 +116,18 @@ static mlir::Value computeGlobalSize(fir::FirOpBuilder &builder,
     mlir::Type structTy = typeConverter.convertBoxTypeAsStruct(boxTy);
     size = dl.getTypeSizeInBits(structTy) / 8;
   }
+  if (!size) {
+    if (auto s = fir::getTypeSizeAndAlignment(loc, globalOp.getType(), dl,
+                                              kindMap))
+      size = s->first;
+  }
+  if (!size) {
+    // A global embedding descriptor (allocatable/pointer) components has no
+    // structural size; size it via its LLVM type, which inlines the descriptors.
+    mlir::Type llvmTy = typeConverter.convertType(globalOp.getType());
+    if (llvmTy && mlir::isa<mlir::DataLayoutTypeInterface>(llvmTy))
+      size = dl.getTypeSizeInBits(llvmTy) / 8;
+  }
   if (!size) {
     size = fir::getTypeSizeAndAlignmentOrCrash(loc, globalOp.getType(), dl,
                                                kindMap)
@@ -136,6 +148,18 @@ static uint64_t getGlobalSizeInBytes(mlir::Location loc,
     mlir::Type structTy = typeConverter.convertBoxTypeAsStruct(boxTy);
     size = dl.getTypeSizeInBits(structTy) / 8;
   }
+  if (!size) {
+    if (auto s = fir::getTypeSizeAndAlignment(loc, globalOp.getType(), dl,
+                                              kindMap))
+      size = s->first;
+  }
+  if (!size) {
+    // A global embedding descriptor (allocatable/pointer) components has no
+    // structural size; size it via its LLVM type, which inlines the descriptors.
+    mlir::Type llvmTy = typeConverter.convertType(globalOp.getType());
+    if (llvmTy && mlir::isa<mlir::DataLayoutTypeInterface>(llvmTy))
+      size = dl.getTypeSizeInBits(llvmTy) / 8;
+  }
   if (!size) {
     size = fir::getTypeSizeAndAlignmentOrCrash(loc, globalOp.getType(), dl,
                                                kindMap)
diff --git a/flang/test/Fir/CUDA/cuda-managed-descriptor-component.fir b/flang/test/Fir/CUDA/cuda-managed-descriptor-component.fir
new file mode 100644
index 0000000000000..46613be9bed5b
--- /dev/null
+++ b/flang/test/Fir/CUDA/cuda-managed-descriptor-component.fir
@@ -0,0 +1,17 @@
+// RUN: fir-opt --cuf-add-constructor %s | FileCheck %s
+
+// CUFAddConstructor must size a managed global of a derived type with a
+// descriptor (allocatable/pointer) component instead of aborting.
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<270>, dense<32> : vector<4xi64>>, #dlti.dl_entry<f128, dense<128> : vector<2xi64>>, #dlti.dl_entry<f64, dense<64> : vector<2xi64>>, #dlti.dl_entry<f80, dense<128> : vector<2xi64>>, #dlti.dl_entry<f16, dense<16> : vector<2xi64>>, #dlti.dl_entry<i32, dense<32> : vector<2xi64>>, #dlti.dl_entry<i16, dense<16> : vector<2xi64>>, #dlti.dl_entry<i128, dense<128> : vector<2xi64>>, #dlti.dl_entry<i8, dense<8> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi64>>, #dlti.dl_entry<i64, dense<64> : vector<2xi64>>, #dlti.dl_entry<i1, dense<8> : vector<2xi64>>, #dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", gpu.container_module, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu"} {
+  fir.global @_QMmEobj {data_attr = #cuf.cuda<managed>} : !fir.array<10x!fir.type<_QMmTt{nodl:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+
+  gpu.module @cuda_device_mod {
+    fir.global @_QMmEobj {data_attr = #cuf.cuda<managed>} : !fir.array<10x!fir.type<_QMmTt{nodl:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+  }
+}
+
+// CHECK-LABEL: llvm.func internal @__cudaFortranConstructor()
+// CHECK: %[[SIZE:.*]] = arith.constant 480 : index
+// CHECK: %[[SIZE_I64:.*]] = fir.convert %[[SIZE]] : (index) -> i64
+// CHECK: fir.call @_FortranACUFRegisterManagedVariable(%{{.*}}, %{{.*}}, %{{.*}}, %[[SIZE_I64]])



More information about the flang-commits mailing list