On December 12, 2019 7:15:36 PM GMT+01:00, Richard Sandiford 
<richard.sandif...@arm.com> wrote:
>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.

With LTO we don't. Both get the same TYPE_CANONICAL. 

>>>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.

True. 

>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.

Still selecting the ABI during call expansion only and based on values types at 
that point is fragile. The frontend are in charge of specifying the actual 
argument type and at that point the target may fix the ABI. The ABI can be 
recorded in the calls fntype, either via its TYPE_ARG_TYPES or in more awkward 
ways for varargs functions (in full generality that would mean attaching 
varargs ABI meta to each call). 

The alternative is to have an actual argument type vector associated with each 
call.

Btw, how does STRIP_NOPS preserve the argument type if a conversion happens in 
the call and generic folding applies? IIRC that puns down to modes as well 
(which was the reason to make useless_type_conversion_p do the same). 

Sorry for the vague and late answers, I'm already in christmas mode ;) 

Richard. 

>Thanks,
>Richard

Reply via email to