Repository navigation
Conversation
3964207 to
e38779f
Compare
- Rebuilds each location as its typed subclass and checks it with isinstance, since the bindings no longer have Location.is_a_callsite() and friends, and the locations an MLIRError carries come back as plain Location. - Drops the catch-all exception handlers in location_chain and diag_record_from_diagnostic, which hid the missing methods by resolving every location to no frames. - Builds pass-pipeline error records from the MLIRError's own diagnostics, since PassManager.run captures errors before any context handler sees them, in one helper shared by the pipeline and the IR-dump stage loop. - Keeps each error's MLIR notes, such as "see current operation", on one line, leaving out the body of any region they print. - Re-parses the module with its source locations before the pass pipeline, so pass diagnostics point at user code; locations only become DWARF when the debug-info pass runs. - Covers typed, synthetic and unknown locations, a real verifier failure, a real pass-pipeline failure, a kernel that fails LLVM translation, and the locations the first pass sees without debug info. Without this, no DSLCompileError showed a source line: verifier errors lost their locations in the bindings, pass errors never reached the records, and the pipeline ran on IR whose locations pointed into its own printed text.
e38779f to
8e3df81
Compare
FlyDSL PR #1337 — [Bugfix] Show the user's source line in DSL compile errorsMakes Review (advisory): ✅ NO FINDINGS above note level (two 📝 notes below) 📝 [inferred] The "7.4 ms (2%) median per kernel over 291 kernels on MI355X" compile-time figure in the PR body cannot be traced to a log or script in the PR, and Independent reader's corrections (not yet applied to the findings above):
Advisory review by the review-pr skill with Claude-Sonnet-5.5, requested by @coderfeli with the |
Summary
DSLCompileErrornow points at the user's source line, for verifier errors and for errors from the pass pipeline. Generated code is unchanged: this only affects error messages, plus source locations in IR dumps. On main it never does. For a kernel that builds an invalidarith.addi, main prints only the MLIR message:With this PR it also prints the MLIR note and DSL traceback:
Ops built by
fx.*primitives always carry the line that called them. A rawir.Operation.create, as here, gets its own line only withFLYDSL_DEBUG_ENABLE_DEBUG_INFO=1. Otherwise the traceback points at the@flyc.kernelline.Motivation
Three things lose the location:
location_chainusesLocation.is_a_callsite()and similar methods, which the MLIR Python bindings removed in favor of typed subclasses (CallSiteLoc, ...). A catch-allexcepthid the error, so every location resolved to no frames. Verifier errors also hold plainir.Locations, which match no subclass.PassManager.runcollects pass-pipeline errors into itsMLIRErrorbefore FlyDSL's diagnostic handler sees them, so those errors produce no records.loc("-":N:M).Changes
location_chainrebuilds each location as its typed subclass (Location.from_attr) and no longer swallows exceptions.MLIRError's diagnostics, in one helper used by both the pipeline and theFLYDSL_DUMP_IRstage loop.gpu.module, say) leaves out the body.Out of scope
With
FLYDSL_COMPILE_LLVM_DIR(external codegen), theverify()after codegen still raises a bareMLIRError. It checks the module after thegpu.modulehas been replaced by its binary, so a failure there comes from FlyDSL or the external tool, not from user code, and there's no user source line to point at.Performance
Compile time grows slightly, because the passes now carry source locations. Timing
MlirCompiler.compilefor each of the 273 kernels oftests/kernels/test_flash_attn_fwd.pyon MI355X, best of two runs on each side, the median compile goes from 260.9 to 268.9 ms; the median paired difference is 7.2 ms (2.5%). The cost scales with the amount of IR, so a small kernel shows no measurable difference. Generated code is unchanged.Testing
Unit tests added/updated:
tests/unit/test_diagnostics.py: call-site, name and fused locations resolve to frames, synthetic and unknown ones to none; a real verifier failure keeps its source chain.tests/unit/test_compile_error_locations.py: a pass-pipeline failure keeps its source chain; a kernel that fails LLVM translation raises aDSLCompileErrorpointing at its file; without debug info, the IR the first pass sees still has user locations.On main, every new test fails except the two that check skipped locations.
Full
scripts/run_tests.shset on MI355X.Compile time measured as above
Tested on MI355X and cross-compiled for gfx942
Dependencies
Breaking Changes
None.