Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions tests/unit/ir/test_failures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""tilelens.ir.failures: what a config's failed host compile means. The
compiled sanitizer's verdicts built on it are pinned in
tests/unit/sanitizer_compiled/test_client.py."""

from __future__ import annotations

import ast
from types import SimpleNamespace

from tilelens.core.host_compile import HostCompileUnavailable
from tilelens.ir.capture import CompileFailure
from tilelens.ir.failures import (
compiles_nowhere,
failure_refusal,
none_compiled,
nothing_compiled,
nowhere_note,
)

HINT = "Client(target=...)"


def _cuda89():
from triton.backends.compiler import GPUTarget

return GPUTarget("cuda", 89, 32)


def test_an_error_no_target_compiles_past_is_a_note():
from triton.compiler.errors import CompilationError, CompileTimeAssertionFailure

error = CompilationError(None, ast.Pass(), None)
error.__cause__ = CompileTimeAssertionFailure(None, ast.Pass(), "BLOCK <= 1024")
failure = CompileFailure(error, {"BLOCK": 2048}, _cuda89())
assert compiles_nowhere(error)
note = nowhere_note(failure, {"BLOCK": 2048})
assert note.startswith("config {'BLOCK': 2048} was not checked: it failed")
assert "for cuda:89 (CompileTimeAssertionFailure: BLOCK <= 1024)" in note
refusal = none_compiled(SimpleNamespace(failures=[failure]))
assert refusal.kind == "compile-failed"
assert "compiled for cuda:89" in refusal.message


def test_an_error_that_may_be_the_targets_names_another_target():
failure = CompileFailure(RuntimeError("no MMA"), {}, _cuda89())
assert not compiles_nowhere(failure.error)
refusal = failure_refusal(failure, HINT)
assert refusal.kind == "compile-failed"
assert "for cuda:89 (RuntimeError: no MMA)" in refusal.message
assert refusal.message.endswith(f"name a target it compiles for ({HINT})")


def test_a_host_compile_that_could_not_run_is_unavailable():
error = HostCompileUnavailable("the installed Triton is 3.9.0")
failure = CompileFailure(error, {}, _cuda89())
assert not compiles_nowhere(error)
refusal = failure_refusal(failure, HINT)
assert refusal.kind == "host-compile-unavailable"
assert refusal.message == "the installed Triton is 3.9.0"


def test_a_launch_without_a_jit_function_names_the_eager_client():
log = SimpleNamespace(call=SimpleNamespace(capture=False))
assert nothing_compiled(log, "Client()").endswith(
"the eager Client() checks such launches"
)
22 changes: 21 additions & 1 deletion tests/unit/ir/test_lowering.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import pytest
import z3

from tilelens.ir.lowering import Lowerer, children, fold
from tilelens.ir.lowering import GuardDag, Lowerer, children, fold
from tilelens.ir.ttir_reader import (
AccessGraph,
Arange,
Expand Down Expand Up @@ -379,3 +379,23 @@ def test_a_loop_term_without_a_loop_is_a_bug(term):
graph = _graph(None, (IterArgInfo(0, "p", Const(0), Const(1)),))
with pytest.raises(ValueError, match="without a loop"):
Lowerer(graph, _Leaves()).lower(term)


def test_guard_dag_guards_the_terms_read_through_select_arms():
"""A term read only through an arm is guarded by the arm's condition;
one also read directly (or the condition itself) is not."""
graph = _graph()
cond, wide, other = Cmp("slt", X, Y), Bin("*", X, Y), Bin("-", Y, X)
root = Bin("+", Select(cond, wide, other), Y)
lowerer = Lowerer(graph, _Leaves())
dag = GuardDag((root,), graph, lowerer.cond)
c = lowerer.cond(cond)
assert _proved(dag.guards[id(wide)] == c)
assert _proved(dag.guards[id(other)] == z3.Not(c))
assert {id(cond), id(X), id(Y)}.isdisjoint(dag.guards)
holds = z3.Bool("holds")
assert _proved(dag.premise(wide, holds) == z3.Implies(c, holds))
assert dag.premise(cond, holds) is holds
assert dag.rank(cond) < dag.rank(wide) < dag.rank(root)
# Without ``cond``: the ranks only.
assert GuardDag((root,), graph).guards == {}
4 changes: 2 additions & 2 deletions tests/unit/sanitizer_compiled/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -877,10 +877,10 @@ def check_graph(graph, binding, **kw):


def test_a_bug_outside_the_configs_is_an_internal_error(quiet, monkeypatch):
def broken(failure):
def broken(failure, retarget):
raise RuntimeError("note bug")

monkeypatch.setattr(client_module, "_failure_refusal", broken)
monkeypatch.setattr(client_module, "failure_refusal", broken)
failure = _failed(ADD, _add_args(), {"BLOCK_SIZE": 2048}, RuntimeError("bad"))
launch = _launch(quiet, compiled=[_oob_event()], failures=[failure])

Expand Down
Loading
Loading