Repository navigation
Emit valid kernel source for non-finite float constants - #3648
Merged
angeloskath merged 2 commits intoJun 11, 2026
Merged
Conversation
Compiling a function that bakes a NaN (or infinity) scalar constant into a fused kernel failed because print_float_constant streamed a bare token such as `nan`, which is not a valid identifier in the generated kernel source (e.g. Metal: "use of undeclared identifier 'nan'"). Emit the NAN / INFINITY / -INFINITY macros instead; both the Metal (<metal_stdlib>) and CPU (<cmath>) kernel toolchains provide them. The finite check widens to double first so it is exact for every float type. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
zcbenz
approved these changes
Jun 10, 2026
zcbenz
left a comment
Member
There was a problem hiding this comment.
This would be a nice improvement, can you also remove the #define infs in https://github.com/search?q=repo%3Aml-explore%2Fmlx%20%22define%20inf%22&type=code ?
The prebuilt CPU preamble is produced by running the preprocessor over compiled_preamble.h, which consumes the NAN / INFINITY macro definitions (macros vanish during preprocessing, leaving only the expanded <cmath> declarations). print_float_constant emits those macros for non-finite constants, so the generated kernel failed to compile with "'NAN' was not declared in this scope" on the Linux/Windows prebuilt-preamble path. Define the macros in the generated source when they are missing, backed by std::numeric_limits (available via <limits>). The #ifndef guards make this a no-op on paths where <cmath>'s macros are already in scope (e.g. the include-based preamble path), avoiding redefinition clashes. Also drop the now-dead `#define inf` from the CUDA backends: non-finite constants are emitted as the standard INFINITY/NAN macros (which CUDA provides), so the bare `inf` token is no longer generated. Verified on a Linux + g++ build (the failing path): the regression test fails with the original "'NAN' was not declared" error without this change and passes with it. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
tillahoffmann
force-pushed
the
fix-nan-constant-codegen
branch
from
June 10, 2026 12:54
2061983 to
9db52bc
Compare
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
Compiling a function that bakes a NaN (or infinity) scalar constant into a fused kernel fails to compile.
print_float_constantstreams the value withoperator<<, producing a bare token likenan, which is interpolated verbatim into the generated kernel source and is not a valid identifier:Eager evaluation is fine; only the compiled path is affected.
Repro
Fix
Emit the
NAN/INFINITY/-INFINITYmacros for non-finite values. Both kernel toolchains provide them — Metal via<metal_stdlib>(#define NAN __builtin_nanf(""),#define INFINITY __builtin_inff()) and the CPU C++ codegen via<cmath>— so the same emitted text is valid for both backends. The finite check widens todoublefirst so it is exact for every float type.Tests
tests/compile_tests.cpp:test compile with non-finite constants.python/tests/test_compile.py:test_compile_nonfinite_constants(float32/float16/bfloat16, NaN and -inf).Verified red→green on both: the unfixed build reproduces the
nanerror, the fixed build computes the expected values. Full C++ compile suite andtest_compile.pypass.🤖 Generated with Claude Code