[flang-commits] [flang] [Flang]Add support for inlining hlfir.assign operation where both LHS and RHS are slices of the same array (PR #204532)
via flang-commits
flang-commits at lists.llvm.org
Thu Jun 18 02:20:14 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Kaviya Rajendiran (kaviya2510)
<details>
<summary>Changes</summary>
Added support for inlining hlfir.assign operation where both LHS and RHS are slices of the same array.
If overlap between the slices of the array cannot be proved at compile time, the pass inserts a runtime disjointness check genRuntimeDisjointnessCheck(..)
- If bounds are disjoint at runtime → perform a direct element-wise copy without using a temporary.
- If bounds may overlap at runtime → allocate a temp buffer, copy RHS into temp, then copy from temp to LHS
---
Patch is 21.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/204532.diff
5 Files Affected:
- (modified) flang/include/flang/Optimizer/Analysis/ArraySectionAnalyzer.h (+13-2)
- (modified) flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp (+51)
- (modified) flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp (+53-8)
- (added) flang/test/HLFIR/inline-hlfir-assign-self-copy-runtime-stride.fir (+102)
- (added) flang/test/HLFIR/inline-hlfir-assign-self-copy.fir (+148)
``````````diff
diff --git a/flang/include/flang/Optimizer/Analysis/ArraySectionAnalyzer.h b/flang/include/flang/Optimizer/Analysis/ArraySectionAnalyzer.h
index e87e37c3c5590..5bf60c49621ab 100644
--- a/flang/include/flang/Optimizer/Analysis/ArraySectionAnalyzer.h
+++ b/flang/include/flang/Optimizer/Analysis/ArraySectionAnalyzer.h
@@ -9,13 +9,13 @@
#ifndef FORTRAN_OPTIMIZER_ANALYSIS_ARRAYSECTIONANALYZER_H
#define FORTRAN_OPTIMIZER_ANALYSIS_ARRAYSECTIONANALYZER_H
+#include "mlir/IR/Location.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/Value.h"
#include "llvm/ADT/STLFunctionalExtras.h"
namespace mlir {
-class Operation;
-class Value;
+class OpBuilder;
} // namespace mlir
namespace hlfir {
@@ -62,6 +62,17 @@ class ArraySectionAnalyzer {
analyze(mlir::Value ref1, mlir::Value ref2,
ValueEquivalenceCallback areKnownEquivalent = nullptr);
+ /// Generate a runtime disjointness check for the given LHS and RHS.
+ /// Check if the sections are disjoint using `ub1 < lb2 || ub2 < lb1`
+ /// Returns true if the sections are disjoint, false otherwise.
+ /// Returns nullptr if the operands are not a matching pair of
+ /// hlfir.designate on the same base or no dimension has statically-known
+ /// stride order.
+ static mlir::Value genRuntimeDisjointnessCheck(mlir::Location loc,
+ mlir::OpBuilder &builder,
+ mlir::Value lhsRef,
+ mlir::Value rhsRef);
+
static bool isDesignatingArrayInOrder(hlfir::DesignateOp designate,
hlfir::ElementalOpInterface elemental);
diff --git a/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp b/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp
index 6eec184b99a7f..f657d67289874 100644
--- a/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp
+++ b/flang/lib/Optimizer/Analysis/ArraySectionAnalyzer.cpp
@@ -11,6 +11,7 @@
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
+#include "mlir/IR/BuiltinTypes.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "array-section-analyzer"
@@ -193,6 +194,56 @@ ArraySectionAnalyzer::analyze(mlir::Value ref1, mlir::Value ref2,
return SlicesOverlapKind::Unknown;
}
+mlir::Value ArraySectionAnalyzer::genRuntimeDisjointnessCheck(
+ mlir::Location loc, mlir::OpBuilder &builder, mlir::Value lhsRef,
+ mlir::Value rhsRef) {
+ auto des1 = lhsRef.getDefiningOp<hlfir::DesignateOp>();
+ auto des2 = rhsRef.getDefiningOp<hlfir::DesignateOp>();
+ if (!des1 || !des2)
+ return {};
+
+ if (des1.getMemref() != des2.getMemref())
+ return {};
+
+ if (des1.getComponent() != des2.getComponent() ||
+ des1.getComponentShape() != des2.getComponentShape() ||
+ des1.getSubstring() != des2.getSubstring() ||
+ des1.getComplexPart() != des2.getComplexPart() ||
+ des1.getTypeparams() != des2.getTypeparams())
+ return {};
+
+ if (des1.getIsTriplet().empty() ||
+ !llvm::equal(des1.getIsTriplet(), des2.getIsTriplet()))
+ return {};
+
+ mlir::Type idxTy = mlir::IndexType::get(des1.getContext());
+ auto toIdx = [&](mlir::Value v) -> mlir::Value {
+ return fir::ConvertOp::create(builder, loc, idxTy, v);
+ };
+
+ mlir::Value disjoint;
+ auto des1It = des1.getIndices().begin();
+ auto des2It = des2.getIndices().begin();
+ for (bool isTriplet : des1.getIsTriplet()) {
+ SectionDesc desc1 = readSectionDesc(des1It, isTriplet);
+ SectionDesc desc2 = readSectionDesc(des2It, isTriplet);
+ auto [lb1, ub1] = getOrderedBounds(desc1);
+ auto [lb2, ub2] = getOrderedBounds(desc2);
+ if (!lb1 || !lb2)
+ continue;
+
+ mlir::Value c1 = mlir::arith::CmpIOp::create(
+ builder, loc, mlir::arith::CmpIPredicate::slt, toIdx(ub1), toIdx(lb2));
+ mlir::Value c2 = mlir::arith::CmpIOp::create(
+ builder, loc, mlir::arith::CmpIPredicate::slt, toIdx(ub2), toIdx(lb1));
+ mlir::Value c1Orc2 = mlir::arith::OrIOp::create(builder, loc, c1, c2);
+ disjoint = disjoint
+ ? mlir::arith::OrIOp::create(builder, loc, disjoint, c1Orc2)
+ : c1Orc2;
+ }
+ return disjoint;
+}
+
bool ArraySectionAnalyzer::isLess(mlir::Value v1, mlir::Value v2) {
auto removeConvert = [](mlir::Value v) -> mlir::Operation * {
auto *op = v.getDefiningOp();
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
index b795d0b46da85..c38f351f067f8 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
@@ -103,6 +103,8 @@ class InlineHLFIRAssignConversion
return rewriter.notifyMatchFailure(assign,
"RHS/LHS element types mismatch");
+ bool rhsNeedsTemporary = false;
+
if (rhs.isArray() && !mlir::isa<hlfir::ExprType>(rhs.getType())) {
// If RHS is not an hlfir.expr, then we should prove that
// LHS and RHS do not alias.
@@ -121,7 +123,15 @@ class InlineHLFIRAssignConversion
<< "\tLHS: " << lhs << "\n"
<< "\tRHS: " << rhs << "\n"
<< "\tALIAS: " << aliasRes << "\n");
- return rewriter.notifyMatchFailure(assign, "RHS/LHS may alias");
+ // Overlap is Unknown: unsafe to read RHS while writing LHS
+ // without a temp. Call
+ // ArraySectionAnalyzer::genRuntimeDisjointnessCheck to check if the
+ // sections are disjoint.
+ // 1. Sections disjoint at runtime-> direct element-wise copy (no
+ // temp)
+ // 2. Sections are not disjoint at runtime -> Allocate a temporary
+ // and copy RHS into it, then copy the temporary to LHS.
+ rhsNeedsTemporary = true;
}
}
}
@@ -130,6 +140,43 @@ class InlineHLFIRAssignConversion
fir::FirOpBuilder builder(rewriter, assign.getOperation());
builder.setInsertionPoint(assign);
+ const bool useWorkshare = flangomp::shouldUseWorkshareLowering(assign);
+ mlir::ArrayAttr accessGroups;
+ if (auto attrs = assign.getOperation()->getAttrOfType<mlir::ArrayAttr>(
+ fir::getAccessGroupsAttrName()))
+ accessGroups = attrs;
+
+ auto emitAssignFrom = [&](hlfir::Entity rhsEntity) {
+ hlfir::genNoAliasArrayAssignment(
+ loc, builder, rhsEntity, lhs, useWorkshare,
+ /*temporaryLHS=*/false, nullptr, accessGroups);
+ };
+
+ if (rhsNeedsTemporary) {
+ if (mlir::Value disjoint =
+ fir::ArraySectionAnalyzer::genRuntimeDisjointnessCheck(
+ loc, builder, lhs, rhs)) {
+ builder.genIfThenElse(loc, disjoint)
+ .genThen([&]() { emitAssignFrom(rhs); })
+ .genElse([&]() {
+ mlir::Value tempExpr = hlfir::AsExprOp::create(builder, loc, rhs);
+ emitAssignFrom(hlfir::Entity{tempExpr});
+ hlfir::DestroyOp::create(builder, loc, tempExpr);
+ })
+ .end();
+ rewriter.eraseOp(assign);
+ return mlir::success();
+ }
+ }
+
+ // When rhsNeedsTemporary is true and genRuntimeDisjointnessCheck
+ // returned null, always use a temporary rhsExpr.
+ mlir::Value rhsTempExpr;
+ if (rhsNeedsTemporary) {
+ rhsTempExpr = hlfir::AsExprOp::create(builder, loc, rhs);
+ rhs = hlfir::Entity{rhsTempExpr};
+ }
+
// Materialize scalar RHS before the assignment loop. Fortran 10.2.1.3
// requires that the RHS expression is fully evaluated before any part
// of the LHS variable is defined. When the scalar RHS is a reference
@@ -138,13 +185,11 @@ class InlineHLFIRAssignConversion
if (!rhs.isArray())
rhs = hlfir::loadTrivialScalar(loc, builder, rhs);
- mlir::ArrayAttr accessGroups;
- if (auto attrs = assign.getOperation()->getAttrOfType<mlir::ArrayAttr>(
- fir::getAccessGroupsAttrName()))
- accessGroups = attrs;
- hlfir::genNoAliasArrayAssignment(
- loc, builder, rhs, lhs, flangomp::shouldUseWorkshareLowering(assign),
- /*temporaryLHS=*/false, /*combiner=*/nullptr, accessGroups);
+ emitAssignFrom(rhs);
+
+ if (rhsTempExpr)
+ hlfir::DestroyOp::create(builder, loc, rhsTempExpr);
+
rewriter.eraseOp(assign);
return mlir::success();
}
diff --git a/flang/test/HLFIR/inline-hlfir-assign-self-copy-runtime-stride.fir b/flang/test/HLFIR/inline-hlfir-assign-self-copy-runtime-stride.fir
new file mode 100644
index 0000000000000..6e5cce3d5d8b0
--- /dev/null
+++ b/flang/test/HLFIR/inline-hlfir-assign-self-copy-runtime-stride.fir
@@ -0,0 +1,102 @@
+// Self-copy of array sections with the same runtime stride on LHS and RHS.
+// Runtime stride prevents genRuntimeDisjointnessCheck(..) from building a disjoint
+// i1, so inlining uses hlfir.as_expr temporary
+//
+// RUN: fir-opt --inline-hlfir-assign %s | FileCheck %s
+
+// Fortran source:
+// subroutine testcase(a, n, step)
+// implicit none
+// integer, intent(in) :: n, step
+// real, intent(inout) :: a(n)
+// integer :: lo1, hi1, lo2, hi2
+// lo1 = 1
+// hi1 = max(n / 2, 1)
+// lo2 = 2
+// hi2 = n
+// a(lo1:hi1:step) = a(lo2:hi2:step)
+// end subroutine testcase
+//
+
+// CHECK-LABEL: func.func @_QPtestcase
+// CHECK-SAME: %[[A:.*]]: !fir.ref<!fir.array<?xf32>>
+
+// Box self-assign is lowered with a temp expr (no runtime disjointness guard).
+// CHECK: hlfir.designate
+// CHECK: hlfir.designate
+// CHECK: [[EXPR:%.*]] = hlfir.as_expr
+// CHECK-NOT: fir.if
+// CHECK: fir.do_loop
+// CHECK: hlfir.apply [[EXPR]]
+// CHECK: hlfir.assign
+// CHECK: hlfir.destroy [[EXPR]]
+
+func.func @_QPtestcase(%arg0: !fir.ref<!fir.array<?xf32>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}, %arg2: !fir.ref<i32> {fir.bindc_name = "step"}) {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1:2 = hlfir.declare %arg1 dummy_scope %0 arg 2 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtestcaseEn"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %2 = fir.alloca i32 {bindc_name = "hi1", uniq_name = "_QFtestcaseEhi1"}
+ %3:2 = hlfir.declare %2 {uniq_name = "_QFtestcaseEhi1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %4 = fir.alloca i32 {bindc_name = "hi2", uniq_name = "_QFtestcaseEhi2"}
+ %5:2 = hlfir.declare %4 {uniq_name = "_QFtestcaseEhi2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %6 = fir.alloca i32 {bindc_name = "lo1", uniq_name = "_QFtestcaseElo1"}
+ %7:2 = hlfir.declare %6 {uniq_name = "_QFtestcaseElo1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %8 = fir.alloca i32 {bindc_name = "lo2", uniq_name = "_QFtestcaseElo2"}
+ %9:2 = hlfir.declare %8 {uniq_name = "_QFtestcaseElo2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %10:2 = hlfir.declare %arg2 dummy_scope %0 arg 3 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtestcaseEstep"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %11 = fir.load %1#0 : !fir.ref<i32>
+ %12 = fir.convert %11 : (i32) -> i64
+ %13 = fir.convert %12 : (i64) -> index
+ %c0 = arith.constant 0 : index
+ %14 = arith.cmpi sgt, %13, %c0 : index
+ %15 = arith.select %14, %13, %c0 : index
+ %16 = fir.shape %15 : (index) -> !fir.shape<1>
+ %17:2 = hlfir.declare %arg0(%16) dummy_scope %0 arg 1 {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFtestcaseEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>)
+ %c1_i32 = arith.constant 1 : i32
+ hlfir.assign %c1_i32 to %7#0 : i32, !fir.ref<i32>
+ %18 = fir.load %1#0 : !fir.ref<i32>
+ %c2_i32 = arith.constant 2 : i32
+ %19 = arith.divsi %18, %c2_i32 : i32
+ %c1_i32_0 = arith.constant 1 : i32
+ %20 = arith.maxsi %19, %c1_i32_0 : i32
+ hlfir.assign %20 to %3#0 : i32, !fir.ref<i32>
+ %c2_i32_1 = arith.constant 2 : i32
+ hlfir.assign %c2_i32_1 to %9#0 : i32, !fir.ref<i32>
+ %21 = fir.load %1#0 : !fir.ref<i32>
+ hlfir.assign %21 to %5#0 : i32, !fir.ref<i32>
+ %22 = fir.load %9#0 : !fir.ref<i32>
+ %23 = fir.convert %22 : (i32) -> i64
+ %24 = fir.load %5#0 : !fir.ref<i32>
+ %25 = fir.convert %24 : (i32) -> i64
+ %26 = fir.convert %23 : (i64) -> index
+ %27 = fir.convert %25 : (i64) -> index
+ %28 = fir.load %10#0 : !fir.ref<i32>
+ %29 = fir.convert %28 : (i32) -> i64
+ %30 = fir.convert %29 : (i64) -> index
+ %c0_2 = arith.constant 0 : index
+ %31 = arith.subi %27, %26 : index
+ %32 = arith.addi %31, %30 : index
+ %33 = arith.divsi %32, %30 : index
+ %34 = arith.cmpi sgt, %33, %c0_2 : index
+ %35 = arith.select %34, %33, %c0_2 : index
+ %36 = fir.shape %35 : (index) -> !fir.shape<1>
+ %37 = hlfir.designate %17#0 (%26:%27:%30) shape %36 : (!fir.box<!fir.array<?xf32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+ %38 = fir.load %7#0 : !fir.ref<i32>
+ %39 = fir.convert %38 : (i32) -> i64
+ %40 = fir.load %3#0 : !fir.ref<i32>
+ %41 = fir.convert %40 : (i32) -> i64
+ %42 = fir.convert %39 : (i64) -> index
+ %43 = fir.convert %41 : (i64) -> index
+ %44 = fir.load %10#0 : !fir.ref<i32>
+ %45 = fir.convert %44 : (i32) -> i64
+ %46 = fir.convert %45 : (i64) -> index
+ %c0_3 = arith.constant 0 : index
+ %47 = arith.subi %43, %42 : index
+ %48 = arith.addi %47, %46 : index
+ %49 = arith.divsi %48, %46 : index
+ %50 = arith.cmpi sgt, %49, %c0_3 : index
+ %51 = arith.select %50, %49, %c0_3 : index
+ %52 = fir.shape %51 : (index) -> !fir.shape<1>
+ %53 = hlfir.designate %17#0 (%42:%43:%46) shape %52 : (!fir.box<!fir.array<?xf32>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+ hlfir.assign %37 to %53 : !fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>
+ return
+}
diff --git a/flang/test/HLFIR/inline-hlfir-assign-self-copy.fir b/flang/test/HLFIR/inline-hlfir-assign-self-copy.fir
new file mode 100644
index 0000000000000..84c3071c43dd7
--- /dev/null
+++ b/flang/test/HLFIR/inline-hlfir-assign-self-copy.fir
@@ -0,0 +1,148 @@
+// Test inlining of hlfir.assign for self-copy array section
+
+// RUN: fir-opt --inline-hlfir-assign %s | FileCheck %s
+
+// Fortran source code:
+// subroutine self_copy_ew(field, xm, ym, levs, xh, yh)
+// integer, intent(in) :: xm, ym, levs, xh, yh
+// real, intent(inout) :: field(xm + 2 * xh, ym + 2 * yh, levs)
+// integer :: x1, x2, x5, x6
+// x1 = 1
+// x2 = xh
+// x5 = xm + 1
+// x6 = xm + xh
+// field(x1:x2, :, :) = field(x5:x6, :, :)
+// end subroutine self_copy_ew
+
+// CHECK-LABEL: func.func @_QPself_copy_ew
+// CHECK-SAME: %[[ARGF:.*]]: !fir.ref<!fir.array<?x?x?xf32>> {fir.bindc_name = "field"}
+
+// CHECK: hlfir.declare %[[ARGF]](%{{.*}}) {{.*}} uniq_name = "_QFself_copy_ewEfield"
+// CHECK-DAG: hlfir.designate %{{.*}}#0 (
+// CHECK-DAG: hlfir.designate %{{.*}}#0 (
+// CHECK: fir.if %{{.*}} {
+// CHECK: fir.do_loop
+// CHECK: hlfir.assign
+// CHECK: } else {
+// CHECK: hlfir.as_expr
+// CHECK: fir.do_loop
+// CHECK: hlfir.destroy
+
+func.func @_QPself_copy_ew(%arg0: !fir.ref<!fir.array<?x?x?xf32>> {fir.bindc_name = "field"}, %arg1: !fir.ref<i32> {fir.bindc_name = "xm"}, %arg2: !fir.ref<i32> {fir.bindc_name = "ym"}, %arg3: !fir.ref<i32> {fir.bindc_name = "levs"}, %arg4: !fir.ref<i32> {fir.bindc_name = "xh"}, %arg5: !fir.ref<i32> {fir.bindc_name = "yh"}) {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1:2 = hlfir.declare %arg1 dummy_scope %0 arg 2 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFself_copy_ewExm"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %2:2 = hlfir.declare %arg4 dummy_scope %0 arg 5 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFself_copy_ewExh"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %3:2 = hlfir.declare %arg2 dummy_scope %0 arg 3 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFself_copy_ewEym"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %4:2 = hlfir.declare %arg5 dummy_scope %0 arg 6 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFself_copy_ewEyh"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %5:2 = hlfir.declare %arg3 dummy_scope %0 arg 4 {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFself_copy_ewElevs"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %6 = fir.alloca i32 {bindc_name = "x1", uniq_name = "_QFself_copy_ewEx1"}
+ %7:2 = hlfir.declare %6 {uniq_name = "_QFself_copy_ewEx1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %8 = fir.alloca i32 {bindc_name = "x2", uniq_name = "_QFself_copy_ewEx2"}
+ %9:2 = hlfir.declare %8 {uniq_name = "_QFself_copy_ewEx2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %10 = fir.alloca i32 {bindc_name = "x5", uniq_name = "_QFself_copy_ewEx5"}
+ %11:2 = hlfir.declare %10 {uniq_name = "_QFself_copy_ewEx5"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %12 = fir.alloca i32 {bindc_name = "x6", uniq_name = "_QFself_copy_ewEx6"}
+ %13:2 = hlfir.declare %12 {uniq_name = "_QFself_copy_ewEx6"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+ %14 = fir.load %1#0 : !fir.ref<i32>
+ %c2_i32 = arith.constant 2 : i32
+ %15 = fir.load %2#0 : !fir.ref<i32>
+ %16 = arith.muli %c2_i32, %15 : i32
+ %17 = arith.addi %14, %16 : i32
+ %18 = fir.convert %17 : (i32) -> i64
+ %19 = fir.convert %18 : (i64) -> index
+ %c0 = arith.constant 0 : index
+ %20 = arith.cmpi sgt, %19, %c0 : index
+ %21 = arith.select %20, %19, %c0 : index
+ %22 = fir.load %3#0 : !fir.ref<i32>
+ %c2_i32_0 = arith.constant 2 : i32
+ %23 = fir.load %4#0 : !fir.ref<i32>
+ %24 = arith.muli %c2_i32_0, %23 : i32
+ %25 = arith.addi %22, %24 : i32
+ %26 = fir.convert %25 : (i32) -> i64
+ %27 = fir.convert %26 : (i64) -> index
+ %c0_1 = arith.constant 0 : index
+ %28 = arith.cmpi sgt, %27, %c0_1 : index
+ %29 = arith.select %28, %27, %c0_1 : index
+ %30 = fir.load %5#0 : !fir.ref<i32>
+ %31 = fir.convert %30 : (i32) -> i64
+ %32 = fir.convert %31 : (i64) -> index
+ %c0_2 = arith.constant 0 : index
+ %33 = arith.cmpi sgt, %32, %c0_2 : index
+ %34 = arith.select %33, %32, %c0_2 : index
+ %35 = fir.shape %21, %29, %34 : (index, index, index) -> !fir.shape<3>
+ %36:2 = hlfir.declare %arg0(%35) dummy_scope %0 arg 1 {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFself_copy_ewEfield"} : (!fir.ref<!fir.array<?x?x?xf32>>, !fir.shape<3>, !fir.dscope) -> (!fir.box<!fir.array<?x?x?xf32>>, !fir.ref<!fir.array<?x?x?xf32>>)
+ %c1_i32 = arith.constant 1 : i32
+ hlfir.assign %c1_i32 to %7#0 : i32, !fir.ref<i32>
+ %37 = fir.load %2#0 : !fir.ref<i32>
+ hlfir.assign %37 to %9#0 : i32, !fir.ref<i32>
+ %38 = fir.load %1#0 : !fir.ref<i32>
+ %c1_i32_3 = arith.constant 1 : i32
+ %39 = arith.addi %38, %c1_i32_3 : i32
+ hlfir.assign %39 to %11#0 : i32, !fir.ref<i32>
+ %40 = fir.load %1#0 : !fir.ref<i32>
+ %41 = fir.load %2#0 : !fir.ref<i32>
+ %42 = arith.addi %40, %41 : i32
+ hlfir.assign %42 to %13#0 : i32, !fir.ref<i32>
+ %43 = fir.load %11#0 : !fir.ref<i32>
+ %44 = fir.convert %43 : (i32) -> i64
+ %45 = fir.load %13#0 : !fir.ref<i32>
+ %46 = fir.convert %45 : (i32) -> i64
+ %47 = fir.convert %44 : (i64) -> index
+ %48 = fir.convert %46 : (i64) -> index
+ %c1 = arith.constant 1 : index
+ %c0_4 = arith.constant 0 : index
+ %49 = arith.subi %48, %47 : index
+ %50 = arith.addi %49, %c1 : index
+ %51 = arith.divsi %50, %c1 : index
+ %52 = arith.cmpi sgt, %51, %c0_4 : index
+ %53 = arith.select %52, %51, %c0_4 : index
+ %c1_5 = arith.constant 1 : index
+ %c1_6 = arith.constant 1 : index
+ %c0_7 = arith.constant 0 : index
+ %54 = arith.subi %29, %c1_5 : index
+ %55 = arith.addi %54, %c1_6 : index
+ %56 = arith.divsi %55, %c1_6 : index
+ %57 = arith.cmpi sgt, %56, %c0_7 : index
+ %58 = arith.select %57, %56, %c0_7 : index
+ %c1_8 = arith.constant 1 : index
+ %c0_9 = arith.constant 0 : index
+ %59 = arith.subi %34, %c1_5 : index
+ %60 = arith.addi %59, %c1_8 : index
+ %61 = arith.divsi %60, %c1_8 : index
+ %62 = arith.cmpi sgt, %61, %c0_9 : index
+ %63 = arith.select %62, %61, %c0_9 : index
+ %64 = fir.shape %53, %58, %63 : (index, index, index) -> !fir.shape<3>
+ %65 = hlfir.designate %36#0 (%47:%48:%c1, %c1_5:%29:%c1_...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/204532
More information about the flang-commits
mailing list