[flang-commits] [flang] [flang] propagate IVDEP in array expressions optimization (PR #178171)
via flang-commits
flang-commits at lists.llvm.org
Tue Jan 27 03:54:32 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: None (jeanPerier)
<details>
<summary>Changes</summary>
Follow-up on https://github.com/llvm/llvm-project/pull/177940.
This propagates the access attribute in cases where hlfir.assign is being transformed in array expression optimizations.
It also adds handling for the cases where there are WHERE/FORALL or user defined assignments inside the loop and that an hlfir.region_assign is first being generated.
---
Full diff: https://github.com/llvm/llvm-project/pull/178171.diff
5 Files Affected:
- (modified) flang/lib/Lower/Bridge.cpp (+8)
- (modified) flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp (+4-1)
- (modified) flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp (+16-3)
- (added) flang/test/Lower/HLFIR/ivdep-elemental.f90 (+20)
- (added) flang/test/Lower/HLFIR/ivdep-where.f90 (+17)
``````````diff
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 1699b4b94a3dd..1d8d89776c33d 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2408,6 +2408,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// necessary to forward the AccessGroups attribute.
assignOp.getOperation()->setAttr(fir::getAccessGroupsAttrName(),
attrs);
+ } else if (hlfir::RegionAssignOp regionAssignOp =
+ mlir::dyn_cast<hlfir::RegionAssignOp>(op)) {
+ // User defined assignment, WHERE and FORALL assignments are
+ // abstracted via hlfir.region_assign at that stage. Set the
+ // access group on it so that it can later be propagated to
+ // hlfir.assign/fir.store/fir.loads created to implement it.
+ regionAssignOp.getOperation()->setAttr(
+ fir::getAccessGroupsAttrName(), attrs);
} else if (fir::CallOp callOp = mlir::dyn_cast<fir::CallOp>(op)) {
callOp.setAccessGroupsAttr(attrs);
}
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
index 32998ab64cb8c..71b4e91f0110d 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
@@ -517,7 +517,10 @@ void OrderedAssignmentRewriter::pre(hlfir::RegionAssignOp regionAssignOp) {
} else {
// TODO: preserve allocatable assignment aspects for forall once
// they are conveyed in hlfir.region_assign.
- hlfir::AssignOp::create(builder, loc, rhsEntity, lhsEntity);
+ auto assignOp = hlfir::AssignOp::create(builder, loc, rhsEntity, lhsEntity);
+ if (auto accessGroups = regionAssignOp->getAttrOfType<mlir::ArrayAttr>(
+ fir::getAccessGroupsAttrName()))
+ assignOp->setAttr(fir::getAccessGroupsAttrName(), accessGroups);
}
generateCleanupIfAny(loweredLhs.elementalCleanup);
if (loweredLhs.vectorSubscriptLoopNest)
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
index 2712bfba60dd4..5351a9a50954f 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
@@ -727,9 +727,13 @@ llvm::LogicalResult ElementalAssignBufferization::matchAndRewrite(
// Assign the element value to the array element for this iteration.
auto arrayElement =
hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices);
- hlfir::AssignOp::create(
+ auto newAssign = hlfir::AssignOp::create(
builder, loc, elementValue, arrayElement, /*realloc=*/false,
/*keep_lhs_length_if_realloc=*/false, match->assign.getTemporaryLhs());
+ if (auto accessGroups =
+ match->assign.getOperation()->getAttrOfType<mlir::ArrayAttr>(
+ fir::getAccessGroupsAttrName()))
+ newAssign->setAttr(fir::getAccessGroupsAttrName(), accessGroups);
rewriter.eraseOp(match->assign);
rewriter.eraseOp(match->destroy);
@@ -788,6 +792,11 @@ llvm::LogicalResult BroadcastAssignBufferization::matchAndRewrite(
llvm::SmallVector<mlir::Value> extents =
hlfir::getIndexExtents(loc, builder, shape);
+ mlir::ArrayAttr accessGroups;
+ if (auto attrs = assign.getOperation()->getAttrOfType<mlir::ArrayAttr>(
+ fir::getAccessGroupsAttrName()))
+ accessGroups = attrs;
+
if (lhs.isSimplyContiguous() && extents.size() > 1) {
// Flatten the array to use a single assign loop, that can be better
// optimized.
@@ -824,7 +833,9 @@ llvm::LogicalResult BroadcastAssignBufferization::matchAndRewrite(
mlir::Value arrayElement =
hlfir::DesignateOp::create(builder, loc, fir::ReferenceType::get(eleTy),
flatArray, loopNest.oneBasedIndices);
- hlfir::AssignOp::create(builder, loc, rhs, arrayElement);
+ auto newAssign = hlfir::AssignOp::create(builder, loc, rhs, arrayElement);
+ if (accessGroups)
+ newAssign->setAttr(fir::getAccessGroupsAttrName(), accessGroups);
} else {
hlfir::LoopNest loopNest =
hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true,
@@ -832,7 +843,9 @@ llvm::LogicalResult BroadcastAssignBufferization::matchAndRewrite(
builder.setInsertionPointToStart(loopNest.body);
auto arrayElement =
hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices);
- hlfir::AssignOp::create(builder, loc, rhs, arrayElement);
+ auto newAssign = hlfir::AssignOp::create(builder, loc, rhs, arrayElement);
+ if (accessGroups)
+ newAssign->setAttr(fir::getAccessGroupsAttrName(), accessGroups);
}
rewriter.eraseOp(assign);
diff --git a/flang/test/Lower/HLFIR/ivdep-elemental.f90 b/flang/test/Lower/HLFIR/ivdep-elemental.f90
new file mode 100644
index 0000000000000..ac5b274429725
--- /dev/null
+++ b/flang/test/Lower/HLFIR/ivdep-elemental.f90
@@ -0,0 +1,20 @@
+! RUN: %flang_fc1 -emit-fir -O2 %s -o - | FileCheck %s
+
+! CHECK: #[[ANNOTATION:.*]] = #llvm.loop_annotation<vectorize = #{{.*}}, parallelAccesses = #[[GROUP:.*]]>
+subroutine elemental_assignment_in_loop(a, b)
+ real :: a(100,100), b(100,100)
+ !dir$ ivdep
+ ! CHECK: fir.do_loop
+ ! CHECK-SAME: loopAnnotation = #[[ANNOTATION]]
+ do i=1,100
+ ! CHECK: fir.do_loop
+ ! CHECK: fir.load
+ ! CHECK-SAME: accessGroups = [#[[GROUP]]]
+ ! CHECK: fir.store
+ ! CHECK-SAME: accessGroups = [#[[GROUP]]]
+ a(i, :) = b(i, :) * 3.0
+ ! CHECK: }
+ ! CHECK: }
+ ! CHECK: return
+ end do
+end subroutine
diff --git a/flang/test/Lower/HLFIR/ivdep-where.f90 b/flang/test/Lower/HLFIR/ivdep-where.f90
new file mode 100644
index 0000000000000..cddf28cf4e4b7
--- /dev/null
+++ b/flang/test/Lower/HLFIR/ivdep-where.f90
@@ -0,0 +1,17 @@
+! RUN: %flang_fc1 -emit-fir -O2 %s -o - | FileCheck %s
+
+! CHECK: #[[ANNOTATION:.*]] = #llvm.loop_annotation<vectorize = #{{.*}}, parallelAccesses = #[[GROUP:.*]]>
+subroutine test_where(a, l)
+ real :: a(100,100)
+ logical :: l(100, 100)
+ !dir$ ivdep
+ ! CHECK: fir.do_loop
+ ! CHECK-SAME: loopAnnotation = #[[ANNOTATION]]
+ do i=1,100
+ ! CHECK: fir.do_loop
+ where (l(i, :)) a(i, :) = 3.0
+ ! CHECK: fir.store
+ ! CHECK-SAME: accessGroups = [#[[GROUP]]]
+ ! CHECK: }
+ end do
+end subroutine
``````````
</details>
https://github.com/llvm/llvm-project/pull/178171
More information about the flang-commits
mailing list