[flang-commits] [flang] f550160 - [flang][OpenACC] Attach `OpenACCLoopLocAttr` to `acc.loop` op (#208238)

via flang-commits flang-commits at lists.llvm.org
Wed Jul 8 13:47:05 PDT 2026


Author: Moazin K.
Date: 2026-07-08T13:47:00-07:00
New Revision: f550160b2d59a780ed86ae2a72cd2e3b8b3a70fa

URL: https://github.com/llvm/llvm-project/commit/f550160b2d59a780ed86ae2a72cd2e3b8b3a70fa
DIFF: https://github.com/llvm/llvm-project/commit/f550160b2d59a780ed86ae2a72cd2e3b8b3a70fa.diff

LOG: [flang][OpenACC] Attach `OpenACCLoopLocAttr` to `acc.loop` op (#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.

Added: 
    

Modified: 
    flang/lib/Lower/OpenACC.cpp
    flang/test/Lower/OpenACC/locations.f90
    mlir/include/mlir/Dialect/OpenACC/OpenACCOps.td

Removed: 
    


################################################################################
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