[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