Hi Tom,

I'll admit that I'd not myself considered the ABI issues when I initially 
proposed
experimental HFmode support for the nvptx backend, and was surprised when
I finally tracked down the source of the problem you'd reported: that libgcc
spots HFmode support exists and immediately starts passing/returning values
in this type.

The one precedent that I can point to is that LLVM's nvptx backend passes
HFmode values in SImode regs,   see https://reviews.llvm.org/D28540
Their motivation is that not all PTX ISAs support fp16, so for compatibility
with say sm_30/sm_35, fp16 values are treated like b16, i.e. HImode.
At this point, the nvptx ABI states that HImode values are passed as SImode,
so we end up with the interesting mismatch of HFmode<->SImode.
I guess the same thing affects host code, where an i386/x86 host that
doesn't support 16-bit floating point, can pass "unsigned short" values
to and from the accelerator, and likewise this HImode locally gets passed
in a wider (often WORD_MODE) integer types on most x86 ABIs.

My guess is that passing SFmode in DImode may have been supported
in older versions of GCC, before handling of SUBREGs was tightened up,
so this might be considered a regression.

Cheers,
Roger
--

> -----Original Message-----
> From: Tom de Vries <tdevr...@suse.de>
> Sent: 22 February 2022 15:43
> To: Roger Sayle <ro...@nextmovesoftware.com>; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] middle-end: Support ABIs that pass FP values as wider
> integers.
> 
> On 2/9/22 21:12, Roger Sayle wrote:
> >
> > This patch adds middle-end support for target ABIs that pass/return
> > floating point values in integer registers with precision wider than
> > the original FP mode.  An example, is the nvptx backend where 16-bit
> > HFmode registers are passed/returned as (promoted to) SImode registers.
> > Unfortunately, this currently falls foul of the various (recent?)
> > sanity checks that (very sensibly) prevent creating paradoxical
> > SUBREGs of floating point registers.  The approach below is to
> > explicitly perform the conversion/promotion in two steps, via an
> > integer mode of same precision as the floating point value.  So on
> > nvptx, 16-bit HFmode is initially converted to 16-bit HImode (using
> > SUBREG), then zero-extended to SImode, and likewise when going the
> > other way, parameters truncated to HImode then converted to HFmode
> > (using SUBREG).  These changes are localized to expand_value_return
> > and expanding DECL_RTL to support strange ABIs, rather than inside
> > convert_modes or gen_lowpart, as mismatched precision integer/FP
> > conversions should be explicit in the RTL, and these semantics not generally
> visible/implicit in user code.
> >
> 
> Hi Roger,
> 
> I cannot comment on the patch, but I do wonder (after your "strange ABI"
> comment): did we actively decide on (or align to) a register passing ABI for
> HFmode, or has it merely been decided by the implementation of
> promote_arg:
> ...
> static machine_mode
> promote_arg (machine_mode mode, bool prototyped) {
>    if (!prototyped && mode == SFmode)
>      /* K&R float promotion for unprototyped functions.  */
>      mode = DFmode;
>    else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
>      mode = SImode;
> 
>    return mode;
> }
> ...
> 
> There may be a rationale why it's good to pass a HF as SI, but it's not
> documented there.
> 
> Anyway, I checked what cuda does for HF, and it passes a byte array:
> ...
> .param .align 2 .b8 _Z5helloPj6__halfs_param_1[2], ...
> 
> So, I guess what I'm saying is I'd like to understand why we're having the HF 
> -> SI
> promotion.
> 
> Thanks,
> - Tom

Reply via email to