Stam Markianos-Wright <stam.markianos-wri...@arm.com> writes: > On 1/30/20 10:01 AM, Richard Sandiford wrote: >> Stam Markianos-Wright <stam.markianos-wri...@arm.com> writes: >>> On 1/29/20 12:42 PM, Richard Sandiford wrote: >>>> Stam Markianos-Wright <stam.markianos-wri...@arm.com> writes: >>>>> Hi all, >>>>> >>>>> This fixes: >>>>> >>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93300 >>>>> >>>>> Genmodes.c was generating the "wider_mode" chain as follows: >>>>> >>>>> HF -> BF -> SF - > DF -> TF -> VOID >>>>> >>>>> This caused issues in some rare cases where conversion between modes >>>>> was needed, such as the above PR93300 where BFmode was being picked up >>>>> as a valid mode for: >>>>> >>>>> optabs.c:prepare_float_lib_cmp >>>>> >>>>> which then led to the ICE at expr.c:convert_mode_scalar. >>> >>> Hi Richard, >>> >>>> >>>> Can you go into more details about why this chain was a problem? >>>> Naively, it's the one I'd have expected: HF should certainly have >>>> priority over BF, >>> >>> Is that because functionally it looks like genmodes puts things in reverse >>> alphabetical order if all else is equal? (If I'm reading the comment about >>> MODE_RANDOM, MODE_CC correctly) >>> >>>> but BF coming before SF doesn't seem unusual in itself. >>>> >>>> I'm not saying the patch is wrong. It just wasn't clear why it was >>>> right either. >>>> >>> Yes, I see what you mean. I'll go through my thought process here: >>> >>> In investigating the ICE PR93300 I found that the diversion from pre-bf16 >>> behaviour was specifically at `optabs.c:prepare_float_lib_cmp`, where a >>> `FOR_EACH_MODE_FROM (mode, orig_mode)` is used to then go off and generate >>> library calls for conversions. >>> >>> This was then being caught further down by the gcc_assert at expr.c:325 >>> where >>> GET_MODE_PRECISION (from_mode) was equal to GET_MODE_PRECISION (to_mode) >>> because >>> it was trying to emit a HF->BF conversion libcall as `bl __extendhfbf2` >>> (which >>> is what happened if i removed the gcc_assert at expr.c:325) >>> >>> With BFmode being a target-defined mode, I didn't want to add something >>> like `if >>> (mode != BFmode)` to specifically exclude BFmode from being selected for >>> this. >>> (and there's nothing different between HFmode and BFmode here to allow me to >>> make this distinction?) >>> >>> Also I couldn't find anywhere where the target back-end is not consulted >>> for a >>> "is this supported: yes/no" between the `FOR_EACH_MODE_FROM` loop and the >>> libcall being created later on as __extendhfbf2. >> >> Yeah, prepare_float_lib_cmp just checks for libfuncs rather than >> calling target hooks directly. The libfuncs themselves are under >> the control of the target though. >> >> By default we assume all float modes have associated libfuncs. >> It's then up to the target to remove functions that don't exist >> (or redirect them to other functions). So I think we need to remove >> BFmode libfuncs in arm_init_libfuncs in the same way as we currently >> do for HFmode. >> >> I guess we should also nullify the conversion libfuncs for BFmode, >> not just the arithmetic and comparison ones. > > Ahhh now this works, thank you for the suggestion! > > I was aware of arm_init_libfuncs, but I had not realised that returning NULL > would have the desired effect for us, in this case. So I have essentially > rolled > back the whole previous version of the patch and done this in the new diff. > It seems to have fixed the ICE and I am currently in the process of > regression > testing!
LGTM behaviourally, just a couple of requests about how it's written: > > Thank you! > Stam > >> >> Thanks, >> Richard >> >>> Finally, because we really don't want __bf16 to be in the same "conversion >>> rank" >>> as standard float modes for things like automatic promotion, this seemed >>> like a >>> reasonable solution to that problem :) >>> >>> Let me know of your thoughts! >>> >>> Cheers, >>> Stam > > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index c47fc232f39..18055d4a75e 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -2643,6 +2643,30 @@ arm_init_libfuncs (void) > default: > break; > } > + > + /* For all possible libcalls in BFmode, return NULL. */ > + /* Conversions. */ > + set_conv_libfunc (trunc_optab, BFmode, HFmode, (NULL)); > + set_conv_libfunc (sext_optab, HFmode, BFmode, (NULL)); > + set_conv_libfunc (trunc_optab, BFmode, SFmode, (NULL)); > + set_conv_libfunc (sext_optab, SFmode, BFmode, (NULL)); > + set_conv_libfunc (trunc_optab, BFmode, DFmode, (NULL)); > + set_conv_libfunc (sext_optab, DFmode, BFmode, (NULL)); It might be slightly safer to do: FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_FLOAT) to iterate over all float modes on the non-BF side. > + /* Arithmetic. */ > + set_optab_libfunc (add_optab, BFmode, NULL); > + set_optab_libfunc (sdiv_optab, BFmode, NULL); > + set_optab_libfunc (smul_optab, BFmode, NULL); > + set_optab_libfunc (neg_optab, BFmode, NULL); > + set_optab_libfunc (sub_optab, BFmode, NULL); > + > + /* Comparisons. */ > + set_optab_libfunc (eq_optab, BFmode, NULL); > + set_optab_libfunc (ne_optab, BFmode, NULL); > + set_optab_libfunc (lt_optab, BFmode, NULL); > + set_optab_libfunc (le_optab, BFmode, NULL); > + set_optab_libfunc (ge_optab, BFmode, NULL); > + set_optab_libfunc (gt_optab, BFmode, NULL); > + set_optab_libfunc (unord_optab, BFmode, NULL); Could you split this part out into a subroutine and reuse it for the existing HFmode code too? Thanks, Richard