Skip to content

t27b: f32 @floor, @ceil, @round, @trunc and @rem from libm.t27 (compiler_rt floorf, ceilf, roundf, truncf, fmodf) #7819

Closed

Description

@gHashTag

Part of #7746 (t27b passes specs/numeric/gf16.t27), which is part of #6063 (t27b coverage), item C10 of #6488. This is the second PR of #7746's split, after #7791.

What gf16.t27 needs

gf16_floor, gf16_ceil, gf16_round, gf16_trunc and gf16_fmod call @floor, @ceil, @round, @trunc and @rem on an f32, and each has direct tests. t27b refuses all five today (ExprCall(@floor) and so on).

What the reference does

Measured on the t27c lab (zig 0.16.0, x86_64 Debug, the CPU has SSE4.1):

  • @floor, @ceil and @trunc of an f32 are not calls. Zig emits roundss, which is exact and quiets a signalling NaN (0x7F800001 gives 0x7FC00001). On aarch64, frintm, frintp and frintz do the same.
  • @round of an f32 calls compiler_rt roundf: half away from zero, and a NaN comes back as it is (0x7F800001 stays 0x7F800001). aarch64's frinta quiets it instead, so @round of a signalling NaN is the one place the two references differ.
  • @rem of an f32 calls compiler_rt fmodf (generic_fmod): exact, and the sign follows the dividend (@rem(-4, 2) is -0.0). Its NaN is (x * y) / (x * y), whose bits are the platform's: 0xFFC00000 on x86_64, 0x7FC00000 on aarch64.

Plan

  • Port compiler_rt's floorf, ceilf, roundf, truncf and fmodf to t27 in specs/tri/t27b/libm.t27. For floorf, ceilf and truncf, a NaN is quieted, as the instruction does.
  • Add the five builtins to specs/tri/t27b/libm_plan.t27:
    • an f32 calls its routine;
    • an f64 is refused, because libm.t27 has no f64 routine for these yet;
    • @rem takes two operands, and the second takes the first one's type.
  • Test each routine against Zig's builtin, bit for bit, over sweeps of bit patterns: signed zeros, subnormals, halves, NaN payloads and the infinities. No NaN bits are asserted where the two references differ.

Acceptance criteria

  • t27b test --blockers specs/numeric/gf16.t27 names none of @floor, @ceil, @round, @trunc and @rem.
  • libm.t27's new tests pass under t27c test-report with 0 vacuous tests, and under t27b.
  • The lab corpus receipt compare gives IMPROVED_ONLY, EQUIVALENT or NEUTRAL.

User Scenarios

  • Given gf16.t27 calls @floor, @ceil, @round, @trunc, @rem on f32 values, When t27b compiles gf16.t27, Then none of the five builtins are refused and the tests in gf16.t27 pass.
  • Given libm.t27 provides floorf, ceilf, roundf, truncf, fmodf ported from compiler_rt, When t27c test-report runs on libm.t27, Then all new tests pass with 0 vacuous tests and bit-for-bit match Zig's builtins over the specified sweeps.
  • Given libm_plan.t27 declares the five f32 builtins with correct signatures, When t27b type-checks a call to @rem with two f32 operands, Then the second operand takes the first's type and f64 calls are refused.

Requirements

  • FR-001: specs/tri/t27b/libm.t27 MUST contain floorf, ceilf, roundf, truncf, fmodf routines ported from compiler_rt for f32.
  • FR-002: floorf, ceilf, truncf in libm.t27 MUST quiet a signalling NaN (0x7F800001 → 0x7FC00001) matching x86_64 roundss / aarch64 frintm|p|z behavior.
  • FR-003: roundf in libm.t27 MUST implement half-away-from-zero and preserve a signalling NaN payload (0x7F800001 stays 0x7F800001) matching compiler_rt roundf.
  • FR-004: fmodf in libm.t27 MUST implement exact remainder with sign following dividend (@rem(-4, 2) = -0.0) and produce platform NaN bits via (x*y)/(x*y) matching compiler_rt generic_fmod.
  • FR-005: specs/tri/t27b/libm_plan.t27 MUST declare @floor, @ceil, @round, @trunc as unary f32 builtins calling their libm.t27 routines and refuse f64.
  • FR-006: specs/tri/t27b/libm_plan.t27 MUST declare @rem as binary f32 builtin where the second operand takes the first's type and refuse f64.
  • FR-007: libm.t27 MUST include bit-for-bit tests against Zig builtins covering signed zeros, subnormals, halves, NaN payloads, and infinities with no assertions on differing NaN bits between x86_64 and aarch64.

Success Criteria

  • t27b test --blockers specs/numeric/gf16.t27 exits 0 and names none of @floor, @ceil, @round, @trunc, @rem as blockers.
  • t27c test-report specs/tri/t27b/libm.t27 exits 0 with 0 vacuous tests and all new routine tests passing.
  • t27b test specs/tri/t27b/libm.t27 exits 0.
  • Lab corpus receipt compare yields IMPROVED_ONLY, EQUIVALENT, or NEUTRAL (no REGRESSION).

Boundary

  • specs/numeric/gf16.t27
  • specs/tri/t27b/libm.t27
  • specs/tri/t27b/libm_plan.t27

Activity

  1. added 5 commits that reference this issue on Oct 8, 2026
    3e7653e
    74d6f55
    d940bce
    5e8857a
    4d26398
  2. added 4 commits that reference this issue on Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions