https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122762
--- Comment #24 from Richard Sandiford <rsandifo at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #21)
> (In reply to Richard Sandiford from comment #17)
> > (In reply to Richard Biener from comment #11)
> > > (In reply to Richard Sandiford from comment #10)
> [...]
> > > > As for why it does that, see the commit message for
> > > > g:482b2b43e5101921ad94e51e052a18b353f8a3f5, which introduced the check.
> > >
> > > Hm, but that talks about argument passing / return ABIs?
> > > useless_type_conversion_p applies to value types, at most its check
> > > for FUNCTION_TYPE compatibility would need to use this check?
> >
> > Wouldn't that be bad for composability though? It would seem odd for "T1
> > f()" vs "T2 g()" to impose stricter rules than T1 vs T2.
>
> Sure, but useless_type_conversion_p is generally the wrong place to address
> ABI compatibility issues. What breaks when not having this check in
> useless_type_conversion_p? The testcases added, if they break, would
> point to places where we use this function wrongly. It's by far
> "complete" to check whether two FUNCTION_TYPE have the same ABI.
I think the FUNCTION_TYPE thing is a bit of a red herring. The main reason for
the check is to preserve the types of vector values. That's because
code-generation of calls depends on the gimple type of the value being passed,
rather than the argument type recorded in the FUNCTION_TYPE. For example, see
calls.cc:
FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
{
tree argtype = TREE_TYPE (arg);
if (targetm.calls.split_complex_arg…)
…
else
args[j].tree_value = arg;
as used in:
for (argpos = 0; argpos < num_actuals; i--, argpos++)
{
tree type = TREE_TYPE (args[i].tree_value);
…
function_arg_info arg (type, argpos < n_named_args);
if (pass_by_reference (args_so_far_pnt, arg))
…
}
where the way that something is passed is keyed off the type of the gimple
value. The FUNCTION_TYPE's TYPE_ARG_TYPES is only used to distinguish
prototyped from unprototyped functions and to determine which arguments are
named and which are varargs.
And I think it has to be that way. The different passing of SVE vs. non-SVE
types extends to varargs. If gimple didn't preserve the difference, then we
wouldn't know which convention to use.