riscv-non-isa / riscv-elf-psabi-doc

A RISC-V ELF psABI Document
https://jira.riscv.org/browse/RVG-4
Creative Commons Attribution 4.0 International
679 stars 159 forks source link

Question on vector register convention #264

Open kito-cheng opened 2 years ago

kito-cheng commented 2 years ago

Review comment come from @anderslindgren-iar and Anders Berg(IAR) https://lists.riscv.org/g/tech-toolchain-runtime/message/344

Vector Register Convention

Anders: The vector register convention is not settled yet as far as I know, so this is only preliminary and can be changed later on. Should therefore be marked as such.

jrtc27 commented 2 years ago

I don't think this is true? There may be some __attribute__((vectorcall)) equivalent, but this isn't changing for the standard default calling convention?

kito-cheng commented 2 years ago

My thought is the vector register convention IS settle down and we really need this to settle down right now, since we might use vector instructions with existing calling conventions without backward incompatibility. e.g. Using lp64d ABI but using vector instruction, and make this workable is important since current linux distro are using either rv64g/lp64d or rv64gc/lp64d, and we definitely don't want make vector instructions incompatible with that, that would be a disaster for the RISC-V ecosystem IMO.

But we DO need a better vector register convention for optimizing the vector code, and that will be a separate calling convention, and might require users to mark something like __attribute__((vectorcall)) or __attribute__((vectorcc)) like Jessica mentioned, and that is a high priority task of this year for psABI group.

And actually we have some preparation for the alternative vector calling convention in future: STO_RISCV_VARIANT_CC, that what we referenced the design from AArch64 SVE :P

anderslindgren-iar commented 2 years ago

Hi!

I think it's a good idea to have attributes to describe which sets of scratch registers a function destroys. This doesn't only apply to vector register but to floating-point registers as well. After all, functions like strlen doesn't destroy floating-point or vector registers. This can be used when declaring functions in the standard library headers as well as user functions, giving applications more registers that survive function calls.

However, I would like to make it naming of the attributes the other way around. It is more natural to specify which register sets a function destroys. In addition, this is future proof in case more register sets are added in the future.

My suggestion is to use something like __attribute__((scratchxregs)) for functions that may destroy the scratch integer registers and __attribute__((scratchxregs, scratchfregs)) for functions that may destroy the scratch integer and scratch floating-point registers.

A function without any such attribute may destroy all scratch registers for the current compilation settings (just like today). This could includes integer, floating-point, and vector scratch registers (once this has been defined).

/ Anders Lindgren, IAR Systems

Den 2022-04-26 kl. 13:36, skrev Kito Cheng:

My thought is the vector register convention /IS/ settle down and we really need this to settle down right now, since we might use vector instructions with existing calling conventions without backward incompatibility. e.g. Using lp64d ABI but using vector instruction, and make this workable is important since current linux distro are using either rv64g/lp64d or rv64gc/lp64d, and we definitely don't want make vector instructions incompatible with that, that would be a disaster for the RISC-V ecosystem IMO.

But we DO need a better vector register convention for optimizing the vector code, and that will be a separate calling convention, and might require users to mark something like |attribute((vectorcall))| or |attribute((vectorcc))| like Jessica mentioned, and that is a high priority task of this year for psABI group.

And actually we have some preparation for the alternative vector calling convention in future: STO_RISCV_VARIANT_CC, that what we referenced the design from AArch64 SVE :P

— Reply to this email directly, view it on GitHub https://eur05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Friscv-non-isa%2Friscv-elf-psabi-doc%2Fissues%2F264%23issuecomment-1109687611&data=05%7C01%7Canders.lindgren%40iar.com%7C6f1504bad60247739d7808da27790cb1%7C752d689536a34853a00fc9efc645753e%7C1%7C0%7C637865698097807419%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=SWa0AlL2%2FHNqz6Txbq%2F0PtZ0Y%2BE4r%2FrOiI8tL%2BhXKGc%3D&reserved=0, or unsubscribe https://eur05.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAYPY25Y6CXNYXU3G2PGQNJDVG7IMRANCNFSM5T5ZHAUA&data=05%7C01%7Canders.lindgren%40iar.com%7C6f1504bad60247739d7808da27790cb1%7C752d689536a34853a00fc9efc645753e%7C1%7C0%7C637865698097807419%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=hqy8iHJ5vxfOWvDnk5AukpIZQmhVQkHJUw5Eqm0Mso4%3D&reserved=0. You are receiving this because you were mentioned.Message ID: @.***>

