debug-compilation
Skill1.1k starsChanged 9 days agoApache-2.0View on GitHub
Use when an onnx-mlir compile fails, produces wrong results, or runs slowly: pick the right --Emit* stage, dump and isolate IR per pass (onnx-mlir-print.sh, IsolatePass.py), compare against onnxruntime, profile with instrumentation, and check NNPA offload.
1 other project uses a version of this.
Trending
Quiet since December.about the whole repository
Most recently taken up by
- torch-spyre/torch-spyretheir own version, first seen Oct 8, 2026
Who's talking about onnx/onnx-mlir
- elixir-nx/nx“Import of MLIR modules”GitHub · Mar 5, 2024 · 4 reactions
- PyTorchKR/pytorchcore-kr“더 나은 질의 응답 구조를 위한 Discussion 활용 방안”GitHub · Jan 20, 2025 · 2 reactions
- llvm/torch-mlir“[RFC] Support for an embedded build of Torch-MLIR”GitHub · Sep 23, 2022 · 2 reactions
- Samsung/ONE“[circle-mlir] Update onnx-mlir to official release”GitHub · Jun 8, 2025 · 1 reactions
- Xilinx/onnx-mlir“ONNX to TOSA Legalization Upstream tracker”GitHub · Apr 20, 2023 · 1 reactions
The biggest 5 of 22 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 22
Talked about on GitHub (22 times).
On GitHub · 22
- Mar 5, 2024Import of MLIR modules — elixir-nx/nx4 reactions · 2 comments
- Jan 20, 2025더 나은 질의 응답 구조를 위한 Discussion 활용 방안 — PyTorchKR/pytorchcore-kr2 reactions
- Sep 23, 2022[RFC] Support for an embedded build of Torch-MLIR — llvm/torch-mlir2 reactions · 4 comments
- Jun 8, 2025[circle-mlir] Update onnx-mlir to official release — Samsung/ONE1 reaction · 4 comments
- Apr 20, 2023ONNX to TOSA Legalization Upstream tracker — Xilinx/onnx-mlir1 reaction
17 more on GitHub
- Dec 16, 2025[ttl] Automate elementwise op generation from specifications — tenstorrent/tt-lang0 reactions · 1 comment
- Jul 29, 2025Missing Symbols due to visibility setting change — onnx/onnx0 reactions · 2 comments
- Nov 19, 2024Add fancier CI badges showing number of tests and/or test coverage — iree-org/iree-test-suites0 reactions · 2 comments
- Aug 6, 2024Standardize rewriter tests; testing facilities — microsoft/onnxscriptsays it tested it0 reactions · 1 comment
- May 8, 2024Fix macos build by pinning version — Xilinx/onnx-mlir0 reactions
- Mar 30, 2024Include the ".onnxtext" extension in supported serialization format — onnx/onnx0 reactions · 1 comment
- Dec 20, 2023add filecheck test for add.onnx — xdslproject/xdsl0 reactions · 7 comments
- Dec 1, 2023Failed to build with the use of --cpp-implementation — protocolbuffers/protobuf0 reactions
- Oct 27, 2023Bring in the fix for empty slice in canonicalization — Xilinx/onnx-mlir0 reactions
- Oct 25, 2023Cherry-picked upstream PR: Add conversion for DivOp ONNX to TOSA (#2207) — Xilinx/onnx-mlir0 reactions
- Aug 26, 2023Build error on M1 MacOS machine — onnx/onnx0 reactions · 3 comments
- Oct 18, 2022ONNX MLIR exporter — nod-ai/onnx-mlir-exporter0 reactions · 1 comment
- Oct 9, 2022[Feature request] Machine Readable definition of Operations (Schema file instead of Markdown or cc file) — onnx/onnx0 reactions · 14 comments
- Jun 28, 2022Can we have newer opset of bidaf-9 model (including opset 9 or newer onnx.Scan op)? — onnx/models0 reactions · 1 comment
- Jun 5, 2022Broken Links — onnx/onnx.github.io0 reactions · 3 comments
- May 12, 2022Update the onnx-mlir version — DependableSystemsLab/LLTFI0 reactions · 2 comments
- Jun 30, 2020Error when trying to lower alex net onnx model to MLIR — onnx/models0 reactions · 1 comment
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- torch-spyre/torch-spyre★ 64same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository14 other files it gives its agents.
- AGENTS.mdAGENTS.md
- add-fusion-patternSkill
- add-new-onnx-operationSkill
- add-onnx-op-loweringSkill
- add-onnx-op-to-dialectSkill
- add-onnx-transform-passSkill
- coding-conventionsSkill
- debug-type-catalogueSkill
- ground-lit-testsSkill
- nnpa-internalsSkill
- nnpa-performanceSkill
- onnx-mlir-internalsSkill
- upgrade-llvm-mlirSkill
- using-torch-onnxmlir-with-huggingfaceSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Run with the default target first:
- Very specific: line 87
When it's unclear which of the *many* passes between two emission stages caused a regression, utils/onnx-mlir-print.sh runs a normal …
- Very specific: line 123
Check if --disable-simd fixes it (SIMD vectorization bug)
- Distinctive: line 157
Use the runtime route below when you need the *cost* of what fell back rather than the fact of it — it measures per-op time, which the …
- Very specific: line 184
If the compiled model crashes, hangs, or you suspect a leak/buffer-overrun/use-after-free, don't debug it inside a full test harness — …
- Very specific: line 206
How to test: Run any .onnx model through each step.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- Generated from the onnx-mlir knowledge base (skills/debug-compilation.md), verified against onnx-mlir@b505d64b. Do not edit here: see .agents/skills/README.md. -->Debug an onnx-mlir Compilation
Step-by-step walkthrough for diagnosing onnx-mlir compilation failures and performance issues using the built-in emission and instrumentation tools. docs/DebuggingNumericalError.md is onnx-mlir's own, more official version of much of this walkthrough (comparing against a reference, comparing two compile options, pass-by-pass IR inspection, printing values at runtime, and — not otherwise covered on this page — finding memory errors and crashes) — treat it as the primary source and this page as a companion index into it.
Step 1: Identify the failure mode
Run with the default target first:
onnx-mlir mymodel.onnx -o mymodel 2>&1Common failure categories:
- Import error: malformed protobuf, unsupported opset version → fix the model or update opset support
- Shape inference failure:
assertorerror: operation has unresolved type→ Step 2 - Lowering failure:
error: failed to legalize operation 'onnx.SomeOp'→ missing lowering - Compile crash: segfault or ICE → Step 3
- Wrong results: compiles fine but outputs are incorrect → Step 4
- Inputs rejected at run time: the model returns
NULL(errnoEINVAL) after printing e.g.Wrong rank for the input 1: expect 2, but got 3orInconsistent dimension for symbol 'batch_size' at dimension 0 of input 1: expect 4, but got 8→ the inputs do not match the model's signature, including inputs that must agree on a shared symbolic dimension. Print the signature withinspect-so mymodel.soand see stack/runtime.md
Step 2: Inspect the ONNX dialect IR
onnx-mlir --EmitONNXBasic mymodel.onnx 2>&1 | less # before shape inference
onnx-mlir --EmitONNXIR mymodel.onnx 2>&1 | less # after graph transformsLook for:
tensor<*xf32>— unranked tensors that shape inference failed to resolvetensor<?xNxM xf32>— check if the?is expected or a bugonnx.Custom— op type not in the dialect's dispatch table (not a nonexistentonnx.UnknownOp)- Missing ops entirely — may be inside a subgraph that wasn't visited
To run only shape inference:
onnx-mlir-opt --shape-inference mymodel.mlir # (first emit with --EmitONNXBasic)Step 3: Narrow to a single pass
Emit at each stage to find where the error occurs:
onnx-mlir --EmitONNXBasic mymodel.onnx -o /tmp/stage1 # import only
onnx-mlir --EmitONNXIR mymodel.onnx -o /tmp/stage2 # + graph transforms
onnx-mlir --EmitMLIR mymodel.onnx -o /tmp/stage3 # + krnl lowering
onnx-mlir --EmitLLVMIR mymodel.onnx -o /tmp/stage4 # + llvm loweringThe stage that fails first contains the buggy pass. Then run individual passes with onnx-mlir-opt:
# Test a single pass
onnx-mlir-opt --constprop-onnx /tmp/stage1.mlir
onnx-mlir-opt --shape-inference /tmp/stage1.mlir
onnx-mlir-opt --convert-onnx-to-krnl /tmp/stage2.mlir
onnx-mlir-opt --convert-krnl-to-affine /tmp/stage3.mlirGetting a pass's internal reasoning with LLVM_DEBUG
If narrowing to a stage isn't enough — you know which pass is misbehaving but not why — most passes (onnx-mlir's own Krnl/ONNX transforms, and the underlying LLVM/MLIR infrastructure alike) wrap internal trace output in LLVM_DEBUG(...), gated by a #define DEBUG_TYPE "<name>" near the top of that pass's source file. Running the compiled onnx-mlir (or onnx-mlir-opt) with -debug-only=<name> prints just that pass's own reasoning — usually far more targeted than reading a generic --EmitONNXIR/--EmitMLIR dump line by line:
onnx-mlir -debug-only=lowering-to-krnl mymodel.onnx 2>&1 | lessSee skills/debug-type-catalogue.md for the full lookup table of every DEBUG_TYPE string in src/ to the pass it belongs to and what its trace output actually shows — including which strings are shared stage-wide across many files versus scoped to one narrow pass, and one pair of near-identical strings (dialect-builder/dialect_builder) that are easy to confuse. That page's "two-tool combo" section also spells out how to pair this with the dump-everything-then-isolate workflow below: the -debug-only trace tells you why, IsolatePass.py shows you what changed.
This convention isn't specific to onnx-mlir — it applies equally to llvm-project/mlir/lib/ passes, since DEBUG_TYPE/LLVM_DEBUG is an LLVM-wide idiom.
Not sure which pass introduced the bug: dump every pass, then isolate one
When it's unclear which of the many passes between two emission stages caused a regression, utils/onnx-mlir-print.sh runs a normal onnx-mlir invocation and dumps the IR after every pass into one log file. It takes the same arguments as onnx-mlir, plus a trailing output-file argument:
onnx-mlir-print.sh <normal onnx-mlir args...> /tmp/all-passes.logUnder the hood it adds --mlir-print-ir-after-all --mlir-print-ir-after-change and delegates to utils/onnx-mlir-truncate.py. Because of --mlir-print-ir-after-change, only passes that actually modified the IR appear in the log. The script's own header comment still says that flag is not added by default, but the command line adds it. onnx-mlir-truncate.py adds --mlir-elide-elementsattrs-if-larger=20 and --mlir-elide-resource-strings-if-larger=20, writes the command line at the top of the log, and cleans each line with clean_line() from utils/mlir_log_utils.py. It does not cut lines at a fixed length. Instead it rewrites the unparseable dense<__elided__> marker as dense_resource<__elided__> and replaces any quoted string longer than 300 characters (e.g. an llvm.mlir.global byte dump) with a short placeholder, so individual IR listings stay parseable.
Then utils/IsolatePass.py extracts one pass's IR back out of that log:
IsolatePass.py -i /tmp/all-passes.log -l # list every pass name in the log (default when -p/-n omitted)
IsolatePass.py -i /tmp/all-passes.log -p <regex> # isolate pass(es) whose name matches regex
IsolatePass.py -i /tmp/all-passes.log -n <num> # isolate the num'th pass
IsolatePass.py -i /tmp/all-passes.log -p <regex> -a <N> # isolate N passes after the match (N may be negative)-c/--comments additionally annotates the extracted listing with per-value use-counts and scalar constant values, and -w/--wrap splits long function signatures, ops and returns across several indented lines.
Typical flow: dump everything with onnx-mlir-print.sh, skim with -l to spot where the IR looks wrong, then isolate that pass (and the one immediately before it, via -a -1) to diff before/after in isolation.
Step 4: Verify correctness against onnxruntime
python3 utils/RunONNXModel.py \
--model mymodel.onnx \
--verify onnxruntime --verify-every-value \
--rtol=1e-3 --atol=1e-5 \
2>&1If outputs differ:
- Try
--O0to disable optimizations and see if that changes the result - Narrow to the offending op with instrumentation (Step 5)
- Check if
--disable-simdfixes it (SIMD vectorization bug)
Step 5: Profile op-level performance
onnx-mlir emits a shared library, not an executable, so profiling needs a driver process to load the .so and call it — RunONNXModel.py compiles and runs in one step:
# Compile with profiling instrumentation and run
python3 utils/RunONNXModel.py --model mymodel.onnx \
--compile-args="-O3 --profile-ir=Onnx" > profile.txt
# Find top-10 slowest ops
grep "PERF-REPORT" profile.txt | sort -t, -k5 -rn | head -10--profile-ir=<stage> is the flag to use; it sets the whole --instrument-stage/--instrument-ops/--Instrument* combination, including the correct op pattern for the stage. The raw --instrument-* flags are deprecated for everyday use — see flows/instrumentation-and-profiling.md, which also covers running an already-compiled .so and sending the log to ONNX_MLIR_INSTRUMENT_FILE instead of stdout.
For per-op shape information (e.g. to determine which dimension a Transpose actually permutes, or spot a missing broadcast) rather than timing, use --profile-ir-with-sig and utils/make-report.py instead — see flows/instrumentation-and-profiling.md.
Step 6: Check NNPA offload (if using --maccel=NNPA)
Offload is decided at compile time, so start there — no run needed. Every NNPA compile already prints a fallback summary for nine heavy op types with no flag, and --opt-report=NNPAUnsupportedOps gives the per-op reason:
onnx-mlir -O3 --march=z16 --maccel=NNPA --opt-report=NNPAUnsupportedOps mymodel.onnx \
| grep -E "not accelerated by NNPA|NNPA-UNSUPPORTEDOPS-REPORT"Full walkthrough of the reason categories and the fix for each: nnpa-performance.md.
Use the runtime route below when you need the cost of what fell back rather than the fact of it — it measures per-op time, which the compile-time report cannot:
python3 utils/RunONNXModel.py --model mymodel.onnx \
--compile-args="-O3 --march=z16 --maccel=NNPA --profile-ir=ZHigh" > profile_nnpa.txt
# Count ops on NNPA vs CPU
grep "zhigh\." profile_nnpa.txt | wc -l # NNPA ops
grep "onnx\." profile_nnpa.txt | wc -l # CPU fallback ops--profile-ir=ZHigh instruments onnx.* and zhigh.* together, so one run gives both counts and both timings.
Step 7: Get SIMD/parallel report
onnx-mlir -O3 --opt-report=Simd --opt-report=Parallel mymodel.onnx 2>&1 | grep -E "SIMD|parallel"Without --parallel every op reports "parallelism is disabled". With --parallel, some lowerings collapse several loop levels into one parallel region by default; the report line then says which levels were collapsed. To check whether collapsing changes a result or a timing, compare against a --disable-collapse build, e.g. utils/CheckONNXModel.py --model=mymodel.onnx --compile-args="-O3 --parallel" --ref-compile-args="--disable-collapse" (the reference run adds --disable-collapse; the test run uses the shared args alone). utils/make-report.py -c <compile_log> --stats=par summarizes the report — see flows/instrumentation-and-profiling.md.
Step 8: Find memory errors and crashes
If the compiled model crashes, hangs, or you suspect a leak/buffer-overrun/use-after-free, don't debug it inside a full test harness — build a small, standalone executable and run that under a memory tool instead:
# Static build: model compiled directly into the binary — symbols resolved
# at link time, no dlopen/dlsym indirection, easiest target for a debugger
# or sanitizer.
sh utils/build-run-onnx-lib.sh mymodel.so
<bin-dir>/run-onnx-lib
valgrind --error-exitcode=1 <bin-dir>/run-onnx-lib --shape-info 0:1x10x20 --seed 1 -n 20-n/--iterations re-runs the model in one process — useful for issues that only appear after repeated calls (leaks, state not reset between calls). Full flag reference and the Electric Fence library (for pinpointing buffer overruns/use-after-free specifically) are in stack/tools.md#build-run-onnx-libsh--runonnxlibcpp and docs/DebuggingNumericalError.md's "Finding memory errors and crashes" section.
Related: proving a pass you're writing is correct
This page is for diagnosis — a compile or a result is wrong and you need to find which pass did it. The complementary problem, verification of a pass you are actively writing or changing, is ground-lit-tests.md: establish numerically that the output is right, then freeze it into FileCheck assertions. The -debug-only=<DEBUG_TYPE> and pass-isolation steps above are what you reach for when a grounding run fails and you need to know why.
Verification
- Grounded against:
repo:onnx-mlir@b505d64:docs/Instrumentation.md,repo:onnx-mlir@b505d64:src/Compiler/CompilerOptions.cpp(emission targets,--profile-ir,--opt-report,--parallel,--disable-collapse,--disable-simd); Step 3's dump-and-isolate section, Step 4's--verifychoices, Step 5'sPERF-REPORTcolumn layout and Step 8 re-checked againstrepo:onnx-mlir@b505d64(utils/onnx-mlir-print.sh,utils/onnx-mlir-truncate.py,utils/mlir_log_utils.pyclean_line,utils/IsolatePass.py,utils/RunONNXModel.py,docs/Instrumentation.md,src/Runtime/OMInstrument.c,docs/DebuggingNumericalError.md,utils/build-run-onnx-lib.sh); the run-time input-rejection category (src/Conversion/KrnlToLLVM/KrnlEntryPoint.cpp,docs/InputVerification.md,src/Tools/inspect-so/InspectSo.cpp) and Step 7 (src/Compiler/CompilerOptions.cppdisable-collapse,src/Conversion/ONNXToKrnl/KrnlParallelPlan.cpp,utils/make-report.py) re-checked againstrepo:onnx-mlir@b505d64 - Files read:
docs/Instrumentation.md,CompilerOptions.cpp(emission target enum),docs/TestingHighLevel.md,utils/onnx-mlir-print.sh,utils/onnx-mlir-truncate.py,utils/mlir_log_utils.py,utils/IsolatePass.py(argparse definitions),utils/RunONNXModel.py(--verifychoices), grep for#define DEBUG_TYPEacrosssrc/,docs/DebuggingNumericalError.md(full read, 2026-08-06 sync) - How to test: Run any
.onnxmodel through each step;RunONNXModel.py --verify onnxruntime --verify-every-valueis the correctness gate; for Step 8,valgrind --error-exitcode=1against a known-good model should exit 0
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

