[llvm-branch-commits] [flang] e636639 - [flang] fix DIR IVDEP for array assignments inside loops (#177940)
Cullen Rhodes via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 29 00:12:46 PST 2026
Author: jeanPerier
Date: 2026-01-29T08:12:38Z
New Revision: e636639f579b9ad5d1524a9059bcae6301cbed1c
URL: https://github.com/llvm/llvm-project/commit/e636639f579b9ad5d1524a9059bcae6301cbed1c
DIFF: https://github.com/llvm/llvm-project/commit/e636639f579b9ad5d1524a9059bcae6301cbed1c.diff
LOG: [flang] fix DIR IVDEP for array assignments inside loops (#177940)
The access attribute set on hlfir.assign for arrays was lost in
InlineHLFIRAssign.cpp. This patch propagates it to the creates loads and
stores.
(cherry picked from commit c2d510f5bdabf71f4f5fde36a37faf5565762195)
Added:
flang/test/Lower/ivdep-array.f90
Modified:
flang/include/flang/Optimizer/Builder/HLFIRTools.h
flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
flang/lib/Lower/Bridge.cpp
flang/lib/Optimizer/Builder/HLFIRTools.cpp
flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
index 9933e3ed6c308..404144f11e3df 100644
--- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h
+++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h
@@ -461,7 +461,8 @@ void genNoAliasArrayAssignment(
bool temporaryLHS = false,
std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &,
hlfir::Entity, hlfir::Entity)> *combiner =
- nullptr);
+ nullptr,
+ mlir::ArrayAttr accessGroups = {});
/// Generate an assignment from \p rhs to \p lhs when they are known not to
/// alias. Handles both arrays and scalars: for arrays, delegates to
@@ -474,15 +475,17 @@ void genNoAliasAssignment(
bool temporaryLHS = false,
std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &,
hlfir::Entity, hlfir::Entity)> *combiner =
- nullptr);
+ nullptr,
+ mlir::ArrayAttr accessGroups = {});
inline void genNoAliasAssignment(
mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs,
hlfir::Entity lhs, bool emitWorkshareLoop, bool temporaryLHS,
std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &,
hlfir::Entity, hlfir::Entity)>
- combiner) {
+ combiner,
+ mlir::ArrayAttr accessGroups = {}) {
genNoAliasAssignment(loc, builder, rhs, lhs, emitWorkshareLoop, temporaryLHS,
- &combiner);
+ &combiner, accessGroups);
}
/// Create a new temporary with the shape and parameters of the provided
diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index ae471eb0d2e04..b014d925592cb 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -131,6 +131,11 @@ static constexpr llvm::StringRef getHasLifetimeMarkerAttrName() {
return "fir.has_lifetime";
}
+/// Attribute to mark the access groups of an operation.
+static constexpr llvm::StringRef getAccessGroupsAttrName() {
+ return "access_groups";
+}
+
/// Does the function, \p func, have a host-associations tuple argument?
/// Some internal procedures may have access to host procedure variables.
bool hasHostAssociationArgument(mlir::func::FuncOp func);
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 1f35153928500..cd743cc0b27c6 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2405,7 +2405,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// In some loops, the HLFIR AssignOp operation can be translated
// into FIR operation(s) containing StoreOp. It is therefore
// necessary to forward the AccessGroups attribute.
- assignOp.getOperation()->setAttr("access_groups", attrs);
+ assignOp.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/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index a345dcb86e3d6..133fa17af3f71 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -1396,23 +1396,33 @@ static void combineAndStoreElement(
mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity lhs,
hlfir::Entity rhs, bool temporaryLHS,
std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &,
- hlfir::Entity, hlfir::Entity)> *combiner) {
+ hlfir::Entity, hlfir::Entity)> *combiner,
+ mlir::ArrayAttr accessGroups) {
hlfir::Entity valueToAssign = hlfir::loadTrivialScalar(loc, builder, rhs);
+ if (accessGroups)
+ if (auto load = valueToAssign.getDefiningOp<fir::LoadOp>())
+ load.setAccessGroupsAttr(accessGroups);
if (combiner) {
hlfir::Entity lhsValue = hlfir::loadTrivialScalar(loc, builder, lhs);
+ if (accessGroups)
+ if (auto load = lhsValue.getDefiningOp<fir::LoadOp>())
+ load.setAccessGroupsAttr(accessGroups);
valueToAssign = (*combiner)(loc, builder, lhsValue, valueToAssign);
}
- hlfir::AssignOp::create(builder, loc, valueToAssign, lhs,
- /*realloc=*/false,
- /*keep_lhs_length_if_realloc=*/false,
- /*temporary_lhs=*/temporaryLHS);
+ auto assign = hlfir::AssignOp::create(builder, loc, valueToAssign, lhs,
+ /*realloc=*/false,
+ /*keep_lhs_length_if_realloc=*/false,
+ /*temporary_lhs=*/temporaryLHS);
+ if (accessGroups)
+ assign->setAttr(fir::getAccessGroupsAttrName(), accessGroups);
}
void hlfir::genNoAliasArrayAssignment(
mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs,
hlfir::Entity lhs, bool emitWorkshareLoop, bool temporaryLHS,
std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &,
- hlfir::Entity, hlfir::Entity)> *combiner) {
+ hlfir::Entity, hlfir::Entity)> *combiner,
+ mlir::ArrayAttr accessGroups) {
mlir::OpBuilder::InsertionGuard guard(builder);
rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs);
lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs);
@@ -1434,22 +1444,24 @@ void hlfir::genNoAliasArrayAssignment(
auto lhsArrayElement =
hlfir::getElementAt(loc, builder, lhs, loopNest.oneBasedIndices);
combineAndStoreElement(loc, builder, lhsArrayElement, rhsArrayElement,
- temporaryLHS, combiner);
+ temporaryLHS, combiner, accessGroups);
}
void hlfir::genNoAliasAssignment(
mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs,
hlfir::Entity lhs, bool emitWorkshareLoop, bool temporaryLHS,
std::function<hlfir::Entity(mlir::Location, fir::FirOpBuilder &,
- hlfir::Entity, hlfir::Entity)> *combiner) {
+ hlfir::Entity, hlfir::Entity)> *combiner,
+ mlir::ArrayAttr accessGroups) {
if (lhs.isArray()) {
genNoAliasArrayAssignment(loc, builder, rhs, lhs, emitWorkshareLoop,
- temporaryLHS, combiner);
+ temporaryLHS, combiner, accessGroups);
return;
}
rhs = hlfir::derefPointersAndAllocatables(loc, builder, rhs);
lhs = hlfir::derefPointersAndAllocatables(loc, builder, lhs);
- combineAndStoreElement(loc, builder, lhs, rhs, temporaryLHS, combiner);
+ combineAndStoreElement(loc, builder, lhs, rhs, temporaryLHS, combiner,
+ accessGroups);
}
std::pair<hlfir::Entity, bool>
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
index a63695f38afc6..13d9fc264b9b8 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -151,7 +151,7 @@ class AssignOpConversion : public mlir::OpRewritePattern<hlfir::AssignOp> {
mlir::ArrayAttr accessGroups;
if (auto attrs = assignOp.getOperation()->getAttrOfType<mlir::ArrayAttr>(
- "access_groups"))
+ fir::getAccessGroupsAttrName()))
accessGroups = attrs;
// genScalarAssignment() must take care of potential overlap
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
index 1fc592c7fe522..a6a2eb0cb3c37 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/InlineHLFIRAssign.cpp
@@ -107,8 +107,13 @@ class InlineHLFIRAssignConversion
mlir::Location loc = assign->getLoc();
fir::FirOpBuilder builder(rewriter, assign.getOperation());
builder.setInsertionPoint(assign);
+ mlir::ArrayAttr accessGroups;
+ if (auto attrs = assign.getOperation()->getAttrOfType<mlir::ArrayAttr>(
+ fir::getAccessGroupsAttrName()))
+ accessGroups = attrs;
hlfir::genNoAliasArrayAssignment(
- loc, builder, rhs, lhs, flangomp::shouldUseWorkshareLowering(assign));
+ loc, builder, rhs, lhs, flangomp::shouldUseWorkshareLowering(assign),
+ /*temporaryLHS=*/false, /*combiner=*/nullptr, accessGroups);
rewriter.eraseOp(assign);
return mlir::success();
}
diff --git a/flang/test/Lower/ivdep-array.f90 b/flang/test/Lower/ivdep-array.f90
new file mode 100644
index 0000000000000..d018fbaf81a92
--- /dev/null
+++ b/flang/test/Lower/ivdep-array.f90
@@ -0,0 +1,20 @@
+! RUN: %flang_fc1 -emit-fir -O2 %s -o - | FileCheck %s
+
+! CHECK: #[[ANNOTATION:.*]] = #llvm.loop_annotation<vectorize = #{{.*}}, parallelAccesses = #[[GROUP:.*]]>
+subroutine array_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, :)
+ ! CHECK: }
+ ! CHECK: }
+ ! CHECK: return
+ end do
+end subroutine
More information about the llvm-branch-commits
mailing list