[flang-commits] [flang] [flang] add AllocationPolicy attribute to module and use it in InlineHLFIRCopy (PR #222013)

via flang-commits flang-commits at lists.llvm.org
Wed Sep 9 05:30:57 PDT 2026


================
@@ -38,23 +45,81 @@ static llvm::cl::opt<bool> noInlineHLFIRCopy(
     llvm::cl::init(false));
 
 namespace {
+/// Everything needed to compute the constant byte size of a buffer, gathered
+/// once by the pass since it is module-level information.
+struct SizeContext {
+  std::optional<mlir::DataLayout> dataLayout;
+  std::optional<fir::KindMapping> kindMap;
+};
+
+/// Gather the module level information needed to compute buffer sizes. Without
+/// a data layout no size can be computed, and all the buffers are then left on
+/// the heap.
+static SizeContext getSizeContext(mlir::Operation *op) {
+  auto module = mlir::dyn_cast<mlir::ModuleOp>(op);
+  if (!module)
+    module = op->getParentOfType<mlir::ModuleOp>();
+  if (!module)
+    return SizeContext{std::nullopt, std::nullopt};
+  return SizeContext{fir::support::getOrSetMLIRDataLayout(
+                         module, /*allowDefaultLayout=*/false),
+                     fir::getKindMapping(module)};
+}
+
 class InlineCopyInConversion : public mlir::OpRewritePattern<hlfir::CopyInOp> {
 public:
-  using mlir::OpRewritePattern<hlfir::CopyInOp>::OpRewritePattern;
+  InlineCopyInConversion(mlir::MLIRContext *context,
+                         const fir::AllocationPolicy &policy,
+                         const SizeContext &sizeContext)
+      : mlir::OpRewritePattern<hlfir::CopyInOp>(context), policy(policy),
+        sizeContext(sizeContext) {}
 
   llvm::LogicalResult
   matchAndRewrite(hlfir::CopyInOp copyIn,
                   mlir::PatternRewriter &rewriter) const override;
+
+private:
+  /// Return true if the copy-in buffer of type \p sequenceType should be
+  /// allocated on the stack rather than on the heap.
+  bool shouldUseStack(mlir::Location loc, mlir::Type sequenceType) const;
+
+  fir::AllocationPolicy policy;
+  const SizeContext &sizeContext;
 };
 
+bool InlineCopyInConversion::shouldUseStack(mlir::Location loc,
+                                            mlir::Type sequenceType) const {
+  // Only buffers with a compile-time constant size are considered. A buffer
+  // with a runtime size would need stack save/restore to avoid growing the
+  // stack when the copy-in is inside a loop. There is also little to gain: for
+  // a big buffer the element-per-element copy costs much more than the
+  // allocation itself.
+  if (fir::hasDynamicSize(sequenceType))
+    return false;
+  if (!sizeContext.dataLayout || !sizeContext.kindMap)
+    return false;
+  auto sizeAndAlignment = fir::getTypeSizeAndAlignment(
+      loc, sequenceType, *sizeContext.dataLayout, *sizeContext.kindMap);
+  if (!sizeAndAlignment)
+    return false;
+
+  fir::PendingAllocationInfo info;
+  info.isTemporary = true;
+  info.isDynamic = false;
+  info.byteSize = static_cast<std::int64_t>(sizeAndAlignment->first);
+  // The per-function stack budget is not tracked here: the
+  // allocation-placement pass sees the fir.alloca generated below and can
+  // still move it back to the heap if the budget turns out to be exceeded.
+  return fir::shouldAllocateOnStack(info, policy, /*stackBytesUsed=*/0);
----------------
jeanPerier wrote:

It is also used in   `bool wantStack = fir::shouldAllocateOnStack(info, policy, stackBytesUsed);`  [here in fir::decideAllocationPlacement](https://github.com/jeanPerier/llvm-project/blob/780461d8f609834cd5cf6e4c02622c07c0b47f96/flang/lib/Optimizer/Support/AllocationPolicy.cpp#L80) in AllocationPolicy.cpp.

fir::decideAllocationPlacement is used in the AllocationPlacement pass with an actual threshold (for now quite high at 4Gb).

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


More information about the flang-commits mailing list