[flang-commits] [flang] [flang][hlfir] Extend InlineHLFIRCopy to inline copy_out with copy-back (PR #179096)
via flang-commits
flang-commits at lists.llvm.org
Sun Feb 1 02:21:38 PST 2026
https://github.com/khaki3 created https://github.com/llvm/llvm-project/pull/179096
Rename `InlineHLFIRCopyIn` to `InlineHLFIRCopy` and extend it to inline the paired `hlfir.copy_out` operation. This handles both:
- Deallocation-only cases (`intent(in)`): generates `fir.freemem`
- Copy-back cases (`intent(out/inout`)): generates copy loop then `fir.freemem`
The `copy_out` is inlined at its original location, after the subroutine call, ensuring proper ordering of copy-back and deallocation.
>From 5a34808d83fd9a48be35f60c995d8df5df1efc3d Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Sat, 31 Jan 2026 16:17:56 -0800
Subject: [PATCH] [flang][hlfir] Extend InlineHLFIRCopy to inline copy_out with
copy-back
Rename InlineHLFIRCopyIn to InlineHLFIRCopy and extend it to inline
the paired hlfir.copy_out operation. This handles both:
- Deallocation-only cases (intent(in)): generates fir.freemem
- Copy-back cases (intent(out/inout)): generates copy loop then fir.freemem
The copy_out is inlined at its original location, after the subroutine
call, ensuring proper ordering of copy-back and deallocation.
---
flang/include/flang/Optimizer/HLFIR/Passes.td | 4 +-
.../Optimizer/HLFIR/Transforms/CMakeLists.txt | 2 +-
...ineHLFIRCopyIn.cpp => InlineHLFIRCopy.cpp} | 118 ++++++++++++++----
flang/lib/Optimizer/Passes/Pipelines.cpp | 2 +-
...lfir-copy-in.fir => inline-hlfir-copy.fir} | 93 +++++++++-----
5 files changed, 159 insertions(+), 60 deletions(-)
rename flang/lib/Optimizer/HLFIR/Transforms/{InlineHLFIRCopyIn.cpp => InlineHLFIRCopy.cpp} (59%)
rename flang/test/HLFIR/{inline-hlfir-copy-in.fir => inline-hlfir-copy.fir} (69%)
diff --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td
index bfff458f7a6c5..88b89de956366 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.td
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.td
@@ -73,8 +73,8 @@ def InlineHLFIRAssign : Pass<"inline-hlfir-assign"> {
let summary = "Inline hlfir.assign operations";
}
-def InlineHLFIRCopyIn : Pass<"inline-hlfir-copy-in"> {
- let summary = "Inline hlfir.copy_in operations";
+def InlineHLFIRCopy : Pass<"inline-hlfir-copy"> {
+ let summary = "Inline hlfir.copy_in and hlfir.copy_out operations";
}
def PropagateFortranVariableAttributes : Pass<"propagate-fortran-attrs"> {
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
index 5c24fe58b05c4..2005eb9770d30 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
@@ -6,7 +6,7 @@ add_flang_library(HLFIRTransforms
ExpressionSimplification.cpp
InlineElementals.cpp
InlineHLFIRAssign.cpp
- InlineHLFIRCopyIn.cpp
+ InlineHLFIRCopy.cpp
LowerHLFIRIntrinsics.cpp
LowerHLFIROrderedAssignments.cpp
ScheduleOrderedAssignments.cpp
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRCopyIn.cpp b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRCopy.cpp
similarity index 59%
rename from flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRCopyIn.cpp
rename to flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRCopy.cpp
index b4e89b0966e9c..ab3944fcdbaea 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRCopyIn.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRCopy.cpp
@@ -1,14 +1,18 @@
-//===- InlineHLFIRCopyIn.cpp - Inline hlfir.copy_in ops -------------------===//
+//===- InlineHLFIRCopy.cpp - Inline hlfir.copy_in/copy_out ops ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
-// Transform hlfir.copy_in array operations into loop nests performing element
-// per element assignments. For simplicity, the inlining is done for trivial
-// data types when the copy_in does not require a corresponding copy_out and
-// when the input array is not behind a pointer. This may change in the future.
+// Transform hlfir.copy_in and hlfir.copy_out array operations into loop nests
+// performing element per element assignments. For simplicity, the inlining is
+// done for trivial data types when the input array is not behind a pointer.
+// This may change in the future.
+//
+// When the copy_in is inlined, the corresponding copy_out is also inlined:
+// - For deallocation-only (intent(in)): just fir.freemem
+// - For copy-back (intent(out/inout)): copy loop from temp to dest, then free
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Builder/FIRBuilder.h"
@@ -21,15 +25,15 @@
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
namespace hlfir {
-#define GEN_PASS_DEF_INLINEHLFIRCOPYIN
+#define GEN_PASS_DEF_INLINEHLFIRCOPY
#include "flang/Optimizer/HLFIR/Passes.h.inc"
} // namespace hlfir
-#define DEBUG_TYPE "inline-hlfir-copy-in"
+#define DEBUG_TYPE "inline-hlfir-copy"
-static llvm::cl::opt<bool> noInlineHLFIRCopyIn(
- "no-inline-hlfir-copy-in",
- llvm::cl::desc("Do not inline hlfir.copy_in operations"),
+static llvm::cl::opt<bool> noInlineHLFIRCopy(
+ "no-inline-hlfir-copy",
+ llvm::cl::desc("Do not inline hlfir.copy_in/copy_out operations"),
llvm::cl::init(false));
namespace {
@@ -42,6 +46,52 @@ class InlineCopyInConversion : public mlir::OpRewritePattern<hlfir::CopyInOp> {
mlir::PatternRewriter &rewriter) const override;
};
+// Helper function to inline a copy_out operation.
+// If copyBackDest is provided, generates copy-back loop then freemem.
+// Otherwise, just generates freemem (deallocation-only).
+// Generates: if (wasCopied) { [copy_back_loop;] freemem(...) }
+static void inlineCopyOut(fir::FirOpBuilder &builder, mlir::Location loc,
+ mlir::Value tempBox, mlir::Value wasCopied,
+ mlir::Value copyBackDest, mlir::Value shape,
+ mlir::Type sequenceType) {
+ builder.genIfOp(loc, {}, wasCopied, /*withElseRegion=*/false)
+ .genThen([&]() {
+ mlir::Value box = fir::LoadOp::create(builder, loc, tempBox);
+
+ // If we need to copy back, generate the copy loop
+ if (copyBackDest) {
+ hlfir::Entity temp{box};
+ hlfir::Entity dest{copyBackDest};
+ llvm::SmallVector<mlir::Value> extents =
+ hlfir::getIndexExtents(loc, builder, shape);
+ hlfir::LoopNest loopNest =
+ hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true,
+ /*workshare=*/false, /*couldVectorize=*/false);
+ builder.setInsertionPointToStart(loopNest.body);
+ hlfir::Entity tempElem = hlfir::getElementAt(
+ loc, builder, temp, loopNest.oneBasedIndices);
+ tempElem = hlfir::loadTrivialScalar(loc, builder, tempElem);
+ hlfir::Entity destElem = hlfir::getElementAt(
+ loc, builder, dest, loopNest.oneBasedIndices);
+ hlfir::AssignOp::create(builder, loc, tempElem, destElem);
+ builder.setInsertionPointAfter(loopNest.outerOp);
+ }
+
+ // Free the temporary
+ mlir::Value addr = fir::BoxAddrOp::create(builder, loc, box);
+ auto heapType = fir::HeapType::get(sequenceType);
+ mlir::Value heapAddr =
+ fir::ConvertOp::create(builder, loc, heapType, addr);
+ fir::FreeMemOp::create(builder, loc, heapAddr);
+ });
+}
+
+// Note: We don't have a separate InlineCopyOutConversion pattern.
+// Copy_out inlining is handled by InlineCopyInConversion when it inlines
+// the paired copy_in. For copy_outs that aren't paired with an eligible
+// copy_in (e.g., optional args, assumed-rank, non-trivial types), the
+// copy_out is left as-is and will be lowered to a runtime call.
+
llvm::LogicalResult
InlineCopyInConversion::matchAndRewrite(hlfir::CopyInOp copyIn,
mlir::PatternRewriter &rewriter) const {
@@ -71,16 +121,27 @@ InlineCopyInConversion::matchAndRewrite(hlfir::CopyInOp copyIn,
return rewriter.notifyMatchFailure(copyIn,
"The result array is assumed-rank");
- // Only inline the copy_in when copy_out does not need to be done, i.e. in
- // case of intent(in).
- if (copyOut.getVar())
- return rewriter.notifyMatchFailure(copyIn, "CopyIn needs a copy-out");
+ // Get copy-back destination if needed (null for deallocation-only)
+ mlir::Value copyBackDest;
+ if (mlir::Value destVar = copyOut.getVar()) {
+ hlfir::Entity destEntity{destVar};
+ destEntity =
+ hlfir::derefPointersAndAllocatables(loc, builder, destEntity);
+ copyBackDest = destEntity;
+ }
inputVariable =
hlfir::derefPointersAndAllocatables(loc, builder, inputVariable);
mlir::Type sequenceType =
hlfir::getFortranElementOrSequenceType(inputVariable.getType());
fir::BoxType resultBoxType = fir::BoxType::get(sequenceType);
+
+ // Compute shape before the if-else so it can be used for both copy-in
+ // and copy-out operations.
+ mlir::Value shape = hlfir::genShape(loc, builder, inputVariable);
+ llvm::SmallVector<mlir::Value> extents =
+ hlfir::getIndexExtents(loc, builder, shape);
+
mlir::Value isContiguous =
fir::IsContiguousBoxOp::create(builder, loc, inputVariable);
mlir::Operation::result_range results =
@@ -99,9 +160,6 @@ InlineCopyInConversion::matchAndRewrite(hlfir::CopyInOp copyIn,
mlir::ValueRange{result, builder.createBool(loc, false)});
})
.genElse([&] {
- mlir::Value shape = hlfir::genShape(loc, builder, inputVariable);
- llvm::SmallVector<mlir::Value> extents =
- hlfir::getIndexExtents(loc, builder, shape);
llvm::StringRef tmpName{".tmp.copy_in"};
llvm::SmallVector<mlir::Value> lenParams;
mlir::Value alloc = builder.createHeapTemporary(
@@ -148,20 +206,26 @@ InlineCopyInConversion::matchAndRewrite(hlfir::CopyInOp copyIn,
mlir::OpResult resultBox = results[0];
mlir::OpResult needsCleanup = results[1];
- // Prepare the corresponding copyOut to free the temporary if it is required
+ // Inline the corresponding copyOut (copy-back if needed, then deallocation).
+ // We need to store the resultBox first since it's a box value.
auto alloca = fir::AllocaOp::create(builder, loc, resultBox.getType());
- auto store = fir::StoreOp::create(builder, loc, resultBox, alloca);
- rewriter.startOpModification(copyOut);
- copyOut->setOperand(0, store.getMemref());
- copyOut->setOperand(1, needsCleanup);
- rewriter.finalizeOpModification(copyOut);
+ fir::StoreOp::create(builder, loc, resultBox, alloca);
+
+ // Move to the copyOut location to generate copy-back and deallocation
+ rewriter.setInsertionPoint(copyOut);
+ fir::FirOpBuilder copyOutBuilder(rewriter, copyOut.getOperation());
+ inlineCopyOut(copyOutBuilder, copyOut.getLoc(), alloca, needsCleanup,
+ copyBackDest, shape, sequenceType);
+
+ // Erase the copyOut since we've inlined it
+ rewriter.eraseOp(copyOut);
rewriter.replaceOp(copyIn, {resultBox, builder.genNot(loc, isContiguous)});
return mlir::success();
}
-class InlineHLFIRCopyInPass
- : public hlfir::impl::InlineHLFIRCopyInBase<InlineHLFIRCopyInPass> {
+class InlineHLFIRCopyPass
+ : public hlfir::impl::InlineHLFIRCopyBase<InlineHLFIRCopyPass> {
public:
void runOnOperation() override {
mlir::MLIRContext *context = &getContext();
@@ -172,14 +236,14 @@ class InlineHLFIRCopyInPass
mlir::GreedySimplifyRegionLevel::Disabled);
mlir::RewritePatternSet patterns(context);
- if (!noInlineHLFIRCopyIn) {
+ if (!noInlineHLFIRCopy) {
patterns.insert<InlineCopyInConversion>(context);
}
if (mlir::failed(mlir::applyPatternsGreedily(
getOperation(), std::move(patterns), config))) {
mlir::emitError(getOperation()->getLoc(),
- "failure in hlfir.copy_in inlining");
+ "failure in hlfir.copy_in/copy_out inlining");
signalPassFailure();
}
}
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp
index 6054675643c64..130f129511c45 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -281,7 +281,7 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm,
if (optLevel == llvm::OptimizationLevel::O3) {
addNestedPassToAllTopLevelOperations<PassConstructor>(
- pm, hlfir::createInlineHLFIRCopyIn);
+ pm, hlfir::createInlineHLFIRCopy);
}
}
pm.addPass(hlfir::createLowerHLFIROrderedAssignments());
diff --git a/flang/test/HLFIR/inline-hlfir-copy-in.fir b/flang/test/HLFIR/inline-hlfir-copy.fir
similarity index 69%
rename from flang/test/HLFIR/inline-hlfir-copy-in.fir
rename to flang/test/HLFIR/inline-hlfir-copy.fir
index f1da1da9f9a5c..026f2a91cc499 100644
--- a/flang/test/HLFIR/inline-hlfir-copy-in.fir
+++ b/flang/test/HLFIR/inline-hlfir-copy.fir
@@ -1,5 +1,5 @@
-// Test inlining of hlfir.copy_in
-// RUN: fir-opt --inline-hlfir-copy-in %s | FileCheck %s
+// Test inlining of hlfir.copy_in and hlfir.copy_out
+// RUN: fir-opt --inline-hlfir-copy %s | FileCheck %s
// Test inlining of hlfir.copy_in that does not require the array to be copied out
func.func private @_test_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>> {fir.bindc_name = "x"}, %arg1: !fir.ref<i32> {fir.bindc_name = "i"}, %arg2: !fir.ref<i32> {fir.bindc_name = "j"}) {
@@ -72,16 +72,23 @@ func.func private @_test_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>> {
// CHECK: }
// CHECK: fir.result %[[VAL_25:.*]]#0, %[[VAL_3:.*]] : !fir.box<!fir.array<?xf64>>, i1
// CHECK: }
+// CHECK: %[[VAL_ALLOCA:.*]] = fir.alloca !fir.box<!fir.array<?xf64>>
+// CHECK: fir.store %[[VAL_21:.*]]#0 to %[[VAL_ALLOCA:.*]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
// CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_21:.*]]#0 : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
// CHECK: %[[VAL_23:.*]]:3 = hlfir.associate %[[VAL_5:.*]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
// CHECK: fir.call @_QFPsb(%[[VAL_22:.*]], %[[VAL_23:.*]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>, !fir.ref<i32>) -> ()
-// CHECK: hlfir.copy_out %{{.*}}, %[[VAL_21:.*]]#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> ()
+// CHECK: fir.if %[[VAL_21:.*]]#1 {
+// CHECK: %[[VAL_BOX:.*]] = fir.load %[[VAL_ALLOCA:.*]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
+// CHECK: %[[VAL_ADDR:.*]] = fir.box_addr %[[VAL_BOX:.*]] : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
+// CHECK: %[[VAL_HEAP:.*]] = fir.convert %[[VAL_ADDR:.*]] : (!fir.ref<!fir.array<?xf64>>) -> !fir.heap<!fir.array<?xf64>>
+// CHECK: fir.freemem %[[VAL_HEAP:.*]] : !fir.heap<!fir.array<?xf64>>
+// CHECK: }
// CHECK: hlfir.end_associate %[[VAL_23:.*]]#1, %[[VAL_23:.*]]#2 : !fir.ref<i32>, i1
// CHECK: return
// CHECK: }
-// Test not inlining of hlfir.copy_in that requires the array to be copied out
-func.func private @_test_no_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>> {fir.bindc_name = "x"}, %arg1: !fir.ref<i32> {fir.bindc_name = "i"}, %arg2: !fir.ref<i32> {fir.bindc_name = "j"}) {
+// Test inlining of hlfir.copy_in with copy-back (intent(out/inout))
+func.func private @_test_inline_copy_in_with_copyback(%arg0: !fir.box<!fir.array<?x?x?xf64>> {fir.bindc_name = "x"}, %arg1: !fir.ref<i32> {fir.bindc_name = "i"}, %arg2: !fir.ref<i32> {fir.bindc_name = "j"}) {
%0 = fir.alloca !fir.box<!fir.heap<!fir.array<?xf64>>>
%1 = fir.dummy_scope : !fir.dscope
%2:2 = hlfir.declare %arg1 dummy_scope %1 {uniq_name = "_QFFsb2Ei"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
@@ -113,33 +120,61 @@ func.func private @_test_no_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>
return
}
-// CHECK-LABEL: func.func private @_test_no_inline_copy_in(
+// CHECK-LABEL: func.func private @_test_inline_copy_in_with_copyback(
// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?x?xf64>> {fir.bindc_name = "x"},
// CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "i"},
// CHECK-SAME: %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "j"}) {
-// CHECK: %[[VAL_3:.*]] = arith.constant 100 : i32
-// CHECK: %[[VAL_4:.*]] = arith.constant 0 : index
-// CHECK: %[[VAL_5:.*]] = arith.constant 1 : index
-// CHECK: %[[VAL_6:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf64>>>
-// CHECK: %[[VAL_7:.*]] = fir.dummy_scope : !fir.dscope
-// CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_1:.*]] dummy_scope %[[VAL_7:.*]] {uniq_name = "_QFFsb2Ei"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_2:.*]] dummy_scope %[[VAL_7:.*]] {uniq_name = "_QFFsb2Ej"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
-// CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_0:.*]] dummy_scope %[[VAL_7:.*]] {uniq_name = "_QFFsb2Ex"} : (!fir.box<!fir.array<?x?x?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x?xf64>>, !fir.box<!fir.array<?x?x?xf64>>)
-// CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_8:.*]]#0 : !fir.ref<i32>
-// CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11:.*]] : (i32) -> i64
-// CHECK: %[[VAL_13:.*]]:3 = fir.box_dims %[[VAL_10:.*]]#1, %[[VAL_5:.*]] : (!fir.box<!fir.array<?x?x?xf64>>, index) -> (index, index, index)
-// CHECK: %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_13:.*]]#1, %[[VAL_4:.*]] : index
-// CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_14:.*]], %[[VAL_13:.*]]#1, %[[VAL_4:.*]] : index
-// CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_9:.*]]#0 : !fir.ref<i32>
-// CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16:.*]] : (i32) -> i64
-// CHECK: %[[VAL_18:.*]] = fir.shape %[[VAL_15:.*]] : (index) -> !fir.shape<1>
-// CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_10:.*]]#0 (%[[VAL_12:.*]], %[[VAL_5:.*]]:%[[VAL_13:.*]]#1:%[[VAL_5:.*]], %[[VAL_17:.*]]) shape %[[VAL_18:.*]] : (!fir.box<!fir.array<?x?x?xf64>>, i64, index, index, index, i64, !fir.shape<1>) -> !fir.box<!fir.array<?xf64>>
-// CHECK: %[[VAL_20:.*]]:2 = hlfir.copy_in %[[VAL_19:.*]] to %[[VAL_6:.*]] : (!fir.box<!fir.array<?xf64>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>) -> (!fir.box<!fir.array<?xf64>>, i1)
-// CHECK: %[[VAL_21:.*]] = fir.box_addr %[[VAL_20:.*]]#0 : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
-// CHECK: %[[VAL_22:.*]]:3 = hlfir.associate %[[VAL_3:.*]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
-// CHECK: fir.call @_QFPsb(%[[VAL_21:.*]], %[[VAL_22:.*]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>, !fir.ref<i32>) -> ()
-// CHECK: hlfir.copy_out %[[VAL_6:.*]], %[[VAL_20:.*]]#1 to %[[VAL_19:.*]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xf64>>>>, i1, !fir.box<!fir.array<?xf64>>) -> ()
-// CHECK: hlfir.end_associate %[[VAL_22:.*]]#1, %[[VAL_22:.*]]#2 : !fir.ref<i32>, i1
+// CHECK: %[[VAL_TRUE:.*]] = arith.constant true
+// CHECK: %[[VAL_FALSE:.*]] = arith.constant false
+// CHECK: %[[VAL_100:.*]] = arith.constant 100 : i32
+// CHECK: %[[VAL_C0:.*]] = arith.constant 0 : index
+// CHECK: %[[VAL_C1:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_SCOPE:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[VAL_I:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_SCOPE]] {uniq_name = "_QFFsb2Ei"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+// CHECK: %[[VAL_J:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %[[VAL_SCOPE]] {uniq_name = "_QFFsb2Ej"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+// CHECK: %[[VAL_X:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_SCOPE]] {uniq_name = "_QFFsb2Ex"} : (!fir.box<!fir.array<?x?x?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x?xf64>>, !fir.box<!fir.array<?x?x?xf64>>)
+// CHECK: %[[VAL_ILOAD:.*]] = fir.load %[[VAL_I]]#0 : !fir.ref<i32>
+// CHECK: %[[VAL_ICVT:.*]] = fir.convert %[[VAL_ILOAD]] : (i32) -> i64
+// CHECK: %[[VAL_DIMS:.*]]:3 = fir.box_dims %[[VAL_X]]#1, %[[VAL_C1]] : (!fir.box<!fir.array<?x?x?xf64>>, index) -> (index, index, index)
+// CHECK: %[[VAL_CMP:.*]] = arith.cmpi sgt, %[[VAL_DIMS]]#1, %[[VAL_C0]] : index
+// CHECK: %[[VAL_EXTENT:.*]] = arith.select %[[VAL_CMP]], %[[VAL_DIMS]]#1, %[[VAL_C0]] : index
+// CHECK: %[[VAL_JLOAD:.*]] = fir.load %[[VAL_J]]#0 : !fir.ref<i32>
+// CHECK: %[[VAL_JCVT:.*]] = fir.convert %[[VAL_JLOAD]] : (i32) -> i64
+// CHECK: %[[VAL_SHAPE:.*]] = fir.shape %[[VAL_EXTENT]] : (index) -> !fir.shape<1>
+// CHECK: %[[VAL_DESIGNATE:.*]] = hlfir.designate %[[VAL_X]]#0 (%[[VAL_ICVT]], %[[VAL_C1]]:%[[VAL_DIMS]]#1:%[[VAL_C1]], %[[VAL_JCVT]]) shape %[[VAL_SHAPE]] : (!fir.box<!fir.array<?x?x?xf64>>, i64, index, index, index, i64, !fir.shape<1>) -> !fir.box<!fir.array<?xf64>>
+// CHECK: %[[VAL_ISCONTIG:.*]] = fir.is_contiguous_box %[[VAL_DESIGNATE]] whole : (!fir.box<!fir.array<?xf64>>) -> i1
+// CHECK: %[[VAL_IFRES:.*]]:2 = fir.if %[[VAL_ISCONTIG]] -> (!fir.box<!fir.array<?xf64>>, i1) {
+// CHECK: fir.result %[[VAL_DESIGNATE]], %[[VAL_FALSE]] : !fir.box<!fir.array<?xf64>>, i1
+// CHECK: } else {
+// CHECK: %[[VAL_ALLOC:.*]] = fir.allocmem !fir.array<?xf64>, %[[VAL_EXTENT]] {bindc_name = ".tmp.copy_in", uniq_name = ""}
+// CHECK: %[[VAL_DECL:.*]]:2 = hlfir.declare %[[VAL_ALLOC]](%[[VAL_SHAPE]]) {uniq_name = ".tmp.copy_in"} : (!fir.heap<!fir.array<?xf64>>, !fir.shape<1>) -> (!fir.box<!fir.array<?xf64>>, !fir.heap<!fir.array<?xf64>>)
+// CHECK: fir.do_loop %[[ARG:.*]] = %[[VAL_C1]] to %[[VAL_EXTENT]] step %[[VAL_C1]] unordered {{.*}} {
+// CHECK: %[[VAL_SRC:.*]] = hlfir.designate %[[VAL_DESIGNATE]] (%[[ARG]]) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
+// CHECK: %[[VAL_SRCVAL:.*]] = fir.load %[[VAL_SRC]] : !fir.ref<f64>
+// CHECK: %[[VAL_DST:.*]] = hlfir.designate %[[VAL_DECL]]#0 (%[[ARG]]) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
+// CHECK: hlfir.assign %[[VAL_SRCVAL]] to %[[VAL_DST]] : f64, !fir.ref<f64>
+// CHECK: }
+// CHECK: fir.result %[[VAL_DECL]]#0, %[[VAL_TRUE]] : !fir.box<!fir.array<?xf64>>, i1
+// CHECK: }
+// CHECK: %[[VAL_ALLOCA:.*]] = fir.alloca !fir.box<!fir.array<?xf64>>
+// CHECK: fir.store %[[VAL_IFRES]]#0 to %[[VAL_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
+// CHECK: %[[VAL_BOXADDR:.*]] = fir.box_addr %[[VAL_IFRES]]#0 : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
+// CHECK: %[[VAL_ASSOC:.*]]:3 = hlfir.associate %[[VAL_100]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
+// CHECK: fir.call @_QFPsb(%[[VAL_BOXADDR]], %[[VAL_ASSOC]]#1) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>, !fir.ref<i32>) -> ()
+// CHECK: fir.if %[[VAL_IFRES]]#1 {
+// CHECK: %[[VAL_LOADBOX:.*]] = fir.load %[[VAL_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
+// CHECK: fir.do_loop %[[ARG2:.*]] = %[[VAL_C1]] to %[[VAL_EXTENT]] step %[[VAL_C1]] unordered {{.*}} {
+// CHECK: fir.box_dims %[[VAL_LOADBOX]]
+// CHECK: hlfir.designate %[[VAL_LOADBOX]]
+// CHECK: fir.load
+// CHECK: hlfir.designate %[[VAL_DESIGNATE]] (%[[ARG2]]) : (!fir.box<!fir.array<?xf64>>, index) -> !fir.ref<f64>
+// CHECK: hlfir.assign {{.*}} : f64, !fir.ref<f64>
+// CHECK: }
+// CHECK: %[[VAL_FREEADDR:.*]] = fir.box_addr %[[VAL_LOADBOX]] : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
+// CHECK: %[[VAL_FREEHEAP:.*]] = fir.convert %[[VAL_FREEADDR]] : (!fir.ref<!fir.array<?xf64>>) -> !fir.heap<!fir.array<?xf64>>
+// CHECK: fir.freemem %[[VAL_FREEHEAP]] : !fir.heap<!fir.array<?xf64>>
+// CHECK: }
+// CHECK: hlfir.end_associate %[[VAL_ASSOC]]#1, %[[VAL_ASSOC]]#2 : !fir.ref<i32>, i1
// CHECK: return
// CHECK: }
More information about the flang-commits
mailing list