[flang-commits] [flang] [mlir] [flang][OpenACC] Attach `OpenACCLoopLocAttr` to `acc.loop` op (PR #208238)
Moazin K. via flang-commits
flang-commits at lists.llvm.org
Wed Jul 8 08:19:24 PDT 2026
https://github.com/moazin created https://github.com/llvm/llvm-project/pull/208238
Introduce an attribute `OpenACCLoopLocAttr` that can be attached to an `acc.loop` operation to record loop locations and directive location separately.
Attach it to `acc.loop` when building the op in flang.
>From 719804362ed6aa0712d586845176e31347273dfc Mon Sep 17 00:00:00 2001
From: Moazin Khatti <mkhatti at nvidia.com>
Date: Thu, 2 Jul 2026 06:25:53 -0700
Subject: [PATCH] [flang][OpenACC] Attach `OpenACCLoopLocAttr` to `acc.loop` op
Introduce an attribute `OpenACCLoopLocAttr` that can be attached to
an `acc.loop` operation to record loop locations and directive
location separately.
Attach it to `acc.loop` when building the op in flang.
Assisted-by: Claude Code
---
flang/lib/Lower/OpenACC.cpp | 30 ++++++++++++++-----
flang/test/Lower/OpenACC/locations.f90 | 23 +++++++++++---
.../mlir/Dialect/OpenACC/OpenACCOps.td | 9 ++++++
3 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index e28c31f16b9d9..8c1f071a8d31d 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -1828,7 +1828,6 @@ static void processDoLoopBounds(
std::pair<Fortran::semantics::SymbolRef, Fortran::semantics::SymbolRef>>
&localSymPairs) {
assert(loopsToProcess > 0 && "expect at least one loop");
- locs.push_back(currentLocation); // Location of the directive
bool isDoConcurrent = outerDoConstruct.IsDoConcurrent();
if (isDoConcurrent) {
@@ -2105,7 +2104,7 @@ buildACCLoopOp(Fortran::lower::AbstractConverter &converter,
llvm::SmallVector<mlir::Value> &cacheOperands,
llvm::SmallVector<mlir::Value> &reductionOperands,
llvm::SmallVector<mlir::Type> &retTy, mlir::Value yieldValue,
- uint64_t loopsToProcess) {
+ uint64_t loopsToProcess, bool hasDirective) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
llvm::SmallVector<std::pair<mlir::Value, Fortran::semantics::SymbolRef>>
@@ -2151,10 +2150,26 @@ buildACCLoopOp(Fortran::lower::AbstractConverter &converter,
addOperands(operands, operandSegments, firstprivateOperands);
addOperands(operands, operandSegments, reductionOperands);
+ // list of locations to build FusedLoc to be attached to acc loop
+ llvm::SmallVector<mlir::Location> fusedLocs;
+ if (hasDirective)
+ fusedLocs.push_back(currentLocation);
+ fusedLocs.append(locs.begin(), locs.end());
+
+ // list of only loop locations used to build an `mlir::acc::LoopLocAttr` to be
+ // attached to the `FusedLoc` as metadata so that consumers of location
+ // information can separate out the directive's location from the loops'
+ // locations
+ llvm::SmallVector<mlir::LocationAttr> loopLocAttrs(locs.begin(), locs.end());
+ auto loopLocMeta = mlir::acc::LoopLocAttr::get(
+ builder.getContext(),
+ hasDirective ? mlir::LocationAttr(currentLocation) : mlir::LocationAttr{},
+ loopLocAttrs);
+
auto loopOp = createRegionOp<mlir::acc::LoopOp, mlir::acc::YieldOp>(
- builder, builder.getFusedLoc(locs), currentLocation, eval, operands,
- operandSegments, /*outerCombined=*/false, retTy, yieldValue, ivTypes,
- ivLocs);
+ builder, builder.getFusedLoc(fusedLocs, loopLocMeta), currentLocation,
+ eval, operands, operandSegments, /*outerCombined=*/false, retTy,
+ yieldValue, ivTypes, ivLocs);
// Ensure the iv symbol is mapped to private iv SSA value for the scope of
// the loop even if it did not appear explicitly in a PRIVATE clause (if it
// appeared explicitly in such clause, that is also fine because duplicates
@@ -2419,7 +2434,7 @@ static mlir::acc::LoopOp createLoopOp(
converter, currentLocation, semanticsContext, stmtCtx, outerDoConstruct,
eval, privateOperands, dataMap, gangOperands, workerNumOperands,
vectorOperands, tileOperands, cacheOperands, reductionOperands, retTy,
- yieldValue, loopsToProcess);
+ yieldValue, loopsToProcess, /*hasDirective=*/true);
if (!gangDeviceTypes.empty())
loopOp.setGangAttr(builder.getArrayAttr(gangDeviceTypes));
@@ -5355,7 +5370,8 @@ mlir::Operation *Fortran::lower::genOpenACCLoopFromDoConstruct(
converter, converter.getCurrentLocation(), semanticsContext, stmtCtx,
doConstruct, eval, privateOperands, dataMap, gangOperands,
workerNumOperands, vectorOperands, tileOperands, cacheOperands,
- reductionOperands, retTy, yieldValue, loopsToProcess);
+ reductionOperands, retTy, yieldValue, loopsToProcess,
+ /*hasDirective=*/false);
// Normal do loops which are not annotated with `acc loop` should be
// left for analysis by marking with `auto`. This is the case even in the case
diff --git a/flang/test/Lower/OpenACC/locations.f90 b/flang/test/Lower/OpenACC/locations.f90
index 46e8df0e9dac4..fe1dc5c918e2d 100644
--- a/flang/test/Lower/OpenACC/locations.f90
+++ b/flang/test/Lower/OpenACC/locations.f90
@@ -53,7 +53,7 @@ subroutine nested_acc_locations(arr1d)
!CHECK: acc.loop
!CHECK: acc.yield loc("{{.*}}locations.f90":44:11)
- !CHECK-NEXT: } attributes {{.*}} loc(fused["{{.*}}locations.f90":44:11, "{{.*}}locations.f90":45:5])
+ !CHECK-NEXT: } attributes {{.*}} loc(fused<#acc.loop_loc<directive = loc("{{[^"]*}}locations.f90":44:11), loops = loc("{{[^"]*}}locations.f90":45:5)>>["{{[^"]*}}locations.f90":44:11, "{{[^"]*}}locations.f90":45:5])
!CHECK: acc.yield loc("{{.*}}locations.f90":43:11)
!CHECK-NEXT: } loc("{{.*}}locations.f90":43:11)
@@ -87,7 +87,7 @@ subroutine combined_directive_locations(arr)
!CHECK: acc.parallel
!CHECK: acc.loop
!CHECK: acc.yield loc("{{.*}}locations.f90":82:11)
- !CHECK-NEXT: } {{.*}} loc(fused["{{.*}}locations.f90":82:11, "{{.*}}locations.f90":83:5])
+ !CHECK-NEXT: } {{.*}} loc(fused<#acc.loop_loc<directive = loc("{{[^"]*}}locations.f90":82:11), loops = loc("{{[^"]*}}locations.f90":83:5)>>["{{[^"]*}}locations.f90":82:11, "{{[^"]*}}locations.f90":83:5])
!CHECK: acc.yield loc("{{.*}}locations.f90":82:11)
!CHECK-NEXT: } loc("{{.*}}locations.f90":82:11)
end subroutine
@@ -106,7 +106,7 @@ subroutine if_clause_expr_location(arr)
!CHECK: acc.parallel
!CHECK: acc.loop
!CHECK: acc.yield loc("{{.*}}locations.f90":99:11)
- !CHECK-NEXT: } {{.*}} loc(fused["{{.*}}locations.f90":99:11, "{{.*}}locations.f90":100:5])
+ !CHECK-NEXT: } {{.*}} loc(fused<#acc.loop_loc<directive = loc("{{[^"]*}}locations.f90":99:11), loops = loc("{{[^"]*}}locations.f90":100:5)>>["{{[^"]*}}locations.f90":99:11, "{{[^"]*}}locations.f90":100:5])
!CHECK: acc.yield loc("{{.*}}locations.f90":99:11)
!CHECK-NEXT: } loc("{{.*}}locations.f90":99:11)
end subroutine
@@ -169,7 +169,7 @@ subroutine acc_loop_fused_locations(arr)
! CHECK-LABEL: func.func @_QMacc_locationsPacc_loop_fused_locations
! CHECK: acc.loop
-! CHECK: } attributes {collapse = [3]{{.*}}} loc(fused["{{.*}}locations.f90":160:11, "{{.*}}locations.f90":161:5, "{{.*}}locations.f90":162:7, "{{.*}}locations.f90":163:9])
+! CHECK: } attributes {collapse = [3]{{.*}}} loc(fused<#acc.loop_loc<directive = loc("{{[^"]*}}locations.f90":160:11), loops = loc("{{[^"]*}}locations.f90":161:5), loc("{{[^"]*}}locations.f90":162:7), loc("{{[^"]*}}locations.f90":163:9)>>["{{[^"]*}}locations.f90":160:11, "{{[^"]*}}locations.f90":161:5, "{{[^"]*}}locations.f90":162:7, "{{[^"]*}}locations.f90":163:9])
subroutine data_end_locations(arr)
real, dimension(10) :: arr
@@ -182,4 +182,19 @@ subroutine data_end_locations(arr)
!CHECK-LABEL: acc.copyout
!CHECK-SAME: loc("{{.*}}locations.f90":181:11)
end subroutine
+
+ subroutine acc_kernel_with_loop_locations(arr)
+ real, dimension(10) :: arr
+ integer :: i
+
+ !$acc kernels
+ do i = 1, 10
+ arr(i) = arr(i) + 1
+ end do
+ !$acc end kernels
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMacc_locationsPacc_kernel_with_loop_locations
+! CHECK: acc.loop
+! CHECK: } attributes {{.*}} loc(fused<#acc.loop_loc<loops = loc("{{[^"]*}}locations.f90":191:5)>>["{{[^"]*}}locations.f90":191:5])
end module
diff --git a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
index 26a9344fa3a15..070e6688684e6 100644
--- a/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
+++ b/mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td
@@ -384,6 +384,15 @@ def DeclareActionAttr : OpenACC_Attr<"DeclareAction", "declare_action"> {
let assemblyFormat = "`<` struct(params) `>`";
}
+// Attribute to store locations for an optional OpenACC loop directive and one
+// or more loops
+def OpenACC_LoopLocAttr : OpenACC_Attr<"LoopLoc", "loop_loc"> {
+ let summary = "Stores the OpenACC loop directive and per-loop source locations";
+ let parameters = (ins OptionalParameter<"::mlir::LocationAttr">:$directive,
+ ArrayRefParameter<"::mlir::LocationAttr">:$loops);
+ let assemblyFormat = "`<` struct(params) `>`";
+}
+
// Device type enumeration.
def OpenACC_DeviceTypeNone : I32EnumAttrCase<"None", 0, "none">;
def OpenACC_DeviceTypeStar : I32EnumAttrCase<"Star", 1, "star">;
More information about the flang-commits
mailing list