Repository navigation
fix(mir-importer): lower libm float ops to libdevice intrinsics - #142
Merged
Merged
Conversation
glam (with `nostd-libm`) lowers float ops to `libm::math::*` (`sqrtf`, `sinf`,
`cosf`, `expf`, `powf`, `floor`, ...). Intercept these at the call site and map
them to the libdevice intrinsics (hardware math), and tell the collector NOT to
translate the `libm` bodies (otherwise `-Zalways-encode-mir` drags in their
generic software implementations and trips importer gaps).
Adds `from_libm_path` (final-segment match -> intrinsic) and an `emit_sincos`
handler for `libm::sincos{f}` (returns `(sin, cos)`, so no single scalar intrinsic
fits — emits a `sinf`/`cosf` pair packed into the destination tuple).
Resolve add-add conflict in mir-importer terminator dispatch: main added the bigint intrinsic dispatch at the same spot where the PR added the libm sincos dispatch. Keep both, bigint first to match main's ordering.
The libm match guard accepted any path containing the substring "libm", so a user function that shares a libm function name (for example an `expf` helper in a `libm_compat` module, or anything in a crate whose name mentions libm) was silently rerouted to the `__nv_expf` libdevice call, replacing the user's body with hardware math: a miscompile, proven on IR during review. Anchor both `from_libm_path` and `libm_sincos_is_f64` on the first path segment being exactly `libm`, and pin the adversarial cases in unit tests.
These libm entry points already have lowering variants on the
core-intrinsic path, so the table extension is free: fmax{f}/fmin{f}
reuse the _nsz maxNum/minNum lowering that backs f32::max and
f32::min, and rint{f}/roundeven{f} reuse the round-ties-even lowering
(the device has no dynamic rounding mode, so rint and roundeven
coincide).
The collector skips the whole libm crate, so a libm call the float-math dispatch does not recognize can never resolve: it used to surface only at module verification as a bare "Symbol libm__cbrtf not found", far from the offending kernel. Bail out at the call site instead, naming the libm function and where to add the mapping, following the per-site diagnostics direction of NVIDIA#168.
The workspace fmt check gates CI; the sincos helper's callee-pair tuples needed wrapping.
Covers the f32 and f64 libm entry points, the tuple-returning sincosf, and the new fmax/fmin/rint lanes, comparing device results against host stdlib math with a SUCCESS marker. Also pins the interception anchor end to end: a user expf in a libm-named module must stay a regular device call; the +1000.0 offset turns any wrong rerouting to __nv_expf into a host-comparison failure. libm sqrt/sqrtf are excluded: libm routes sqrt through an arch-specific inline-asm wrapper that MIR-inlines into the kernel before call-site interception, a known follow-up.
Collaborator
|
Thanks for the PR. LGTM Just a couple of additions:
|
nihalpasham
added a commit
to goog00/cuda-oxide
that referenced
this pull request
Jun 12, 2026
Completes the coordination between the libm interception table (NVIDIA#142) and the cbrt lowering (NVIDIA#148): the libm-crate spellings now reach the same libdevice __nv_cbrt{,f} path as the core ones.
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.
When auto-porting existing rust-gpu / SPIR-V shader crates to cuda-oxide, their glam dependency (with
nostd-libm) lowers float ops tolibm::math::*(sqrtf,sinf,cosf,expf,powf,floor, ...). Intercept these at the call site and map them to the libdevice intrinsics (hardware math), and tell the collector NOT to translate thelibmbodies (otherwise-Zalways-encode-mirdrags in their generic software implementations and trips importer gaps).Adds
from_libm_path(final-segment match -> intrinsic) and anemit_sincoshandler forlibm::sincos{f}(returns(sin, cos), so no single scalar intrinsic fits — emits asinf/cosfpair packed into the destination tuple).