Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly #130630

Merged
merged 1 commit into from
Oct 1, 2024

Conversation

taiki-e
Copy link
Member

@taiki-e taiki-e commented Sep 20, 2024

This supports clobber_abi which is one of the requirements of stabilization mentioned in #93335.

This also supports vector registers (as vreg) and access registers (as areg) as clobber-only, which need to support clobbering of them to implement clobber_abi.

Refs:

I have three questions:

Note:

cc @uweigand

r? @Amanieu

@rustbot label +O-SystemZ +A-inline-assembly

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 20, 2024
@rustbot
Copy link
Collaborator

rustbot commented Sep 20, 2024

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbot rustbot added the O-SystemZ Target: SystemZ processors (s390x) label Sep 20, 2024
@uweigand
Copy link
Contributor

This supports clobber_abi which is one of the requirements of stabilization mentioned in #93335.

Thanks for working on SystemZ support for this!

ELF Application Binary Interface s390x Supplement says that cc (condition code, bits 18-19 of PSW) is "Volatile".
However, we do not have a register class for cc and instead mark cc as clobbered unless preserves_flags is specified (Mark s390x condition code register as clobbered in inline assembly #111331).
Therefore, in the current implementation, if both preserves_flags and clobber_abi are specified, cc is not marked as clobbered. Is this okay? Or even if preserves_flags is used, should cc be marked as clobbered if clobber_abi is used?

As I read the Rust inline-asm documention (https://doc.rust-lang.org/stable/reference/inline-assembly.html), this looks OK to me. We have the statement:

Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.
- This only applies to registers which can be specified as an input or output. Other registers follow target-specific rules.

Since the flags register cannot be specified as an input or output, the target-specific rules exception applies. For the flags register specifically, we then have the following rules:

These flags registers must be restored upon exiting the asm block if the preserves_flags option is set: 
- [list per architecture]

We can define this for SystemZ, and the definition that makes sense is to preserve the full CC value. (And I guess also some of the flags in the floating-point control register, specifically the exception masks and rounding modes. But since we don't really model the FPC, we may have to just ignore that part for now.)

Finally, looking at the list of clobbered registers on the other supported targets shows that for none of them, clobber_abi affects the flags register(s). So it seems intentional that clobber_abi and preserves_flags are somewhat orthogonal; it would seem to make sense to follow that precedent on SystemZ as well.

ELF Application Binary Interface s390x Supplement says that pm (program mask, bits 20-23 of PSW) is "Cleared".
There does not appear to be any registers associated with this in either LLVM or GCC, so at this point I don't see any way other than to just ignore it. Is this okay as-is?

Yes, that should be fine to ignore.

Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and reg_addr, which uses the “a” constraint (Support reg_addr register class in s390x inline assembly #119431)...

Not sure exactly what the Rust convention here is. I'd be fine with "areg", but maybe "acreg" or something might be clearer?

GCC seems to recognize only a0 and a1, and using a[2-15] causes errors.
Given that cg_gcc has a similar problem with other architecture (x86_64 asm: Build error when using r[8-15]b rustc_codegen_gcc#485), I don't feel this is a blocker for this PR, but it is worth mentioning here.

Interesting, thanks for pointing this out. This should be fixed in GCC at some point, but it's probably not particularly important. I agree it should not block this PR.

vreg should be able to accept #[repr(simd)] types as input if the vector target feature added in rustc_target: add known safe s390x target features #127506 is enabled, but core_arch has no s390x vector type and both #[repr(simd)] and core::simd are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... S390x inline asm #88245 (comment)

Actually, the situation has improved: the problem I pointed out in that last comment has been fixed in LLVM 16, which now always uses the same data_layout string, no matter whether the vector feature is enabled or not:
https://releases.llvm.org/16.0.0/docs/ReleaseNotes.html#changes-to-the-systemz-backend

Assuming rustc is now always built with LLVM 16 or later, we can drop the code that forces the vector feature to be always off, which would enable making general use of vector facilities if enabled. This would include fully supporting the vreg class for inline asm as well as enabling auto-SIMD and possibly even defining a set of platform-specific vector intrinsics.

@taiki-e taiki-e mentioned this pull request Sep 26, 2024
10 tasks
@taiki-e
Copy link
Member Author

taiki-e commented Sep 26, 2024

ELF Application Binary Interface s390x Supplement says that cc (condition code, bits 18-19 of PSW) is "Volatile".
However, we do not have a register class for cc and instead mark cc as clobbered unless preserves_flags is specified (Mark s390x condition code register as clobbered in inline assembly #111331).
Therefore, in the current implementation, if both preserves_flags and clobber_abi are specified, cc is not marked as clobbered. Is this okay? Or even if preserves_flags is used, should cc be marked as clobbered if clobber_abi is used?

As I read the Rust inline-asm documention (https://doc.rust-lang.org/stable/reference/inline-assembly.html), this looks OK to me. We have the statement:

Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.
- This only applies to registers which can be specified as an input or output. Other registers follow target-specific rules.

Since the flags register cannot be specified as an input or output, the target-specific rules exception applies. For the flags register specifically, we then have the following rules:

These flags registers must be restored upon exiting the asm block if the preserves_flags option is set: 
- [list per architecture]

We can define this for SystemZ, and the definition that makes sense is to preserve the full CC value. (And I guess also some of the flags in the floating-point control register, specifically the exception masks and rounding modes. But since we don't really model the FPC, we may have to just ignore that part for now.)

Finally, looking at the list of clobbered registers on the other supported targets shows that for none of them, clobber_abi affects the flags register(s). So it seems intentional that clobber_abi and preserves_flags are somewhat orthogonal; it would seem to make sense to follow that precedent on SystemZ as well.

Thanks for looking into this! After reading your comment I agree that this is okay as is (clobber_abi` doesn't t affect the flags registers).

ELF Application Binary Interface s390x Supplement says that pm (program mask, bits 20-23 of PSW) is "Cleared".
There does not appear to be any registers associated with this in either LLVM or GCC, so at this point I don't see any way other than to just ignore it. Is this okay as-is?

Yes, that should be fine to ignore.

Thanks for confirming!

Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and reg_addr, which uses the “a” constraint (Support reg_addr register class in s390x inline assembly #119431)...

Not sure exactly what the Rust convention here is. I'd be fine with "areg", but maybe "acreg" or something might be clearer?

If there is a name familiar to people familiar with s390x, I would have preferred to use it, but if there is not, areg, which uses the first letter of the register name, may actually be appropriate since it is also consistent with other register class names such as vreg and freg.

vreg should be able to accept #[repr(simd)] types as input if the vector target feature added in rustc_target: add known safe s390x target features #127506 is enabled, but core_arch has no s390x vector type and both #[repr(simd)] and core::simd are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... S390x inline asm #88245 (comment)

Actually, the situation has improved: the problem I pointed out in that last comment has been fixed in LLVM 16, which now always uses the same data_layout string, no matter whether the vector feature is enabled or not: https://releases.llvm.org/16.0.0/docs/ReleaseNotes.html#changes-to-the-systemz-backend

Assuming rustc is now always built with LLVM 16 or later, we can drop the code that forces the vector feature to be always off, which would enable making general use of vector facilities if enabled. This would include fully supporting the vreg class for inline asm as well as enabling auto-SIMD and possibly even defining a set of platform-specific vector intrinsics.

Thanks for the info! The current minimum external LLVM version is 18 (#130487), so I thought that the explicit disabling of the vector feature could be removed, but reading the target spec code, it seems that there is actually another issue that needs to be resolved...

// FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
// also strip v128 from the data_layout below to match the older LLVM's expectation.
base.features = "-vector".into();

(I think it is off topic to continue talking about this here, so I opened #130869 which tracks the status of vector facilities support.)

@uweigand
Copy link
Contributor

Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and reg_addr, which uses the “a” constraint (Support reg_addr register class in s390x inline assembly #119431)...

Not sure exactly what the Rust convention here is. I'd be fine with "areg", but maybe "acreg" or something might be clearer?

If there is a name familiar to people familiar with s390x, I would have preferred to use it, but if there is not, areg, which uses the first letter of the register name, may actually be appropriate since it is also consistent with other register class names such as vreg and freg.

Well, what should be familiar is the term "access register" as well as the short form AR, which parallels the short forms GPR (general-purpose register), FPR (floating-point register), VR (vector register) and CR (control register). There is no generally-known term "areg", but then there is no generally-known term "freg" or "vreg" either. But given this way of forming the name, it should be clear what is meant by "areg".

In any case, ARs by any name are basically never used on Linux anyway - sort of similar to segment registers on 64-bit Intel Linux. (With the exception of the toolchain using %a0/%a1 as thread-local pointer.)

Thanks for the info! The current minimum external LLVM version is 18 (#130487), so I thought that the explicit disabling of the vector feature could be removed, but reading the target spec code, it seems that there is actually another issue that needs to be resolved...

// FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
// also strip v128 from the data_layout below to match the older LLVM's expectation.
base.features = "-vector".into();

(I think it is off topic to continue talking about this here, so I opened #130869 which tracks the status of vector facilities support.)

Thanks! Will reply there.

@Amanieu
Copy link
Member

Amanieu commented Oct 1, 2024

I'm not too concerned about the areg and vreg names since they are clobber-only: that means that they can't actually be specified as a register class in asm!, at most they would appear in diagnostics.

@bors r+

@bors
Copy link
Contributor

bors commented Oct 1, 2024

📌 Commit fa125e2 has been approved by Amanieu

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 1, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 1, 2024
…llaumeGomez

Rollup of 5 pull requests

Successful merges:

 - rust-lang#130630 (Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly)
 - rust-lang#131042 (Instantiate binders in `supertrait_vtable_slot`)
 - rust-lang#131079 (Update wasm-component-ld to 0.5.9)
 - rust-lang#131085 (make test_lots_of_insertions test take less long in Miri)
 - rust-lang#131088 (add fixme to remove LLVM_ENABLE_TERMINFO when minimal llvm version is 19)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors closed this in 344b6a1 Oct 1, 2024
@bors bors merged commit 344b6a1 into rust-lang:master Oct 1, 2024
6 checks passed
@taiki-e taiki-e deleted the s390x-clobber-abi branch October 1, 2024 19:29
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Oct 1, 2024
Rollup merge of rust-lang#130630 - taiki-e:s390x-clobber-abi, r=Amanieu

Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly

This supports `clobber_abi` which is one of the requirements of stabilization mentioned in rust-lang#93335.

This also supports vector registers (as `vreg`) and access registers (as `areg`) as clobber-only, which need to support clobbering of them to implement clobber_abi.

Refs:
- "1.2.1.1. Register Preservation Rules" section in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
- Register definition in LLVM:
  - Vector registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L249
  - Access registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L332

I have three questions:
- ~~ELF Application Binary Interface s390x Supplement says that `cc` (condition code, bits 18-19 of PSW) is "Volatile".
  However, we do not have a register class for `cc` and instead mark `cc` as clobbered unless `preserves_flags` is specified (rust-lang#111331).
  Therefore, in the current implementation, if both `preserves_flags` and `clobber_abi` are specified, `cc` is not marked as clobbered. Is this okay? Or even if `preserves_flags` is used, should `cc` be marked as clobbered if `clobber_abi` is used?~~ UPDATE: resolved rust-lang#130630 (comment)
- ~~ELF Application Binary Interface s390x Supplement says that `pm` (program mask, bits 20-23 of PSW) is "Cleared".
  There does not appear to be any registers associated with this in either [LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td) or [GCC](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L407-L431), so at this point I don't see any way other than to just ignore it. Is this okay as-is?~~ UPDATE: resolved rust-lang#130630 (comment)
- Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and `reg_addr`, which uses the “a” constraint (rust-lang#119431)...

Note:

- GCC seems to [recognize only `a0` and `a1`](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L428-L429), and using `a[2-15]` [causes errors](https://godbolt.org/z/a46vx8jjn).
  Given that cg_gcc has a similar problem with other architecture (rust-lang/rustc_codegen_gcc#485), I don't feel this is a blocker for this PR, but it is worth mentioning here.
- `vreg` should be able to accept `#[repr(simd)]` types as input if the `vector` target feature added in rust-lang#127506 is enabled, but core_arch has no s390x vector type and both `#[repr(simd)]` and `core::simd` are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... rust-lang#88245 (comment)

cc `@uweigand`

r? `@Amanieu`

`@rustbot` label +O-SystemZ
antoyo pushed a commit to rust-lang/rustc_codegen_gcc that referenced this pull request Oct 9, 2024
Support clobber_abi and vector/access registers (clobber-only) in s390x inline assembly

This supports `clobber_abi` which is one of the requirements of stabilization mentioned in #93335.

This also supports vector registers (as `vreg`) and access registers (as `areg`) as clobber-only, which need to support clobbering of them to implement clobber_abi.

Refs:
- "1.2.1.1. Register Preservation Rules" section in ELF Application Binary Interface s390x Supplement, Version 1.6.1 (lzsabi_s390x.pdf in https://github.com/IBM/s390x-abi/releases/tag/v1.6.1)
- Register definition in LLVM:
  - Vector registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L249
  - Access registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td#L332

I have three questions:
- ~~ELF Application Binary Interface s390x Supplement says that `cc` (condition code, bits 18-19 of PSW) is "Volatile".
  However, we do not have a register class for `cc` and instead mark `cc` as clobbered unless `preserves_flags` is specified (rust-lang/rust#111331).
  Therefore, in the current implementation, if both `preserves_flags` and `clobber_abi` are specified, `cc` is not marked as clobbered. Is this okay? Or even if `preserves_flags` is used, should `cc` be marked as clobbered if `clobber_abi` is used?~~ UPDATE: resolved rust-lang/rust#130630 (comment)
- ~~ELF Application Binary Interface s390x Supplement says that `pm` (program mask, bits 20-23 of PSW) is "Cleared".
  There does not appear to be any registers associated with this in either [LLVM](https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td) or [GCC](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L407-L431), so at this point I don't see any way other than to just ignore it. Is this okay as-is?~~ UPDATE: resolved rust-lang/rust#130630 (comment)
- Is "areg" a good name for register class name for access registers? It may be a bit confusing between that and `reg_addr`, which uses the “a” constraint (rust-lang/rust#119431)...

Note:

- GCC seems to [recognize only `a0` and `a1`](https://github.com/gcc-mirror/gcc/blob/33ccc1314dcdb0b988a9276ca6b6ce9b07bea21e/gcc/config/s390/s390.h#L428-L429), and using `a[2-15]` [causes errors](https://godbolt.org/z/a46vx8jjn).
  Given that cg_gcc has a similar problem with other architecture (#485), I don't feel this is a blocker for this PR, but it is worth mentioning here.
- `vreg` should be able to accept `#[repr(simd)]` types as input if the `vector` target feature added in rust-lang/rust#127506 is enabled, but core_arch has no s390x vector type and both `#[repr(simd)]` and `core::simd` are unstable, so I have not implemented it in this PR. EDIT: And supporting it is probably more complex than doing the equivalent on other architectures... rust-lang/rust#88245 (comment)

cc `@uweigand`

r? `@Amanieu`

`@rustbot` label +O-SystemZ
@rustbot rustbot added the A-inline-assembly Area: Inline assembly (`asm!(…)`) label Oct 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) O-SystemZ Target: SystemZ processors (s390x) S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants