[flang-commits] [flang] [Flang]Add support for inlining hlfir.assign operation where both LHS and RHS are slices of the same array (PR #204532)
Kaviya Rajendiran via flang-commits
flang-commits at lists.llvm.org
Thu Jun 18 02:20:02 PDT 2026
https://github.com/kaviya2510 updated https://github.com/llvm/llvm-project/pull/204532
>From 5ce8f69b0bec1b33ed308b353c355d90e0204d74 Mon Sep 17 00:00:00 2001
From: Kaviya Rajendiran <kaviyara2000 at gmail.com>
Date: Thu, 18 Jun 2026 14:43:52 +0530
Subject: [PATCH] [Flang]Add support for inlining hlfir.assign operation where
both LHS and RHS are slices of the same array
---
.../Optimizer/Analysis/ArraySectionAnalyzer.h | 15 +-
.../Analysis/ArraySectionAnalyzer.cpp | 51 ++++++
.../HLFIR/Transforms/InlineHLFIRAssign.cpp | 61 +++++++-
...-hlfir-assign-self-copy-runtime-stride.fir | 102 ++++++++++++
.../HLFIR/inline-hlfir-assign-self-copy.fir | 148 ++++++++++++++++++
5 files changed, 367 insertions(+), 10 deletions(-)
create mode 100644 flang/test/HLFIR/inline-hlfir-assign-self-copy-runtime-stride.fir
create mode 100644 flang/test/HLFIR/inline-hlfir-assign-self-copy.fir
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_6, %c1_5:%34:%c1_8) shape %64 : (!fir.box<!fir.array<?x?x?xf32>>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box<!fir.array<?x?x?xf32>>
+ %66 = fir.load %7#0 : !fir.ref<i32>
+ %67 = fir.convert %66 : (i32) -> i64
+ %68 = fir.load %9#0 : !fir.ref<i32>
+ %69 = fir.convert %68 : (i32) -> i64
+ %70 = fir.convert %67 : (i64) -> index
+ %71 = fir.convert %69 : (i64) -> index
+ %c1_10 = arith.constant 1 : index
+ %c0_11 = arith.constant 0 : index
+ %72 = arith.subi %71, %70 : index
+ %73 = arith.addi %72, %c1_10 : index
+ %74 = arith.divsi %73, %c1_10 : index
+ %75 = arith.cmpi sgt, %74, %c0_11 : index
+ %76 = arith.select %75, %74, %c0_11 : index
+ %c1_12 = arith.constant 1 : index
+ %c1_13 = arith.constant 1 : index
+ %c0_14 = arith.constant 0 : index
+ %77 = arith.subi %29, %c1_12 : index
+ %78 = arith.addi %77, %c1_13 : index
+ %79 = arith.divsi %78, %c1_13 : index
+ %80 = arith.cmpi sgt, %79, %c0_14 : index
+ %81 = arith.select %80, %79, %c0_14 : index
+ %c1_15 = arith.constant 1 : index
+ %c0_16 = arith.constant 0 : index
+ %82 = arith.subi %34, %c1_12 : index
+ %83 = arith.addi %82, %c1_15 : index
+ %84 = arith.divsi %83, %c1_15 : index
+ %85 = arith.cmpi sgt, %84, %c0_16 : index
+ %86 = arith.select %85, %84, %c0_16 : index
+ %87 = fir.shape %76, %81, %86 : (index, index, index) -> !fir.shape<3>
+ %88 = hlfir.designate %36#0 (%70:%71:%c1_10, %c1_12:%29:%c1_13, %c1_12:%34:%c1_15) shape %87 : (!fir.box<!fir.array<?x?x?xf32>>, index, index, index, index, index, index, index, index, index, !fir.shape<3>) -> !fir.box<!fir.array<?x?x?xf32>>
+ hlfir.assign %65 to %88 : !fir.box<!fir.array<?x?x?xf32>>, !fir.box<!fir.array<?x?x?xf32>>
+ return
+}
More information about the flang-commits
mailing list