[Dwarf-discuss] ISSUE: CPU vector types.
Ben Woodard
woodard@redhat.com
Tue Mar 28 18:13:09 GMT 2023
On 3/27/23 23:51, Cary Coutant wrote:
>> Vector registers
>>
>> It has been the long standing existing practice to treat hardware
>> vector registers as arrays of a fundamental base type. To deliniate
>> these hardware register arrays from arrays in the language source they
>> have been given the DW_AT_GNU_vector attribute. This proposal simply
>> standardizes the existing behavior.
>>
>> In Section 2.2 Attribute Types, DW_AT_vector and
>> DW_AT_variable_vector_width shall be added to Table 2.2
>>
>> --------------------------------------------------------------------
>> DW_AT_vector | A hardware vector register
>> DW_AT_variable_vector_width | Array bound for hardware
>> | implementation defined vector register
>> | width
>> --------------------------------------------------------------------
> I don't understand what tags this DW_AT_vector attribute would apply
> to. Vector registers aren't *types*, they're *locations*, so it
> doesn't really make sense to me to put this attribute on a
> DW_TAG_array_type.
Maybe I should have said.
DW_AT_vector | A hardware vector register type
because what I'm talking about are types not locations. Consider a
simple program like:
#include <x86intrin.h>
__m128 *f( __m128 a, float *b){
__m128 *c=new __m128;
*c=_mm_load_ps(b);
*c+=a;
return c;
}
Which when compiled by GCC generates DWARF like this:
[ 7c] base_type abbrev: 3
byte_size (data1) 4
encoding (data1) float (4)
name (strp) "float"
<snip>
[ 7c5] typedef abbrev: 8
name (strp) "__m128"
decl_file (data1) xmmintrin.h (2)
decl_line (data1) 69
decl_column (data1) 15
type (ref4) [ 7d1]
[ 7d1] array_type abbrev: 30
GNU_vector (flag_present) yes
type (ref4) [ 7c]
sibling (ref4) [ 7dd]
[ 7da] subrange_type abbrev: 31
upper_bound (data1) 3
[ 7dd] base_type abbrev: 3
byte_size (data1) 2
encoding (data1) float (4)
name (strp) "_Float16"
[ 7e4] subprogram abbrev: 32
external (flag_present) yes
name (string) "f"
decl_file (data1) vecreg.C (1)
decl_line (data1) 3
decl_column (data1) 9
linkage_name (strp) "_Z1fDv4_fPf"
type (ref4) [ 881]
low_pc (addr) .text+000000000000000000
<_Z1fDv4_fPf>
high_pc (data8) 38 (.bss+000000000000000000)
frame_base (exprloc)
[ 0] call_frame_cfa
call_all_calls (flag_present) yes
sibling (ref4) [ 881]
[ 808] formal_parameter abbrev: 15
name (string) "a"
decl_file (implicit_const) vecreg.C (1)
decl_line (implicit_const) 3
decl_column (data1) 19
type (ref4) [ 7c5]
location (sec_offset) location list [ 10]
GNU_locviews (sec_offset) location list [ c]
[ 818] formal_parameter abbrev: 15
name (string) "b"
decl_file (implicit_const) vecreg.C (1)
decl_line (implicit_const) 3
decl_column (data1) 29
type (ref4) [ 886]
location (sec_offset) location list [ 22]
GNU_locviews (sec_offset) location list [ 1c]
[ 828] variable abbrev: 33
name (string) "c"
decl_file (data1) vecreg.C (1)
decl_line (data1) 4
decl_column (data1) 11
type (ref4) [ 881]
location (sec_offset) location list [ 37]
GNU_locviews (sec_offset) location list [ 35]
<snip>
[ 881] pointer_type abbrev: 5
byte_size (implicit_const) 8
type (ref4) [ 7c5]
[ 886] pointer_type abbrev: 5
byte_size (implicit_const) 8
type (ref4) [ 7c]
----------------
Offset: 10, Index: 4
offset_pair 0, 15
.text+000000000000000000 <_Z1fDv4_fPf>..
.text+0x0000000000000014 <_Z1fDv4_fPf+0x14>
[ 0] reg17
offset_pair 15, 26
.text+0x0000000000000015 <_Z1fDv4_fPf+0x15>..
.text+0x0000000000000025 <_Z1fDv4_fPf+0x25>
[ 0] fbreg -32
end_of_list
Offset: 1c, Index: 10
view pair 0, 0
view pair 0, 0
view pair 0, 0
Offset: 22, Index: 16
offset_pair 0, 9
.text+000000000000000000 <_Z1fDv4_fPf>..
.text+0x0000000000000008 <_Z1fDv4_fPf+0x8>
[ 0] reg5
offset_pair 9, 25
.text+0x0000000000000009 <_Z1fDv4_fPf+0x9>..
.text+0x0000000000000024 <_Z1fDv4_fPf+0x24>
[ 0] reg3
offset_pair 25, 26
.text+0x0000000000000025 <_Z1fDv4_fPf+0x25>..
.text+0x0000000000000025 <_Z1fDv4_fPf+0x25>
[ 0] entry_value:
[ 0] reg5
[ 3] stack_value
end_of_list
The things that I wanted to point out with this example are:
* that a vector is a type, in this case __mm128
* As a location it is different than a packed array with the same type
that it contains.
* This vector type can have a location that exists in memory, but also
can exist in a register. In this case it exists both in reg17 and on
fbreg-32 (on the stack)
Also it should be noted that clang (thankfully) copies gcc's behavior in
this respect at least on linux. For example:
DWARF section [ 6] '.debug_info' at offset 0x27b:
[Offset]
Compilation unit at offset 0:
Version: 4, Abbreviation section offset: 0, Address size: 8, Offset
size: 4
[ b] compile_unit abbrev: 1
producer (strp) "clang version 15.0.7 (Fedora
15.0.7-2.fc37)"
language (data2) C_plus_plus_14 (33)
name (strp) "vecreg.C"
stmt_list (sec_offset) 0
comp_dir (strp) "/home/ben/Shared/test"
low_pc (addr) .text+000000000000000000
<_Z1fDv4_fPf>
high_pc (data4) 38 (.text+0x0000000000000026)
[ 2a] pointer_type abbrev: 2
type (ref4) [ 2f]
[ 2f] const_type abbrev: 3
type (ref4) [ 34]
[ 34] typedef abbrev: 4
type (ref4) [ 3f]
name (strp) "__m128"
decl_file (data1) xmmintrin.h (1)
decl_line (data1) 21
[ 3f] array_type abbrev: 5
GNU_vector (flag_present) yes
type (ref4) [ 4b]
[ 44] subrange_type abbrev: 6
type (ref4) [ 52]
count (data1) 4
[ 4b] base_type abbrev: 7
name (strp) "float"
encoding (data1) float (4)
byte_size (data1) 4
[ 52] base_type abbrev: 8
name (strp) "__ARRAY_SIZE_TYPE__"
byte_size (data1) 8
encoding (data1) unsigned (7)
> We don't have DW_TAGs that describe registers; the
> ABI defines the registers and DWARF producers and consumers should
> understand and agree on the sizes and shapes of the various registers.
Right and they do as you can see from the fragment above reg17 is the
vector register.
The one tricky complication is ARM SVE and RISC-V RVV where the vector
width is not an architectural feature but a particular hardware
implementation feature. To be able to know the actual vector length you
have to read a machine specific register that tells you the length of
the vector registers in that machine. Never the less SVE types can be
passed as parameters between functions and the ABI for the architecture
explains how. This creates some interesting DWARF expressions.
> In Tony's proposal, the new attribute modifies a base type, thus
> introducing a vector type, which might get placed in a vector
> register. But there, I don't see how the vector base type is
> fundamentally different from an array type. It seems it's just a dodge
> to make it a base type so that we can put whole vectors on the stack.
From a type system point of view they are the same and therefore I can
see the appeal of just making them base types for a particular
architecture. The thing that I worry about is the combinatorial
expansion of the base types.
In code that is different than what posted above, the indexability of
the type is important making it behave more like an array.
> Maybe what we're looking for is a DW_TAG_vector_type, whose DW_AT_type
> attribute gives the base type for each element of the vector. This
> seems to be more DWARF-like, and if we decide there's a reason to
> allow stack entries with vector types, we can do that.
In what ways would DW_TAG_vector_type be different than DW_TAG_array?
-ben
>
> -cary
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.dwarfstd.org/pipermail/dwarf-discuss/attachments/20230328/2bb13703/attachment-0001.htm>
More information about the Dwarf-discuss
mailing list