Repository navigation
Conversation
…lder The compiled race detector needs two pieces that were private to the compiled sanitizer. Move them, unchanged in behaviour, into the shared IR layer: - tilelens/ir/failures.py: what a config's failed host compile means (compiles_nowhere, failure_refusal, nowhere_note, none_compiled, nothing_compiled; the error-chain, summary and kernel-site helpers stay private). The client's own words are parameters: how to name another target, which eager client checks a launch without a JITFunction, and how a config is shown. The sanitizer passes the texts it used before, so every refusal kind, message and note is the same. - tilelens/ir/lowering.py: GuardDag, the Select-arm guard of every term read from a set of roots, its rank, and premise(term, holds), which makes a fact about a term hold only where the term's value reaches a root. The walk's edges are a parameter (default children); the sanitizer passes its own, which stops at a LoopVar, and keeps which obligations are guarded and how a failure is reported.
Performance Benchmark
Threshold: >5% regression flagged with |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The compiled race detector (the next PR) needs two pieces that are private to the compiled sanitizer today: the rules that decide what a failed host compile means for a launch, and the builder that works out under which
tl.wherearms each term of an access is read. This PR moves both into the shared IR layer so the two clients use one copy. It is a move, with no change in behaviour: the sanitizer sends the same Z3 queries and returns the same verdicts, refusals and notes as before (see Behaviour unchanged).Stacked on #515. Triton 3.8 only. One commit.
Change
1.
tilelens/ir/failures.py: the compile-failure classificationThe module-level helpers in
tilelens/clients/sanitizer/compiled/client.pymove here unchanged. The rule they implement stays the same:unsupported, and the program continues;tl.static_assert, a construct the code generator never accepts, from a compile that never asked the driver anything) only adds a note, because the config never launches anywhere;unsupportedwith kindcompile-failed, and the refusal says how to name another target;host-compile-unavailable.Public entry points:
compiles_nowhere(error)_compiles_nowherefailure_refusal(failure, retarget)_failure_refusalnowhere_note(failure, config)_nowhere_notenone_compiled(log)_none_compilednothing_compiled(log, eager_client)_nothing_compiled_error_chain,_summary,_kernel_site,_for_targetand_atstay private to the module.COMPILE_FAILEDandHOST_COMPILE_UNAVAILABLEare the two refusal kinds as plain strings, and the sanitizer'sSanitizerKindmembers of those names now take their values from them.Three pieces of wording belonged to the sanitizer, so they are now parameters, and the sanitizer passes exactly the text it used before:
retarget: how to name another target ("Sanitizer(compile=True, target=...), or TILELENS_IR_TARGET");eager_client: which eager client checks a launch that has no JITFunction ("Sanitizer()");config: how a failed config is shown in a note (the sanitizer's_saveable(failure.config))._describestays in the client. None of the moved helpers uses it, and the client still does for its internal errors.analyze_launchkeeps the loop that turns each failure into a note or aConfigVerdict, because that is the client's verdict policy. Like the othertilelens.irmodules, importingfailures.pydoes not import Triton.2.
GuardDagintilelens/ir/lowering.py: the Select-arm guard builder_Daginoob.pymoves tolowering.pyasGuardDag(roots, graph, cond=None, operands=children):order/rank(term): children before parents, and a Select's condition before its arms. A term the walk does not hold comes right after its children.guards: givencond(the client's lowering of a term to a Bool, e.g.Lowerer.cond), the guard of each term is the condition under which its value reaches a root through Select arms. A term that is read directly, or that is a Select's condition, has no guard.premise(term, holds):Implies(guard, holds), orholdsitself for a term with no guard. This turns a fact about a term, such as a width obligation, into a Select-guarded premise. It is the expression the sanitizer built inline before.It goes into
lowering.pyand not a new module because it is the same kind of code: a walk over the samechildrenrelation, building Z3 conditions from the client's own lowering. It also keeps the module's contract. It is mechanism only, it never creates a Z3 context (its guards are built from whatcondreturns), and it raises only whatchildrenraises for a malformed graph; an exception from the client'scondoroperandspropagates unchanged. The module docstring gains one paragraph on it.What stays in the sanitizer:
_operandsstops at aLoopVar, because the loop's bounds belong to the loop's own checks, and it passes them asoperands;_undefined_when_wide), and divisions are never guarded;Not in this PR
Behaviour unchanged
Each check below compares this PR with a pristine b3c0212 (the head of #515) in its own worktree, with the same Triton 3.8.0 setup.
Compiled sanitizer on the corpus. The same 977 Triton 3.8.0 TTIRs as in [FEAT] Add the race detector's TTIR reader facts #509 and [FEAT] Add the race detector's multipath and loaded-value reader facts #515. Each text is parsed, and every parsed graph goes through
check_graphunder the synthetic binding of [FEAT] Add the race detector's TTIR reader facts #509 (4096-element tensors, scalars 64, grid (4, 2, 1)):Solver.sexpr()at everycheck) are byte for byte the same;(=>in their query sexprs, the same on both sides.Each tree was run five times (once unseeded, then
PYTHONHASHSEED0 to 3), and every field above is identical across all ten runs. One finding's witness changes from run to run, on the base as well as on this PR, from identical queries: thec_ptrstore oftb_matmul_dequantizereports offset 4096 or 8064. In these five runs the base gave 8064 in 2 and this PR in 5; over the twelve runs of each tree made during review, the base gave it in 4 and this PR in 9. Which value comes up does not follow the hash seed (the same seed gave either value in different runs of the same tree). That is Z3's model choice, as in [FEAT] Add the race detector's TTIR reader facts #509 and [FEAT] Add the race detector's multipath and loaded-value reader facts #515. Apart from that one witness (its offset, address and lane values), the full result reprs are identical.Compile-failure classification. One traced launch per failure kind through
Sanitizer(compile=True). Each launch'sIRVerdictrepr is byte-identical between base and this PR:tl.static_assert;num_ctas=2, one fails astatic_assert;num_ctas=2;A function-level matrix also calls the old private helpers on the base and the moved functions on this PR with the same inputs: 18 error shapes (plain errors,
CompilationErrorchains with a cause, a suppressed context and a cycle,static_assertand unsupported constructs with and without a driver query,HostCompileUnavailabledirect and chained, a patched-language error, a call that does not bind, unknown options) for 3 targets, 3 kernels and 3 configs, plusnone_compiledandnothing_compiledover several logs. The 494 output lines are identical once tensor addresses are normalized; they include 410compile-failedand 81host-compile-unavailablerefusals.The existing compile-failure tests in
tests/unit/sanitizer_compiled/test_client.pyandtests/end_to_end/test_compiled_sanitizer.pypass unchanged. The one exception is the test that replacesfailure_refusalwith a broken one: it now patches the new name and signature.Tests
New direct tests for the moved entry points:
tests/unit/ir/test_failures.py(4 tests): an error no target compiles past (compiles_nowhere,nowhere_note,none_compiled); a target-dependent error (failure_refusalnames the client'sretarget); a host compile that could not run (host-compile-unavailable);nothing_compilednames the client's eager client.tests/unit/ir/test_lowering.py(1 test):GuardDagguards terms read through a Select's arms by the arm's condition, and leaves the condition and directly read terms unguarded;premiseandrank; withoutcondthere are no guards.Commands, Triton 3.8.0, CPU only (
CUDA_VISIBLE_DEVICES="",UV_NO_SYNC=1):-n 4-n 4The 5 new rows are the tests above.
Line counts
From
git diff --numstatagainst b3c0212:tilelens/ir/failures.py(new)tilelens/ir/lowering.pytilelens/clients/sanitizer/compiled/client.pytilelens/clients/sanitizer/compiled/oob.pytests/unit/ir/test_failures.py(new)tests/unit/ir/test_lowering.pytests/unit/sanitizer_compiled/test_client.pyMost of the product lines are moved, not new: about 315 lines leave the sanitizer and arrive in
tilelens/ir. The net +66 is the new module's docstring, the two kind constants, the three wording parameters,GuardDag.premisewith theoperandsparameter, and the updated comment on the sanitizer's two kinds. The tests add fewer lines than the product.