[flang-commits] [flang] [flang][optimize] Use ArraySectionAnalyzer to better handle aliasing sections (PR #180595)
Delaram Talaashrafi via flang-commits
flang-commits at lists.llvm.org
Mon Feb 9 12:09:26 PST 2026
https://github.com/delaram-talaashrafi updated https://github.com/llvm/llvm-project/pull/180595
>From cbca54f8024efde6e43bc71c6e791242b2ab5d81 Mon Sep 17 00:00:00 2001
From: Delaram Talaashrafi <dtalaashrafi at rome5.pgi.net>
Date: Mon, 9 Feb 2026 10:58:28 -0800
Subject: [PATCH] [flang][optimize] Use ArraySectionAnalyzer to better handle
aliasing sections
When alias analysis reports potential aliasing between LHS and RHS when inlining hlfir.assign,
use `ArraySectionAnalyzer` to determine if the sections are disjoint or identical, which is safe
for element-wise assignment inlining.
---
.../HLFIR/Transforms/InlineHLFIRAssign.cpp | 20 ++++++----
flang/test/HLFIR/inline-hlfir-assign.fir | 37 +++++++++++++++++++
2 files changed, 50 insertions(+), 7 deletions(-)
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
index a6a2eb0cb3c37..356552fac249d 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Analysis/AliasAnalysis.h"
+#include "flang/Optimizer/Analysis/ArraySectionAnalyzer.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
@@ -93,14 +94,19 @@ class InlineHLFIRAssignConversion
// and proceed with the inlining.
fir::AliasAnalysis aliasAnalysis;
mlir::AliasResult aliasRes = aliasAnalysis.alias(lhs, rhs);
- // TODO: use areIdenticalOrDisjointSlices() from
- // OptimizedBufferization.cpp to check if we can still do the expansion.
if (!aliasRes.isNo()) {
- LLVM_DEBUG(llvm::dbgs() << "InlineHLFIRAssign:\n"
- << "\tLHS: " << lhs << "\n"
- << "\tRHS: " << rhs << "\n"
- << "\tALIAS: " << aliasRes << "\n");
- return rewriter.notifyMatchFailure(assign, "RHS/LHS may alias");
+ // Alias analysis reports potential aliasing, but we can use
+ // ArraySectionAnalyzer to check if the slices are disjoint
+ // or identical (which is safe for element-wise assignment).
+ fir::ArraySectionAnalyzer::SlicesOverlapKind overlap =
+ fir::ArraySectionAnalyzer::analyze(lhs, rhs);
+ if (overlap == fir::ArraySectionAnalyzer::SlicesOverlapKind::Unknown) {
+ LLVM_DEBUG(llvm::dbgs() << "InlineHLFIRAssign:\n"
+ << "\tLHS: " << lhs << "\n"
+ << "\tRHS: " << rhs << "\n"
+ << "\tALIAS: " << aliasRes << "\n");
+ return rewriter.notifyMatchFailure(assign, "RHS/LHS may alias");
+ }
}
}
diff --git a/flang/test/HLFIR/inline-hlfir-assign.fir b/flang/test/HLFIR/inline-hlfir-assign.fir
index 5f728bf140ea3..797ef6e81946a 100644
--- a/flang/test/HLFIR/inline-hlfir-assign.fir
+++ b/flang/test/HLFIR/inline-hlfir-assign.fir
@@ -407,3 +407,40 @@ func.func @_QMtest_global_shaped_targetPtest() {
}
fir.global @_QMtest_global_shaped_targetEa1 target : !fir.array<100xf32>
fir.global @_QMtest_global_shaped_targetEb1 target : !fir.array<100xf32>
+
+// Test disjoint array sections: a(n+1, :) = a(n, :) for a 2D array
+// The first index differs by 1 (n vs n+1), so ArraySectionAnalyzer detects them as disjoint.
+func.func @_QPtest_disjoint(%arg0: !fir.ref<!fir.array<10x10xf32>>) {
+ %c1 = arith.constant 1 : index
+ %c10 = arith.constant 10 : index
+ %0 = fir.shape %c10, %c10 : (index, index) -> !fir.shape<2>
+ %1:2 = hlfir.declare %arg0(%0) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtestEa"} : (!fir.ref<!fir.array<10x10xf32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>)
+ %2 = fir.alloca index
+ %n = fir.load %2 : !fir.ref<index>
+ %n_plus_1 = arith.addi %n, %c1 : index
+ %3 = fir.shape %c10 : (index) -> !fir.shape<1>
+ %4 = hlfir.designate %1#0 (%n, %c1:%c10:%c1) shape %3 : (!fir.ref<!fir.array<10x10xf32>>, index, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ %5 = hlfir.designate %1#0 (%n_plus_1, %c1:%c10:%c1) shape %3 : (!fir.ref<!fir.array<10x10xf32>>, index, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+ hlfir.assign %4 to %5 : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>
+ return
+}
+// CHECK-LABEL: func.func @_QPtest_disjoint(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x10xf32>>) {
+// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
+// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_2]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
+// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QFtestEa"} : (!fir.ref<!fir.array<10x10xf32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>)
+// CHECK: %[[VAL_5:.*]] = fir.alloca index
+// CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<index>
+// CHECK: %[[VAL_7:.*]] = arith.addi %[[VAL_6]], %[[VAL_1]] : index
+// CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
+// CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_6]], %[[VAL_1]]:%[[VAL_2]]:%[[VAL_1]]) shape %[[VAL_8]] : (!fir.ref<!fir.array<10x10xf32>>, index, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+// CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_7]], %[[VAL_1]]:%[[VAL_2]]:%[[VAL_1]]) shape %[[VAL_8]] : (!fir.ref<!fir.array<10x10xf32>>, index, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<10xf32>>
+// CHECK: fir.do_loop %[[VAL_11:.*]] = %[[VAL_1]] to %[[VAL_2]] step %[[VAL_1]] unordered {
+// CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_9]] (%[[VAL_11]]) : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
+// CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]] : !fir.ref<f32>
+// CHECK: %[[VAL_14:.*]] = hlfir.designate %[[VAL_10]] (%[[VAL_11]]) : (!fir.ref<!fir.array<10xf32>>, index) -> !fir.ref<f32>
+// CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_14]] : f32, !fir.ref<f32>
+// CHECK: }
+// CHECK: return
+// CHECK: }
More information about the flang-commits
mailing list