Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ def ROCM_SpectralBackwardKindAttr
: ROCM_EnumStrAttr<["tessera.spectral_filter", "tessera.spectral_conv"],
"ROCm compound spectral backward kind">;
def ROCM_ActivationKindAttr
: ROCM_EnumStrAttr<["gelu", "silu", "relu"], "ROCm activation kind">;
: ROCM_EnumStrAttr<["gelu", "silu", "relu"],
"ROCm activation kind: 'gelu', 'silu', or 'relu'">;
def ROCM_NormKindAttr
: ROCM_EnumStrAttr<["rmsnorm", "layer_norm"], "ROCm normalization kind">;
def ROCM_Int4PackKindAttr
Expand Down
119 changes: 119 additions & 0 deletions tests/_support/apple.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
"""
from __future__ import annotations

import functools
import subprocess
from pathlib import Path

import subprocess
import sys
from typing import Any, Mapping
Expand Down Expand Up @@ -175,3 +179,118 @@ def assert_native_apple_jit(compiled: Any) -> None:
assert getattr(compiled, "execution_kind", None) == "native_gpu"
metadata = compiled.runtime_artifact().metadata
assert metadata.get("execution_mode") == "metal_runtime"


# --- Apple backend compiled into tessera-opt -------------------------------
#
# `tessera-opt` only registers the Apple pipelines when it was configured with
# -DTESSERA_BUILD_APPLE_BACKEND=ON (compile-time `TESSERA_HAVE_APPLE_BACKEND`).
Comment thread
gstoner marked this conversation as resolved.
Resolved
# The ROCm / x86 fleet boxes build it OFF, so on those hosts the Apple tests
# used to FAIL on `Unknown command line argument
# '-tessera-lower-to-apple_cpu-full'` -- 57 red in a full sweep that say nothing
# about Apple and drown out real signal. A capability the host does not have
# must SKIP, not fail (the same rule CLAUDE.md applies to a missing device).
#
# The gate is the existing `tessera-opt not built` guard's missing other half:
# that one asks whether the binary exists, this one asks whether the binary has
# the Apple backend in it.

#: A pipeline registered only under `TESSERA_HAVE_APPLE_BACKEND`. Matched by
#: exact flag name -- a bare "apple" substring would match LLVM's own
#: `=apple` NEON asm flavour in --help and report a false positive.
_APPLE_PROBE_PIPELINE = "tessera-lower-to-apple_cpu"


@functools.cache
def tessera_opt_registers(flag: str) -> bool:
"""True iff this build's ``tessera-opt`` registers ``flag``.

Reads ``--help`` rather than running the pipeline, so the probe cannot be
confused by an unrelated pipeline failure. Returns False (never raises) when
the binary is missing or unrunnable."""
from tests._support.compiler_tool import tessera_opt_path

opt = tessera_opt_path()
if opt is None:
Comment thread
gstoner marked this conversation as resolved.
Resolved
return False
try:
out = subprocess.run([str(opt), "--help"], capture_output=True, text=True, timeout=60)
except (OSError, subprocess.SubprocessError):
return False
return flag in (out.stdout + out.stderr)


def apple_backend_in_tessera_opt() -> bool:
"""True iff ``tessera-opt`` was built with the Apple backend."""
return tessera_opt_registers(_APPLE_PROBE_PIPELINE)


def apple_backend_configured_in_build() -> bool:
"""True iff the build tree's CMake cache says the Apple backend is ON.

Deliberately independent of :func:`apple_backend_in_tessera_opt` -- it reads
the cache, not ``--help`` -- so the two can be cross-checked. A guard that
silently skips a suite it should have run is worse than the loud failure it
replaced, and this is what makes that detectable."""
from tests._support.compiler_tool import tessera_opt_path

opt = tessera_opt_path()
if opt is None:
return False
for parent in Path(opt).resolve().parents:
cache = parent / "CMakeCache.txt"
if cache.is_file():
try:
text = cache.read_text(errors="ignore")
except OSError:
return False
return "TESSERA_BUILD_APPLE_BACKEND:BOOL=ON" in text
return False


def require_apple_backend_in_tessera_opt() -> None:
"""Skip unless ``tessera-opt`` carries the Apple backend."""
import pytest

if not apple_backend_in_tessera_opt():
pytest.skip(
"tessera-opt was built without the Apple backend "
"(configure -DTESSERA_BUILD_APPLE_BACKEND=ON to run these)"
)


def skip_if_apple_pipeline_unregistered(proc: Any) -> None:
"""Skip when ``tessera-opt`` rejected an Apple pipeline it was never built with.

