https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/178152
Backport c2d510f Requested by: @tblah >From 27d655412366c5815961d5fb1acb07cc80ec3d97 Mon Sep 17 00:00:00 2001 From: jeanPerier <[email protected]> Date: Tue, 27 Jan 2026 10:18:41 +0100 Subject: [PATCH] [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) --- .../flang/Optimizer/Builder/HLFIRTools.h | 11 ++++--- .../flang/Optimizer/Dialect/FIROpsSupport.h | 5 +++ flang/lib/Lower/Bridge.cpp | 3 +- flang/lib/Optimizer/Builder/HLFIRTools.cpp | 32 +++++++++++++------ .../HLFIR/Transforms/ConvertToFIR.cpp | 2 +- .../HLFIR/Transforms/InlineHLFIRAssign.cpp | 7 +++- flang/test/Lower/ivdep-array.f90 | 20 ++++++++++++ 7 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 flang/test/Lower/ivdep-array.f90 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
