Agree with Robin and Andrew.

I was thinking we may not need to take care of vxrm similar as frm in previous, 
but seems
not that simple up to a point after Richard S points it out.

I also failed to locate some spec/doc about the details. I remember Jeff has 
some findings/comments,
and may wait for a while if we need to tweak the vxrm behaviors, like set, 
consume, global_reg, ... etc.

Pan

-----Original Message-----
From: Robin Dapp <rdapp....@gmail.com> 
Sent: Tuesday, March 4, 2025 8:51 PM
To: Vineet Gupta <vine...@rivosinc.com>; Andrew Waterman <aswater...@gmail.com>
Cc: Li, Pan2 <pan2...@intel.com>; jeffreya...@gmail.com; 
gcc-patches@gcc.gnu.org; juzhe.zh...@rivai.ai; kito.ch...@gmail.com; 
richard.sandif...@arm.com; Robin Dapp <rdapp....@gmail.com>
Subject: Re: FRM ABI semantics (was Re: [PATCH v1] RISC-V: Make VXRM as global 
register [PR118103])

> Yeah I didn't know how to articulate  it (and perhaps this still requires
> clarification)
>
> Say we have following
>
> // reduced version of  gcc.target/riscv/rvv/base/float-point-frm-run-1.c
>  main
>     set_frm (4);    // orig global FRM update
>
>     test_float_point_frm_run_1 (op1, op2, vl)
>        set_frm (0);
>        result = __riscv_vfadd_vv_f32m1_rm (op1, result, 1, vl);
>        assert_equal (1, get_frm ())
>        // restore global 4 before returning
>
>     assert_equal (4, get_frm ()      <-- here call restores global
>
> vs.
>
> // reduced version of  gcc.target/riscv/rvv/base/float-point-frm-run-5.c
> main
>   set_frm (1);    // orig global FRM update
>
>   test_float_point_frm_run_1 (op1, op2, vl)
>           other_function()
>                set_frm (2);    // also global update
>
>   assert_equal (2, get_frm ()            <-- here call doesn't restore
>
> There's no explicit annotation or anything about the FRM, yet in 2nd example
> other_function () we consider frm write a global event but not in
> test_float_point_frm_run_1 () in 1st example: I'm missing words how to explain
> that :-)

AFAIR the general idea is that every function can potentially "clobber", i.e. 
set FRM globally.

The intent of the first test is to save and restore the global rounding mode 
because we modify it locally by a rounding-mode changing intrinsic.

However, as you note, the set_frm at the beginning of 
test_float_point_frm_run_1 has no effect.  What should intuitively(?) happen is 
that it sets a new global FRM that we restore upon exit.  We, however, restore 
the previous global FRM.  I believe that's because set_frm is an inline 
assembly, inlined into test_float_point_frm_run_1 and we expect inline 
assemblies to _not_ change the rounding mode.  That was one of my concerns 
during the review some time in 2023.  If set_frm were a non-inlined function 
we'd need to assume it changes the rounding mode and restore the value it has 
after the set_frm call.

And that's also what is different in frm-run-5.c (your second snippet).  We 
wrap the set_frm call in another non-inlinable call.  Thus, we need to assume 
the global rounding mode changes and save/restore.

I guess it was a deliberate decision to handle asm snippets different.  At 
least as long as they are in the same visible scope it's obvious when they're 
changing the rounding mode.  One could argue that users doing that are on their 
own.  Not sure that argument has worked very well, historically, though ;)

-- 
Regards
 Robin

Reply via email to