Call right after invoking the pipeline, before asserting on the result.

A build configured with -DTESSERA_BUILD_APPLE_BACKEND=OFF does not register
the Apple pipelines at all, so on the ROCm / x86 boxes these fixtures used to
fail on a missing CLI flag -- 57 red in a full sweep that say nothing about
Apple. A capability the build lacks must skip, not fail.

Deliberately narrow in three ways, so it cannot hide a real defect:
* only fires on the two "this pipeline is not registered" signatures, one
per invocation form (``-flag`` and ``--pass-pipeline=``);
* only when the Apple backend is genuinely absent -- if it IS built, an
unregistered pipeline is a registration regression and stays loud;
* never touches a nonzero exit for any other reason, so the negative
fixtures that expect a rejection still assert their own diagnostics.
"""
import pytest

if getattr(proc, "returncode", 0) == 0:
return
stderr = getattr(proc, "stderr", "") or ""
unregistered = (
"Unknown command line argument" in stderr
or "does not refer to a registered pass or pass pipeline" in stderr
)
if not unregistered:
return
if apple_backend_in_tessera_opt():
return
pytest.skip(
"tessera-opt was built without the Apple backend "
"(configure -DTESSERA_BUILD_APPLE_BACKEND=ON to run this)"
)
2 changes: 2 additions & 0 deletions tests/unit/test_apple_cholesky_seam_closure.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import numpy as np
import pytest
from tests._support.apple import skip_if_apple_pipeline_unregistered

REPO_ROOT = Path(__file__).resolve().parents[2]
_OPT_DEFAULT = REPO_ROOT / "build" / "tools" / "tessera-opt" / "tessera-opt"
Expand Down Expand Up @@ -66,6 +67,7 @@ def _lower(target_pipeline: str) -> str:
proc = subprocess.run(
[_OPT, "-", f"-{target_pipeline}", "--allow-unregistered-dialect"],
input=_TILE_CHOLESKY, capture_output=True, text=True, timeout=60)
skip_if_apple_pipeline_unregistered(proc)
assert proc.returncode == 0, proc.stderr
return proc.stdout

Expand Down
2 changes: 2 additions & 0 deletions tests/unit/test_apple_fusion_descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from pathlib import Path

import pytest
from tests._support.apple import skip_if_apple_pipeline_unregistered

REPO = Path(__file__).resolve().parents[2]
PASS_SRC = (REPO / "src" / "compiler" / "codegen" / "Tessera_Apple_Backend" /
Expand Down Expand Up @@ -83,6 +84,7 @@ def test_descriptor_vs_rediscovered_source_tag(tmp_path):
"--pass-pipeline=builtin.module(tessera-lower-to-apple_gpu-runtime)",
"--allow-unregistered-dialect"],
capture_output=True, text=True, timeout=60)
skip_if_apple_pipeline_unregistered(out)
assert out.returncode == 0, out.stderr
text = out.stdout
# Both functions fuse to the same kernel ...
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/test_apple_fusion_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from pathlib import Path

import pytest
from tests._support.apple import skip_if_apple_pipeline_unregistered

REPO = Path(__file__).resolve().parents[2]
_CANDIDATES = (
Expand Down Expand Up @@ -100,6 +101,7 @@ def test_stamped_chain_lowers_as_descriptor(tmp_path, case_id, fixture, epilogue
"--pass-pipeline=builtin.module(tessera-lower-to-apple_gpu-runtime)",
"--allow-unregistered-dialect"],
capture_output=True, text=True, timeout=60)
skip_if_apple_pipeline_unregistered(out)
assert out.returncode == 0, out.stderr
text = out.stdout
# It fused (a descriptor was emitted) and the compiler intent drove it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import pytest

from tessera.compiler import driver
from tests._support.apple import skip_if_apple_pipeline_unregistered

REPO_ROOT = Path(__file__).resolve().parents[2]
_DEFAULT = REPO_ROOT / "build" / "tools" / "tessera-opt" / "tessera-opt"
Expand Down Expand Up @@ -60,6 +61,7 @@ def _lower_and_parse(sources: list[str]) -> dict[str, str]:
proc = subprocess.run(
[_OPT, "-", "-tessera-lower-to-apple_gpu", "--allow-unregistered-dialect"],
input="\n".join(lines), capture_output=True, text=True, timeout=60)
skip_if_apple_pipeline_unregistered(proc)
assert proc.returncode == 0, proc.stderr
# Each metal_kernel op carries source + status in its (alphabetically sorted)
# attr dict; source < status, so a per-op non-greedy match pairs them.
Expand Down
5 changes: 4 additions & 1 deletion tests/unit/test_apple_value_target_ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from pathlib import Path

import pytest
from tests._support.apple import skip_if_apple_pipeline_unregistered

REPO_ROOT = Path(__file__).resolve().parents[2]
_OPT_DEFAULT = REPO_ROOT / "build-apple" / "tools" / "tessera-opt" / "tessera-opt"
Expand Down Expand Up @@ -82,9 +83,11 @@ def _find_opt() -> str | None:


def _run(pipeline: str, body: str) -> subprocess.CompletedProcess:
return subprocess.run(
proc = subprocess.run(
[_OPT, f"-{pipeline}", "-"],
input=body, capture_output=True, text=True, timeout=60)
skip_if_apple_pipeline_unregistered(proc)
return proc


# The value-mode module must contain none of: the poison/empty husks, any
Expand Down
27 changes: 24 additions & 3 deletions tests/unit/test_autodiff_rocm_matmul_composed.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,32 @@ def test_rocm_composed_matmul_backward_matches_numpy() -> None:
atol=5e-2, rtol=5e-3)
np.testing.assert_allclose(db, a.astype(np.float32).T @ dout.astype(np.float32),
atol=5e-2, rtol=5e-3)
assert _matmul.last_backward_execution == {
# Assert the fields this proof depends on, not whole-dict equality. The
# record gained six tracer-authority fields in E2E-REAL-6 (`family`,
# `frontend_authority`, and the four `*_consumer` keys) and `implementation`
# became `family_plugin_composition`; a `==` over the whole dict fails on
# additive metadata that does not change what was proven, which is exactly
# how this test went stale. Indexing keeps it fail-closed: a dropped key
# raises KeyError rather than silently passing.
execution = _matmul.last_backward_execution
assert {
key: execution[key]
for key in (
"compiler_path",
"evidence_target",
"execution_kind",
"execution_mode",
"family",
"implementation",
"residual_policy",
)
} == {
# Two compiled forward GEMM launches -- the point of the composition.
"compiler_path": "rocm_compiled+rocm_compiled",
"evidence_target": "rocm_gfx1151",
"execution_kind": "native_gpu",
"execution_mode": "hip_runtime",
"evidence_target": "rocm_gfx1151",
"implementation": "composition",
"family": "matmul_backward",
"implementation": "family_plugin_composition",
"residual_policy": "save_inputs",
}
12 changes: 11 additions & 1 deletion tests/unit/test_rocm_activation_rope_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,19 @@ def test_activation_emits_its_math(kind, op):


def test_activation_unknown_kind_named_error():
# An unknown kind is now rejected by the ODS attribute constraint
# (ROCM_ActivationKindAttr) rather than by a check in the pass body -- that
# is Decision #21a's "EnumAttr over unvalidated StrAttr" applied, so the op
# never reaches the generator. Decision #21 still requires the diagnostic to
# be actionable, so assert what a reader needs: the offending op and the
# legal set. Asserting the whole sentence would just re-encode MLIR's
# verifier wording.
r = _opt(_act("mish"), "--generate-rocm-activation-kernel")
assert r.returncode != 0
assert "kind must be gelu, silu, or relu" in r.stderr
assert "tessera_rocm.activation" in r.stderr
assert "kind" in r.stderr
for legal in ("gelu", "silu", "relu"):
assert legal in r.stderr, f"diagnostic must name the legal kind {legal!r}"


def test_rope_signature_and_trig():
Expand Down