[flang-commits] [flang] [flang][debug] Keep the bounds of variables in stack slots at -O0. (PR #229876)

via flang-commits flang-commits at lists.llvm.org
Thu Oct 8 09:56:36 PDT 2026


================
@@ -2571,6 +2572,55 @@ isCapturedInInternalProcedure(Fortran::lower::AbstractConverter &converter,
   return false;
 }
 
+/// Whether \p val is the same wherever it is read, so that the debug info can
+/// describe it directly and it does not need a slot.
+static bool isInvariantBound(mlir::Value val) {
+  mlir::Operation *op = val.getDefiningOp();
+  // A block argument, which for a bound means a dummy, varies between calls.
+  if (!op)
+    return false;
+  if (op->hasTrait<mlir::OpTrait::ConstantLike>())
+    return true;
+  // The assumed-size sentinel is fixed at compile time, and the debug info
+  // leaves it out rather than describing it as an extent.
+  if (mlir::isa<fir::AssumedSizeExtentOp>(op))
+    return true;
+  // A constant bound is usually folded before lowering, but a dimension of an
+  // array that has a non-constant dimension too still reaches here so look
+  // through the computation.
+  return !op->getOperands().empty() && mlir::isPure(op) &&
+         op->getNumRegions() == 0 &&
+         llvm::all_of(op->getOperands(), isInvariantBound);
+}
+
+/// Under the BoundsInStackSlots lowering option, store the non-constant bounds
+/// and length parameters of the variable declared by \p declare in stack slots
+/// that nothing else accesses.
+static void genBoundsInStackSlots(Fortran::lower::AbstractConverter &converter,
+                                  hlfir::DeclareOp declare) {
+  if (!converter.getLoweringOptions().getBoundsInStackSlots())
+    return;
+  llvm::SmallVector<mlir::Value> bounds(declare.getTypeparams());
+  if (mlir::Value shape = declare.getShape())
+    if (mlir::Operation *shapeOp = shape.getDefiningOp())
+      llvm::append_range(bounds, shapeOp->getOperands());
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  mlir::NamedAttribute slotAttr(
+      builder.getStringAttr(fir::getDebugBoundSlotAttrName()),
+      builder.getUnitAttr());
+  // Neither the slot nor the store is something the user wrote, so keep them
+  // out of the line table.
+  mlir::Location loc = builder.getUnknownLoc();
+  mlir::OpBuilder::InsertionGuard guard(builder);
+  builder.setInsertionPoint(declare);
+  for (mlir::Value bound : bounds) {
+    if (isInvariantBound(bound))
+      continue;
+    mlir::Value slot = builder.createTemporary(loc, bound.getType(), slotAttr);
----------------
jiel-nv wrote:

E.g. `a(n, n)` seems to end up with two slots while only one is referenced. Is it worth de-duplicating `bounds`?

https://github.com/llvm/llvm-project/pull/229876


More information about the flang-commits mailing list