Skip to content

[rocjitsu] MODE.FP_ROUND does not reach the arithmetic: every directed rounding mode returns the round-to-nearest result #10855

Description

@lialan

Summary

rocjitsu executes the guest's MODE.FP_ROUND by setting the host's rounding mode — fp_mode.h wraps each architectural operation in a ScopedFenv (feholdexcept + fesetround) and lets the hardware round.

Nothing tells the compiler that rounding is dynamic, so it assumes the default mode and is free to move the arithmetic across the fesetround. Every directed rounding mode silently produces the round-to-nearest answer.

Reproducer

V_FMAC_F64 computing 1.0 * 2^-53 + 1.0 — an exact tie, half an ulp above 1.0, so the rounding mode alone decides the result.

MODE.FP_ROUND guest should see scalar path returns
0 nearest-even 0x3ff0000000000000 0x3ff0000000000000
1 +inf 0x3ff0000000000001 0x3ff0000000000000
2 −inf / 3 zero 0x3ff0000000000000 wrong on operands past the halfway point ❌

Independent of the test suite — a program calling fp_mode::fma_f64 with inputs taken from argv so nothing can be constant-folded:

$ g++-13 -O3 …                  round=1 -> 0x3ff0000000000000   # wrong
$ g++-13 -O3 -frounding-math …  round=1 -> 0x3ff0000000000001   # correct

Not compiler-specific

Measured on the same probe, wrong without -frounding-math and correct with it, on all of:

  • GCC 13.4
  • clang 14
  • clang 15
  • AMD clang 22 (/opt/rocm/llvm/bin/clang++)

So building with amdclang does not avoid it.

Impact

Any guest code that sets a directed rounding mode gets nearest-even instead. The scalar and SIMD paths are affected differently, so a result can also depend on RJ_FORCE_SCALAR.

It currently shows up as three failing tests on develop:

Vop2FmaF64SimdCorrectness.AllRoundAndDenormModesMatchScalar
Vop2FmaF64SimdCorrectness.SpecialValuesAndDenormBoundariesMatchScalarExactly
Gfx1250ExecutionTest.FusedOperationsHonorF16F64ModeControls

Those assert simd == scalar, which catches the divergence but names whichever path it is handed as the reference — here the scalar path is the wrong one, so the failure reads as "the two disagree" rather than "one is wrong".

Note

This is distinct from #10330, which is about scalar and SIMD matrix kernels accumulating MACs differently. Same visible symptom (a result depending on RJ_FORCE_SCALAR), different cause.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions