[Mlir-commits] [mlir] [mlir][OpenACC] Avoid repeated symbol-table scans in routine binding (PR #232592)

Sohail Sarkar llvmlistbot at llvm.org
Thu Oct 15 21:46:28 PDT 2026


https://github.com/n33levo updated https://github.com/llvm/llvm-project/pull/232592

>From 32ed0266b6e6a4c144cf119acb6fa0153ddf6a8d Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:50:13 -0400
Subject: [PATCH 01/10] [mlir][OpenACC] Test repeated string-bound routine
 calls

---
 .../Dialect/OpenACC/acc-bind-routine.mlir     | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
index edee698459449d..ee370ef8daf100 100644
--- a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
+++ b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
@@ -149,3 +149,26 @@ module {
 // CHECK-LABEL: gpu.func @caller
 // CHECK: func.call @actual_local() : () -> ()
 // CHECK: func.func private @actual_local()
+
+// -----
+
+// Repeated lookups must see declarations inserted into the cached table.
+module {
+  acc.routine @r_repeated func(@wrapped_repeated) seq bind("new_target")
+  func.func private @wrapped_repeated()
+      attributes {acc.routine_info = #acc.routine_info<[@r_repeated]>}
+  func.func @repeat() {
+    acc.serial {
+      func.call @wrapped_repeated() : () -> ()
+      func.call @wrapped_repeated() : () -> ()
+      func.call @wrapped_repeated() : () -> ()
+      acc.yield
+    }
+    return
+  }
+}
+
+// CHECK-LABEL: func.func @repeat()
+// CHECK-COUNT-3: func.call @new_target() : () -> ()
+// CHECK: func.func private @new_target()
+// CHECK-NOT: func.func private @new_target

>From e54673934e0241b43f50bb3ea6b86d65e1756ebb Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:50:56 -0400
Subject: [PATCH 02/10] [mlir][OpenACC] Test routine binding in separate GPU
 symbol tables

---
 .../Dialect/OpenACC/acc-bind-routine.mlir     | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
index ee370ef8daf100..e0089f48178250 100644
--- a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
+++ b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
@@ -172,3 +172,41 @@ module {
 // CHECK-COUNT-3: func.call @new_target() : () -> ()
 // CHECK: func.func private @new_target()
 // CHECK-NOT: func.func private @new_target
+
+// -----
+
+// Identical routine and wrapper names in separate GPU symbol tables must
+// resolve independently, including after inserting each string-bound target.
+module {
+  gpu.module @first_scope {
+    acc.routine @r func(@wrapped) seq bind("first_target")
+    func.func private @wrapped()
+        attributes {acc.routine_info = #acc.routine_info<[@r]>}
+    gpu.func @caller() {
+      func.call @wrapped() : () -> ()
+      func.call @wrapped() : () -> ()
+      gpu.return
+    }
+  }
+  gpu.module @second_scope {
+    acc.routine @r func(@wrapped) seq bind("second_target")
+    func.func private @wrapped()
+        attributes {acc.routine_info = #acc.routine_info<[@r]>}
+    gpu.func @caller() {
+      func.call @wrapped() : () -> ()
+      func.call @wrapped() : () -> ()
+      gpu.return
+    }
+  }
+}
+
+// CHECK-LABEL: gpu.module @first_scope
+// CHECK-LABEL: gpu.func @caller
+// CHECK-COUNT-2: func.call @first_target() : () -> ()
+// CHECK: func.func private @first_target()
+// CHECK-NOT: func.func private @first_target
+// CHECK-LABEL: gpu.module @second_scope
+// CHECK-LABEL: gpu.func @caller
+// CHECK-COUNT-2: func.call @second_target() : () -> ()
+// CHECK: func.func private @second_target()
+// CHECK-NOT: func.func private @second_target

>From 9e73329891dfcca65f960f25834e2af29d4ef43c Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:51:12 -0400
Subject: [PATCH 03/10] [mlir][OpenACC] Test reuse of existing string-bound
 targets

---
 .../Dialect/OpenACC/acc-bind-routine.mlir     | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
index e0089f48178250..746674d9119736 100644
--- a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
+++ b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
@@ -210,3 +210,25 @@ module {
 // CHECK-COUNT-2: func.call @second_target() : () -> ()
 // CHECK: func.func private @second_target()
 // CHECK-NOT: func.func private @second_target
+
+// -----
+
+// Existing string-bound targets are reused, not renamed or redeclared.
+module {
+  acc.routine @r_existing func(@wrapped_existing) seq bind("existing_target")
+  func.func private @wrapped_existing()
+      attributes {acc.routine_info = #acc.routine_info<[@r_existing]>}
+  func.func private @existing_target()
+  func.func @reuse_existing() {
+    acc.serial {
+      func.call @wrapped_existing() : () -> ()
+      acc.yield
+    }
+    return
+  }
+}
+
+// CHECK: func.func private @existing_target()
+// CHECK-LABEL: func.func @reuse_existing()
+// CHECK: func.call @existing_target() : () -> ()
+// CHECK-NOT: func.func private @existing_target

>From 415999264bef44ffba0a130076efca1323048dab Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:51:37 -0400
Subject: [PATCH 04/10] [mlir][OpenACC] Test local routine bindings shadowing
 outer symbols

---
 .../Dialect/OpenACC/acc-bind-routine.mlir     | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
index 746674d9119736..5b72930288c025 100644
--- a/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
+++ b/mlir/test/Dialect/OpenACC/acc-bind-routine.mlir
@@ -232,3 +232,28 @@ module {
 // CHECK-LABEL: func.func @reuse_existing()
 // CHECK: func.call @existing_target() : () -> ()
 // CHECK-NOT: func.func private @existing_target
+
+// -----
+
+// A GPU-local routine must take precedence over an identically named outer
+// routine when looking up both the callee and its routine metadata.
+module {
+  acc.routine @r_shadow func(@wrapped_shadow) seq bind("outer_target")
+  func.func private @wrapped_shadow()
+      attributes {acc.routine_info = #acc.routine_info<[@r_shadow]>}
+  gpu.module @shadowed_scope {
+    acc.routine @r_shadow func(@wrapped_shadow) seq bind("inner_target")
+    func.func private @wrapped_shadow()
+        attributes {acc.routine_info = #acc.routine_info<[@r_shadow]>}
+    gpu.func @caller() {
+      func.call @wrapped_shadow() : () -> ()
+      gpu.return
+    }
+  }
+}
+
+// CHECK-LABEL: gpu.module @shadowed_scope
+// CHECK-LABEL: gpu.func @caller
+// CHECK: func.call @inner_target() : () -> ()
+// CHECK: func.func private @inner_target()
+// CHECK-NOT: func.func private @outer_target

>From bf1dee50f814898a9386c67a1866b81d376d04a3 Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:52:06 -0400
Subject: [PATCH 05/10] [mlir][OpenACC] Cache callee resolution in routine
 binding

---
 mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
index 7aace49e4e7ac1..07ef064f88926e 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
@@ -187,6 +187,7 @@ class ACCBindRoutine : public acc::impl::ACCBindRoutineBase<ACCBindRoutine> {
     OpenACCSupport &accSupport =
         cachedAnalysis ? cachedAnalysis->get() : getAnalysis<OpenACCSupport>();
     SymbolTable outerSymTab(module);
+    SymbolTableCollection symbolTables;
     bool failed = false;
 
     func.walk([&](CallOpInterface callOp) {
@@ -200,11 +201,11 @@ class ACCBindRoutine : public acc::impl::ACCBindRoutineBase<ACCBindRoutine> {
       if (!calleeSymbolRef)
         return;
       FunctionOpInterface callee =
-          SymbolTable::lookupNearestSymbolFrom<FunctionOpInterface>(
+          symbolTables.lookupNearestSymbolFrom<FunctionOpInterface>(
               callOp, calleeSymbolRef);
       if (!callee)
-        callee = outerSymTab.lookup<FunctionOpInterface>(
-            calleeSymbolRef.getLeafReference());
+        callee = symbolTables.lookupSymbolIn<FunctionOpInterface>(
+            module, calleeSymbolRef.getLeafReference());
       if (!callee)
         return;
 

>From 87bc20249b7a9a4a0146f94f511b30fbe7f0b382 Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:52:31 -0400
Subject: [PATCH 06/10] [mlir][OpenACC] Reuse cached tables for string-bound
 targets

---
 mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
index 07ef064f88926e..20387407e845dd 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
@@ -239,8 +239,7 @@ class ACCBindRoutine : public acc::impl::ACCBindRoutineBase<ACCBindRoutine> {
         auto gpuMod = func->getParentOfType<gpu::GPUModuleOp>();
         Operation *symbolTableOp =
             gpuMod ? gpuMod.getOperation() : module.getOperation();
-        SymbolTable symbolTable(symbolTableOp);
-        if (!symbolTable.lookup(bindName)) {
+        if (!symbolTables.getSymbolTable(symbolTableOp).lookup(bindName)) {
           callOp.emitError(
               "string-bound ACC routine target was not materialized");
           failed = true;

>From 3521f46d28caa19987b1a6366e48df4000b5ac77 Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:53:26 -0400
Subject: [PATCH 07/10] [mlir][OpenACC] Cache the routine target insertion
 table

---
 mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
index 20387407e845dd..8e4467336960c6 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
@@ -113,7 +113,8 @@ class ACCMaterializeRoutineBindTargets
     }
 
     SymbolTable outerSymTab(mod);
-    SymbolTable insertSymTab(symbolTableOp);
+    SymbolTableCollection symbolTables;
+    SymbolTable &insertSymTab = symbolTables.getSymbolTable(symbolTableOp);
     Block *insertBlock = &symbolTableOp->getRegion(0).front();
 
     symbolTableOp->walk<WalkOrder::PreOrder>([&](Operation *op) {

>From a1f366b3485e10bd0afcd125102014bb690a5572 Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:54:03 -0400
Subject: [PATCH 08/10] [mlir][OpenACC] Cache callee resolution during
 materialization

---
 mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
index 8e4467336960c6..123ffc1e0f668d 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
@@ -133,11 +133,11 @@ class ACCMaterializeRoutineBindTargets
       if (!calleeSymbolRef)
         return WalkResult::advance();
       FunctionOpInterface callee =
-          SymbolTable::lookupNearestSymbolFrom<FunctionOpInterface>(
+          symbolTables.lookupNearestSymbolFrom<FunctionOpInterface>(
               callOp, calleeSymbolRef);
       if (!callee)
-        callee = outerSymTab.lookup<FunctionOpInterface>(
-            calleeSymbolRef.getLeafReference());
+        callee = symbolTables.lookupSymbolIn<FunctionOpInterface>(
+            mod, calleeSymbolRef.getLeafReference());
       if (!callee || !(isAccRoutine(callee) || isSpecializedAccRoutine(callee)))
         return WalkResult::advance();
 

>From 1e3592b83bcd0bf3b0aea87139ed0354f59cd15a Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:54:35 -0400
Subject: [PATCH 09/10] [mlir][OpenACC] Cache nearest routine symbol resolution

---
 .../lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
index 123ffc1e0f668d..d23ece6c615ba7 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
@@ -54,7 +54,8 @@ using namespace mlir::acc;
 namespace {
 
 static RoutineOp getFirstAccRoutineOp(FunctionOpInterface funcOp,
-                                      const SymbolTable &fallbackSymTab) {
+                                      const SymbolTable &fallbackSymTab,
+                                      SymbolTableCollection &symbolTables) {
   SymbolRefAttr routineRef;
   if (isSpecializedAccRoutine(funcOp)) {
     auto attr = funcOp->getDiscardableAttrOfType<SpecializedRoutineAttr>(
@@ -70,7 +71,7 @@ static RoutineOp getFirstAccRoutineOp(FunctionOpInterface funcOp,
   }
 
   RoutineOp routine =
-      SymbolTable::lookupNearestSymbolFrom<RoutineOp>(funcOp, routineRef);
+      symbolTables.lookupNearestSymbolFrom<RoutineOp>(funcOp, routineRef);
   if (routine)
     return routine;
   return fallbackSymTab.lookup<RoutineOp>(routineRef.getLeafReference());
@@ -146,7 +147,8 @@ class ACCMaterializeRoutineBindTargets
         if (routineInfo.getAccRoutines().size() > 1)
           return WalkResult::advance();
 
-      RoutineOp routine = getFirstAccRoutineOp(callee, outerSymTab);
+      RoutineOp routine =
+          getFirstAccRoutineOp(callee, outerSymTab, symbolTables);
       if (!routine ||
           !isACCRoutineBindDefaultOrDeviceType(routine, this->deviceType))
         return WalkResult::advance();
@@ -222,7 +224,8 @@ class ACCBindRoutine : public acc::impl::ACCBindRoutineBase<ACCBindRoutine> {
         }
       }
 
-      RoutineOp routine = getFirstAccRoutineOp(callee, outerSymTab);
+      RoutineOp routine =
+          getFirstAccRoutineOp(callee, outerSymTab, symbolTables);
       if (!routine ||
           !isACCRoutineBindDefaultOrDeviceType(routine, this->deviceType))
         return;

>From be01653f467ee5da310ac021dacd99eb7320d0a7 Mon Sep 17 00:00:00 2001
From: n33levo <n33levo at users.noreply.github.com>
Date: Thu, 15 Oct 2026 23:55:13 -0400
Subject: [PATCH 10/10] [mlir][OpenACC] Reuse cached tables for outer routine
 fallback

---
 .../Dialect/OpenACC/Transforms/ACCBindRoutine.cpp  | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
index d23ece6c615ba7..5e6dd0b776653d 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCBindRoutine.cpp
@@ -52,9 +52,8 @@ using namespace mlir;
 using namespace mlir::acc;
 
 namespace {
-
 static RoutineOp getFirstAccRoutineOp(FunctionOpInterface funcOp,
-                                      const SymbolTable &fallbackSymTab,
+                                      ModuleOp module,
                                       SymbolTableCollection &symbolTables) {
   SymbolRefAttr routineRef;
   if (isSpecializedAccRoutine(funcOp)) {
@@ -74,7 +73,8 @@ static RoutineOp getFirstAccRoutineOp(FunctionOpInterface funcOp,
       symbolTables.lookupNearestSymbolFrom<RoutineOp>(funcOp, routineRef);
   if (routine)
     return routine;
-  return fallbackSymTab.lookup<RoutineOp>(routineRef.getLeafReference());
+  return symbolTables.lookupSymbolIn<RoutineOp>(module,
+                                                routineRef.getLeafReference());
 }
 
 static bool isACCRoutineBindDefaultOrDeviceType(RoutineOp op,
@@ -113,7 +113,6 @@ class ACCMaterializeRoutineBindTargets
       return;
     }
 
-    SymbolTable outerSymTab(mod);
     SymbolTableCollection symbolTables;
     SymbolTable &insertSymTab = symbolTables.getSymbolTable(symbolTableOp);
     Block *insertBlock = &symbolTableOp->getRegion(0).front();
@@ -147,8 +146,7 @@ class ACCMaterializeRoutineBindTargets
         if (routineInfo.getAccRoutines().size() > 1)
           return WalkResult::advance();
 
-      RoutineOp routine =
-          getFirstAccRoutineOp(callee, outerSymTab, symbolTables);
+      RoutineOp routine = getFirstAccRoutineOp(callee, mod, symbolTables);
       if (!routine ||
           !isACCRoutineBindDefaultOrDeviceType(routine, this->deviceType))
         return WalkResult::advance();
@@ -189,7 +187,6 @@ class ACCBindRoutine : public acc::impl::ACCBindRoutineBase<ACCBindRoutine> {
         getCachedParentAnalysis<OpenACCSupport>(func->getParentOp());
     OpenACCSupport &accSupport =
         cachedAnalysis ? cachedAnalysis->get() : getAnalysis<OpenACCSupport>();
-    SymbolTable outerSymTab(module);
     SymbolTableCollection symbolTables;
     bool failed = false;
 
@@ -224,8 +221,7 @@ class ACCBindRoutine : public acc::impl::ACCBindRoutineBase<ACCBindRoutine> {
         }
       }
 
-      RoutineOp routine =
-          getFirstAccRoutineOp(callee, outerSymTab, symbolTables);
+      RoutineOp routine = getFirstAccRoutineOp(callee, module, symbolTables);
       if (!routine ||
           !isACCRoutineBindDefaultOrDeviceType(routine, this->deviceType))
         return;



More information about the Mlir-commits mailing list