jrtc27 commented 2 years ago

This does not work with dynamic linking; you can have the attributes but they're totally useless.

ptomsich commented 2 years ago

My thought is the vector register convention IS settle down and we really need this to settle down right now, since we might use vector instructions with existing calling conventions without backward incompatibility. e.g. Using lp64d ABI but using vector instruction, and make this workable is important since current linux distro are using either rv64g/lp64d or rv64gc/lp64d, and we definitely don't want make vector instructions incompatible with that, that would be a disaster for the RISC-V ecosystem IMO.

Given that vectors has only been ratified in December (and the current psABI release should have been released before that), it is not surprising that the vector calling convention is not included.

Please punt this down the road and we'll keep this as a high-priority project for after this psABI release. We can then aim to have a vector calling-convention addendum to psABI in Q4 (please note that the vector calling convention will have to go through the full DoD/Acceptance flow incl. a PoC).

kito-cheng commented 2 years ago

@anderslindgren-iar I can imagine that would be very useful under static linking model, and might not work well on dynamic linking model (PLT stuffs will silently clobber t1 and t3 even no lazy binding), but that's always free to use non-standard calling convention IF compiler* or user guarantee that will work correctly, however such flexible scheme is not needed to be included in psABI spec, psABI has provide STO_RISCV_VARIANT_CC let you mark this function/symbol is using non standard calling convention variant, and that's all what psABI need to provide.

Generally I feel that’s not a bad idea, but that’s just not need to be part of psABI spec unless we identify some variant is really useful and should be standardized, riscv-c-api-doc should be a better place for that, there is already few attribute has similar effect like __attribute__((naked)), __attribute__((interrupt)) to tell compiler use a non-standard calling convention.

So why vector calling convention variant is special and must become a standard calling convention variant, that because we need a standard variant for passing vector arguments, that's default one, and will used to optimize libm and some other libraries;

Of course toolchain vendors could provide other vector calling conventions to optimize code gen or library, but again, the responsibility is back to the user, user guarantee that will work correctly IF using non standard calling conventions (including std. c.c. variants).

Refs:

AndersBerg-IAR commented 2 years ago

I have a somewhat radical proposal for the vector calling convention.

By using such a calling convention, one do not need to know if a function (tree) is using vector extensions or not. The number of vector registers used for passing arguments, is however debatable.

jrtc27 commented 2 years ago

I have a somewhat radical proposal for the vector calling convention.

  • All vector registers/properties should be callee saved.
  • All vector registers can be used as function arguments (including returned result). In such cases the caller is responsible for saving the used argument registers.

This is what is already there today (other than the VXRM/VXSAT debate).

By using such a calling convention, one do not need to know if a function (tree) is using vector extensions or not.

This is not true when dynamic linking is involved, and is why STO_RISCV_VARIANT_CC. Please see the many past discussions about that.

The number of vector registers used for passing arguments, is however debatable.

kito-cheng commented 2 years ago

I have a somewhat radical proposal for the vector calling convention.

  • All vector registers/properties should be callee saved.

All callee save will increasing the initial cost for using vector operations, and in most case vector operation are happened on leaf function, so callee save might be a potential issue.

e.g. memcpy use 2 m8 register to load and store values, then we MUST store/restore 16 vector resister at prologue/epilogue.

  • All vector registers can be used as function arguments (including returned result). In such cases the caller is responsible for saving the used argument registers.

That's a radical but interesting idea, that sounds like kind of dynamic scheme, should be suitable for IPO/LTO, but I guess need more investigation if we consider treat it as a generic vector calling conventions.