Richard Biener <richard.guent...@gmail.com> writes:
> On December 12, 2019 5:44:25 PM GMT+01:00, Richard Sandiford 
> <richard.sandif...@arm.com> wrote:
>>Richard Biener <richard.guent...@gmail.com> writes:
>>> On December 12, 2019 4:10:33 PM GMT+01:00, Richard Sandiford
>><richard.sandif...@arm.com> wrote:
>>>>One problem with adding an N-bit vector extension to an existing
>>>>architecture is to decide how N-bit vectors should be passed to
>>>>functions and returned from functions.  Allowing all N-bit vector
>>>>types to be passed in registers breaks backwards compatibility,
>>>>since N-bit vectors could be used (and emulated) before the vector
>>>>extension was added.  But always passing N-bit vectors on the
>>>>stack would be inefficient for things like vector libm functions.
>>>>
>>>>For SVE we took the compromise position of predefining new SVE vector
>>>>types that are distinct from all existing vector types, including
>>>>GNU-style vectors.  The new types are passed and returned in an
>>>>efficient way while existing vector types are passed and returned
>>>>in the traditional way.  In the right circumstances, the two types
>>>>are inter-convertible.
>>>>
>>>>The SVE types are created using:
>>>>
>>>>      vectype = build_distinct_type_copy (vectype);
>>>>      SET_TYPE_STRUCTURAL_EQUALITY (vectype);
>>>>      TYPE_ARTIFICIAL (vectype) = 1;
>>>>
>>>>The C frontend maintains this distinction, using VIEW_CONVERT_EXPR
>>>>to convert from one type to the other.  However, the distinction can
>>>>be lost during gimple, which treats two vector types with the same
>>>>mode, number of elements, and element type as equivalent.  And for
>>>>most targets that's the right thing to do.
>>>
>>> And why's that a problem? The difference appears only in the function
>>call ABI which is determined by the function signature rather than
>>types or modes of the actual arguments? 
>>
>>We use the type of the actual arguments when deciding how arguments
>>should be passed to functions:
>>
>>/* I counts args in order (to be) pushed; ARGPOS counts in order
>>written.  */
>>  for (argpos = 0; argpos < num_actuals; i--, argpos++)
>>    {
>>      tree type = TREE_TYPE (args[i].tree_value);
>>      [...]
>>   /* See if this argument should be passed by invisible reference.  */
>>      function_arg_info arg (type, argpos < n_named_args);
>>
>>And it has to be that way for calls to unprototyped functions,
>>or for varargs.
>
> So even for varargs the passing is different? Also we have CALL_EXPR_FNTYPE 
> which you could populate specially even for unprototyped or varargs functions.
>
> I realize we now look at the type of values but you have to realize that 
> differences that are not relevant for values are discarded.  Artificially 
> preserving such non-real differences everywhere(!) while it only matters at 
> call boundaries doesn't look correct. 

But isn't this similar to the way that we preserve the difference
between:

  struct s1 { int i; };
  struct s2 { int i; };

?  They're the same value as far as the target machine is concerned,
but we preserve the difference for other reasons.

>>The AArch64 port emits an error if calls pass values of SVE type to an
>>unprototyped function.  To do that we need to know whether the value
>>really is an SVE type rathr than a plain vector.
>>
>>For varags the ABI is the same for 256 bits+.  But we'll have the
>>same problem there once we support -msve-vector-bits=128, since the
>>layout of SVE and Advanced SIMD vectors differ for big-endian.
>
> But then why don't you have different modes?

Yeah, true, modes will probably help for the Advanced SIMD/SVE
difference.  But from a vector value POV, a vector of 4 ints is a vector
of 4 ints, so even distinguishing based on the mode is artificial.

SVE is AFAIK the first target to have different modes for potentially
the "same" vector type, and I had to add new infrastructure to allow
targets to define multiple modes of the same size.  So the fact that
gimple distinguishes otherwise identical vectors based on mode is a
relatively recent thing.  AFAIK it just fell out in the wash rather
than being deliberately planned.  It happens to be convenient in this
context, but it hasn't been important until now.

The hook doesn't seem any worse than distinguishing based on the mode.
Another way to avoid this would have been to define separate SVE modes
for the predefined vectors.  The big downside of that is that we'd end
up doubling the number of SVE patterns.

Extra on-the-side metadata is going to be easy to drop accidentally,
and this is something we need for correctness rather than optimisation.

Thanks,
Richard

Reply via email to