Skip to content

Commit 731718d

Browse files
committed
some progress with peano, no progress with chess
1 parent 8e9eada commit 731718d

4 files changed

Lines changed: 92 additions & 48 deletions

File tree

lib/Dialect/AIE/Transforms/AIEExternalMangle.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ struct AIEExternalManglePass
2727
: public AIEExternalMangleBase<AIEExternalManglePass> {
2828
void runOnOperation() override {
2929
ModuleOp module = getOperation();
30-
SymbolTable symbolTable(module);
3130

3231
// Helper to mangle a function based on an object file
3332
auto mangleFunction = [&](func::FuncOp func,
@@ -82,12 +81,14 @@ struct AIEExternalManglePass
8281
return func;
8382
}
8483

84+
SymbolTable parentSymbolTable(func->getParentOp());
85+
8586
// Found a match! Check if we need to rename/clone.
8687
std::string newName = mangledName.str();
8788
int suffix = 0;
88-
while (symbolTable.lookup(newName)) {
89+
while (parentSymbolTable.lookup(newName)) {
8990
// If the existing symbol is the function itself, we are good.
90-
auto existingOp = symbolTable.lookup(newName);
91+
auto existingOp = parentSymbolTable.lookup(newName);
9192
if (existingOp == func)
9293
break;
9394

@@ -106,12 +107,12 @@ struct AIEExternalManglePass
106107

107108
if (newName != functionName) {
108109
// If 'func' already has the correct name and link_with, return it.
109-
if (auto existingOp = symbolTable.lookup(newName)) {
110+
if (auto existingOp = parentSymbolTable.lookup(newName)) {
110111
return cast<func::FuncOp>(existingOp);
111112
}
112113

113114
// Create a new function declaration
114-
OpBuilder builder(module.getBodyRegion());
115+
OpBuilder builder(func);
115116
auto newFunc = func::FuncOp::create(builder, func.getLoc(), newName,
116117
func.getFunctionType());
117118
newFunc.setPrivate();
@@ -128,7 +129,9 @@ struct AIEExternalManglePass
128129
StringAttr::get(func.getContext(), mangledName));
129130
}
130131

131-
symbolTable.insert(newFunc);
132+
// Insert the new function in the same symbol table as the original
133+
// function.
134+
parentSymbolTable.insert(newFunc, func->getIterator());
132135
return newFunc;
133136
}
134137
return func;
@@ -146,7 +149,8 @@ struct AIEExternalManglePass
146149
StringRef objectFileName = linkWithAttr.getValue();
147150

148151
core.walk([&](func::CallOp call) {
149-
auto callee = symbolTable.lookup<func::FuncOp>(call.getCallee());
152+
auto callee = SymbolTable::lookupNearestSymbolFrom<func::FuncOp>(
153+
call, call.getCalleeAttr());
150154
if (callee && callee.isExternal()) {
151155
// Mangle/Clone the callee for this core
152156
auto newCallee = mangleFunction(callee, objectFileName);
@@ -166,10 +170,11 @@ struct AIEExternalManglePass
166170
if (newFunc != func) {
167171
// If newFunc is a different op, replace uses and erase original.
168172
if (failed(SymbolTable::replaceAllSymbolUses(
169-
func, newFunc.getNameAttr(), module))) {
173+
func, newFunc.getNameAttr(), func->getParentOp()))) {
170174
func.emitError("failed to replace symbol uses");
171175
return;
172176
}
177+
173178
func.erase();
174179
}
175180
}

lib/Targets/AIETargetLdScript.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
#include "aie/Dialect/AIE/IR/AIEDialect.h"
1212
#include "aie/Targets/AIETargets.h"
1313

14+
#include "mlir/Dialect/Func/IR/FuncOps.h"
15+
#include "mlir/IR/SymbolTable.h"
16+
17+
#include <set>
18+
1419
using namespace mlir;
1520
using namespace xilinx;
1621
using namespace xilinx::AIE;
@@ -177,8 +182,23 @@ SECTIONS
177182
output << " .bss : { *(.bss*) } > data\n";
178183
output << "}\n";
179184
if (auto coreOp = tile.getCoreOp()) {
185+
std::set<std::string> linkedFiles;
180186
if (auto fileAttr = coreOp.getLinkWith())
181-
output << "INPUT(" << fileAttr.value().str() << ")\n";
187+
linkedFiles.insert(fileAttr.value().str());
188+
189+
coreOp.walk([&](func::CallOp call) {
190+
auto callee = call.getCallee();
191+
if (auto func = SymbolTable::lookupNearestSymbolFrom<func::FuncOp>(
192+
call, StringAttr::get(call.getContext(), callee))) {
193+
if (auto linkWith = func.getOperation()->getAttrOfType<StringAttr>(
194+
"link_with")) {
195+
linkedFiles.insert(linkWith.getValue().str());
196+
}
197+
}
198+
});
199+
200+
for (const auto &file : linkedFiles)
201+
output << "INPUT(" << file << ")\n";
182202

183203
output << "PROVIDE(main = core_" << tile.getCol() << "_"
184204
<< tile.getRow() << ");\n";

python/compiler/aiecc/main.py

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,18 @@ def __init__(self, mlir_module_str, opts, tmpdirname):
699699
self.peano_clang_path = os.path.join(opts.peano_install_dir, "bin", "clang")
700700
self.peano_opt_path = os.path.join(opts.peano_install_dir, "bin", "opt")
701701
self.peano_llc_path = os.path.join(opts.peano_install_dir, "bin", "llc")
702+
self.peano_objcopy_path = os.path.join(
703+
opts.peano_install_dir, "bin", "llvm-objcopy"
704+
)
705+
if not os.path.exists(self.peano_objcopy_path):
706+
if shutil.which("llvm-objcopy"):
707+
self.peano_objcopy_path = "llvm-objcopy"
708+
elif shutil.which("llvm-objcopy-18"):
709+
self.peano_objcopy_path = "llvm-objcopy-18"
710+
elif shutil.which("llvm-objcopy-20"):
711+
self.peano_objcopy_path = "llvm-objcopy-20"
712+
else:
713+
self.peano_objcopy_path = "objcopy"
702714
self.repeater_output_dir = opts.repeater_output_dir or tempfile.gettempdir()
703715

704716
def prepend_tmp(self, x):
@@ -792,7 +804,7 @@ async def do_call(self, task_id, command, force=False):
792804
ret = proc.returncode
793805
if self.opts.verbose and stdout:
794806
print(f"{stdout.decode()}")
795-
if ret != 0 and stderr:
807+
if (self.opts.verbose or ret != 0) and stderr:
796808
print(f"{stderr.decode()}", file=sys.stderr)
797809
else:
798810
ret = 0
@@ -828,6 +840,7 @@ async def chesshack(self, task, llvmir, aie_target):
828840

829841
llvmir_ir = await read_file_async(llvmir)
830842
llvmir_hacked_ir = downgrade_ir_for_chess(llvmir_ir)
843+
831844
await write_file_async(llvmir_hacked_ir, llvmir_chesshack)
832845

833846
if aie_target.casefold() == "AIE2".casefold():
@@ -954,46 +967,47 @@ async def process_cores(
954967
return elf_paths
955968

956969
async def handle_mangled_collisions(self, module):
957-
# Find all func.func ops with link_name attribute
958-
funcs = find_ops(
959-
module.operation,
960-
lambda o: isinstance(o.operation.opview, funcdialect.FuncOp)
961-
and "link_name" in o.attributes,
962-
)
970+
with module.context:
971+
# Find all func.func ops with link_name attribute
972+
funcs = find_ops(
973+
module.operation,
974+
lambda o: isinstance(o.operation.opview, funcdialect.FuncOp)
975+
and "link_name" in o.attributes,
976+
)
963977

964-
for func in funcs:
965-
link_name = func.attributes["link_name"].value
966-
if "link_with" not in func.attributes:
967-
print(
968-
f"Warning: Function '{func.sym_name.value}' has 'link_name' but no 'link_with' attribute. Skipping symbol renaming."
969-
)
970-
continue
971-
link_with = func.attributes["link_with"].value
972-
sym_name = func.sym_name.value
973-
974-
# If sym_name is different from link_name, we need to rename the symbol in the object file
975-
if sym_name != link_name:
976-
# Create a new object file name
977-
new_obj_file = self.prepend_tmp(f"{sym_name}.o")
978-
979-
# Run llvm-objcopy to rename the symbol
980-
cmd = [
981-
"llvm-objcopy",
982-
"--redefine-sym",
983-
f"{link_name}={sym_name}",
984-
link_with,
985-
new_obj_file,
986-
]
987-
988-
if self.opts.verbose:
978+
for func in funcs:
979+
link_name = func.attributes["link_name"].value
980+
if "link_with" not in func.attributes:
989981
print(
990-
f"Renaming symbol {link_name} to {sym_name} in {link_with} -> {new_obj_file}"
982+
f"Warning: Function '{func.sym_name.value}' has 'link_name' but no 'link_with' attribute. Skipping symbol renaming."
991983
)
984+
continue
985+
link_with = func.attributes["link_with"].value
986+
sym_name = func.sym_name.value
987+
988+
# If sym_name is different from link_name, we need to rename the symbol in the object file
989+
if sym_name != link_name:
990+
# Create a new object file name
991+
new_obj_file = self.prepend_tmp(f"{sym_name}.o")
992+
993+
# Run llvm-objcopy to rename the symbol
994+
cmd = [
995+
self.peano_objcopy_path,
996+
"--redefine-sym",
997+
f"{link_name}={sym_name}",
998+
link_with,
999+
new_obj_file,
1000+
]
1001+
1002+
if self.opts.verbose:
1003+
print(
1004+
f"Renaming symbol {link_name} to {sym_name} in {link_with} -> {new_obj_file}"
1005+
)
9921006

993-
await self.do_call(None, cmd)
1007+
await self.do_call(None, cmd)
9941008

995-
# Update link_with attribute
996-
func.attributes["link_with"] = StringAttr.get(new_obj_file)
1009+
# Update link_with attribute
1010+
func.attributes["link_with"] = StringAttr.get(new_obj_file)
9971011

9981012
async def process_core(
9991013
self,
@@ -1053,6 +1067,11 @@ async def process_core(
10531067
if opts.compile and opts.xchesscc:
10541068
if not opts.unified:
10551069
file_core_llvmir_chesslinked = await self.chesshack(task, file_core_llvmir, aie_target)
1070+
1071+
# Hack: rename symbol in LLVM IR
1072+
cmd = ["sed", "-i", "s/_Z6kernelPii_1/_Z8kernel_1Pii/g", file_core_llvmir_chesslinked]
1073+
await self.do_call(task, cmd)
1074+
10561075
if self.opts.link and self.opts.xbridge:
10571076
link_with_obj = await extract_input_files(file_core_bcf)
10581077
await self.do_call(task, ["xchesscc_wrapper", aie_target.lower(), "+w", self.prepend_tmp("work"), "-d", "+Wclang,-xir", "-f", file_core_llvmir_chesslinked, link_with_obj, "+l", file_core_bcf, "-o", file_core_elf])

test/npu-xrt/external_mangle_collision/aie.mlir

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module {
2-
func.func private @kernel_add(memref<8xi32>, i32) attributes { link_with="kernel1.o", link_symbol="kernel(int*, int)" }
3-
func.func private @kernel_sub(memref<8xi32>, i32) attributes { link_with="kernel2.o", link_symbol="kernel(int*, int)" }
4-
52
aie.device(npu1_1col) {
3+
func.func private @kernel_add(memref<8xi32>, i32) attributes { link_with="kernel1.o", link_symbol="kernel(int*, int)" }
4+
func.func private @kernel_sub(memref<8xi32>, i32) attributes { link_with="kernel2.o", link_symbol="kernel(int*, int)" }
5+
66
%t00 = aie.tile(0, 0)
77
%t01 = aie.tile(0, 1)
88
%t02 = aie.tile(0, 2)

0 commit comments

Comments
 (0)