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

Basic inline assembly support for SPARC and SPARC64 #132472

Merged
merged 1 commit into from
Nov 7, 2024

Conversation

taiki-e
Copy link
Member

@taiki-e taiki-e commented Nov 1, 2024

This implements asm_experimental_arch (tracking issue #93335) for SPARC and SPARC64.

This PR includes:

  • General-purpose registers r[0-31] (reg register class, LLVM/GCC constraint r)
    Supported types: i8, i16, i32, i64 (SPARC64-only)
    Aliases: g[0-7] (r[0-7]), o[0-7] (r[8-15]), l[0-7] (r[16-23]), i[0-7] (r[24-31])
  • y register (clobber-only, needed for clobber_abi)
  • preserves_flags: Integer condition codes (icc, xcc) and floating-point condition codes (fcc*)

The following are not included:

  • 64-bit integer support on SPARC-V8+'s global or out registers (g[0-7], o[0-7]): GCC's h constraint (it seems that there is no corresponding constraint in LLVM?)
  • Floating-point registers (LLVM/GCC constraint e/f):
    I initially tried to implement this, but postponed it for now because there seemed to be several parts in LLVM that behaved differently than in the LangRef's description.
  • clobber_abi: Support for floating-point registers is needed.

Refs:

cc @thejpster (sparc-unknown-none-elf target maintainer)
(AFAIK, other sparc/sprac64 targets don't have target maintainers)

r? @Amanieu

@rustbot label +O-SPARC +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 Nov 1, 2024
@rustbot
Copy link
Collaborator

rustbot commented Nov 1, 2024

Some changes occurred in compiler/rustc_codegen_gcc

cc @antoyo, @GuillaumeGomez

@rustbot rustbot added A-inline-assembly Area: Inline assembly (`asm!(…)`) O-SPARC Target: SPARC processors labels Nov 1, 2024
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@taiki-e
Copy link
Member Author

taiki-e commented Nov 1, 2024

/checkout/tests/ui/asm/bad-arch.rs: revision [unspecified] should specify needs-llvm-components: as it has --target set

Hmm, but when I set needs-llvm-components, I got:

/checkout/tests/ui/asm/bad-arch.rs: revision [unspecified] specifies unknown LLVM component xtensa

IIUC, it seems difficult to retain this test since there is no builtin target other than xtensa that does not support inline assembly in rust-lang/rust after this PR, and xtensa can probably support inline assembly in LLVM 20 (llvm/llvm-project@dc2d0d5, inline assembly itself is already supported in esp-rs fork).

UPDATE: removed this test

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Nov 5, 2024

☔ The latest upstream changes (presumably #129884) made this pull request unmergeable. Please resolve the merge conflicts.

| SPARC | `r0`/`g0` | This is always zero and cannot be used as inputs or outputs. |
| SPARC | `r1`/`g1` | Used internally by LLVM. |
| SPARC | `r6`/`g6`, `r7`/`g7` | Reserved for system. |
| SPARC | `r31`/`i7` | Return address cannot be used as inputs or outputs. |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i6/o6 also need to be added to the list of stack/frame pointers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And g5 needs to be mentioned as reserved on sparc32.

Copy link
Member Author

@taiki-e taiki-e Nov 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I have updated docs to mention them.

) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => {
// FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better expressed as "v9": I64 in the macro. The feature name can later be changed to v8plus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That constraint is not yet supported in LLVM, so I have updated the FIXME comment to use the way you mention.

types! {
_: I8, I16, I32;
// FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC),
// but not yet supported in LLVM.
// v8plus: I64;
}

_target: &Target,
_is_clobber: bool,
) -> Result<(), &'static str> {
if is_v7_or_v8(arch, target_features) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition used in LLVM is Subtarget.is64Bit(), not whether v8plus is supported. So this should check for InlineAsmArch::Sparc64 instead.

Copy link
Member Author

@taiki-e taiki-e Nov 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Section 2.1.5 "Function Registers with Unassigned Roles" of the V8+ Technical Specification says "%g5; no longer reserved for system software" 1, and LLVM does not seem to match it.

I have changed the condition to Sparc64 vs Sparc and left a FIXME comment mentioning the mismatch between LLVM and the specification.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(The above change removes the need for the addition of the target feature in this PR. It is still needed for other purposes but will be handled in another PR: #132552)

@Amanieu
Copy link
Member

Amanieu commented Nov 7, 2024

I would expect all the FIXME to be resolved before stabilization, but this is good enough for nightly.

@bors r+

@bors
Copy link
Contributor

bors commented Nov 7, 2024

📌 Commit 241f82a 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 Nov 7, 2024
@matthiaskrgr
Copy link
Member

@bors rollup=iffy

@bors
Copy link
Contributor

bors commented Nov 7, 2024

⌛ Testing commit 241f82a with merge b91a3a0...

@bors
Copy link
Contributor

bors commented Nov 7, 2024

☀️ Test successful - checks-actions
Approved by: Amanieu
Pushing b91a3a0 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Nov 7, 2024
@bors bors merged commit b91a3a0 into rust-lang:master Nov 7, 2024
7 checks passed
@rustbot rustbot added this to the 1.84.0 milestone Nov 7, 2024
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (b91a3a0): comparison URL.

Overall result: ❌ regressions - no action needed

@rustbot label: -perf-regression

Instruction count

This is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.8% [0.8%, 0.8%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary -0.7%, secondary -1.9%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
1.3% [1.3%, 1.3%] 1
Regressions ❌
(secondary)
2.2% [2.2%, 2.2%] 1
Improvements ✅
(primary)
-2.7% [-2.7%, -2.7%] 1
Improvements ✅
(secondary)
-2.9% [-4.4%, -2.1%] 4
All ❌✅ (primary) -0.7% [-2.7%, 1.3%] 2

Cycles

Results (primary 2.3%, secondary 7.5%)

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.3% [2.3%, 2.3%] 1
Regressions ❌
(secondary)
7.5% [6.7%, 8.2%] 4
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.3% [2.3%, 2.3%] 1

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 780.698s -> 781.906s (0.15%)
Artifact size: 335.29 MiB -> 335.33 MiB (0.01%)

@taiki-e taiki-e deleted the sparc-asm branch November 8, 2024 01:39
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Nov 9, 2024
…rkingjubilee

Add v9, v8plus, and leoncasa target feature to sparc and use v8plus in create_object_file

This adds the following three unstable target features:

- `v9`: SPARC-V9 instructions ([LLVM definition][sparc-v9])
  - Relevant to rust-lang#131222 (comment)
  - Relevant to rust-lang#132472 (comment)
  - This is also needed to implement taiki-e/atomic-maybe-uninit#31 (depends on inline assembly support) more robustly.
- `v8plus`: SPARC-V8+ ABI ([LLVM definition][sparc-v8plus])
  - This is added in LLVM 20. In LLVM 19 and older, it is emulated to work the same way as LLVM in each LLVM version.
  - See rust-lang#132585 (comment) for more.
- `leoncasa`: CASA instruction[^1] of LEON3 and LEON4 processors ([LLVM definition][sparc-leoncasa], LLVM feature name: `hasleoncasa`)
  - This is needed to implement taiki-e/atomic-maybe-uninit#31 (depends on inline assembly support) more robustly.

[^1]: Atomic CAS instruction

[sparc-v9]: https://github.com/llvm/llvm-project/blob/f5e4ffaa49254706ad6fa209de8aec28e20f0041/llvm/lib/Target/Sparc/Sparc.td#L37-L39
[sparc-v8plus]: https://github.com/llvm/llvm-project/blob/f5e4ffaa49254706ad6fa209de8aec28e20f0041/llvm/lib/Target/Sparc/Sparc.td#L37-L39
[sparc-leoncasa]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/LeonFeatures.td#L32-L37
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 9, 2024
Rollup merge of rust-lang#132552 - taiki-e:sparc-target-feature, r=workingjubilee

Add v9, v8plus, and leoncasa target feature to sparc and use v8plus in create_object_file

This adds the following three unstable target features:

- `v9`: SPARC-V9 instructions ([LLVM definition][sparc-v9])
  - Relevant to rust-lang#131222 (comment)
  - Relevant to rust-lang#132472 (comment)
  - This is also needed to implement taiki-e/atomic-maybe-uninit#31 (depends on inline assembly support) more robustly.
- `v8plus`: SPARC-V8+ ABI ([LLVM definition][sparc-v8plus])
  - This is added in LLVM 20. In LLVM 19 and older, it is emulated to work the same way as LLVM in each LLVM version.
  - See rust-lang#132585 (comment) for more.
- `leoncasa`: CASA instruction[^1] of LEON3 and LEON4 processors ([LLVM definition][sparc-leoncasa], LLVM feature name: `hasleoncasa`)
  - This is needed to implement taiki-e/atomic-maybe-uninit#31 (depends on inline assembly support) more robustly.

[^1]: Atomic CAS instruction

[sparc-v9]: https://github.com/llvm/llvm-project/blob/f5e4ffaa49254706ad6fa209de8aec28e20f0041/llvm/lib/Target/Sparc/Sparc.td#L37-L39
[sparc-v8plus]: https://github.com/llvm/llvm-project/blob/f5e4ffaa49254706ad6fa209de8aec28e20f0041/llvm/lib/Target/Sparc/Sparc.td#L37-L39
[sparc-leoncasa]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/LeonFeatures.td#L32-L37
mati865 pushed a commit to mati865/rust that referenced this pull request Nov 12, 2024
…rkingjubilee

Add v9, v8plus, and leoncasa target feature to sparc and use v8plus in create_object_file

This adds the following three unstable target features:

- `v9`: SPARC-V9 instructions ([LLVM definition][sparc-v9])
  - Relevant to rust-lang#131222 (comment)
  - Relevant to rust-lang#132472 (comment)
  - This is also needed to implement taiki-e/atomic-maybe-uninit#31 (depends on inline assembly support) more robustly.
- `v8plus`: SPARC-V8+ ABI ([LLVM definition][sparc-v8plus])
  - This is added in LLVM 20. In LLVM 19 and older, it is emulated to work the same way as LLVM in each LLVM version.
  - See rust-lang#132585 (comment) for more.
- `leoncasa`: CASA instruction[^1] of LEON3 and LEON4 processors ([LLVM definition][sparc-leoncasa], LLVM feature name: `hasleoncasa`)
  - This is needed to implement taiki-e/atomic-maybe-uninit#31 (depends on inline assembly support) more robustly.

[^1]: Atomic CAS instruction

[sparc-v9]: https://github.com/llvm/llvm-project/blob/f5e4ffaa49254706ad6fa209de8aec28e20f0041/llvm/lib/Target/Sparc/Sparc.td#L37-L39
[sparc-v8plus]: https://github.com/llvm/llvm-project/blob/f5e4ffaa49254706ad6fa209de8aec28e20f0041/llvm/lib/Target/Sparc/Sparc.td#L37-L39
[sparc-leoncasa]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/LeonFeatures.td#L32-L37
mati865 pushed a commit to mati865/rust that referenced this pull request Nov 12, 2024
Basic inline assembly support for SPARC and SPARC64

This implements asm_experimental_arch (tracking issue rust-lang#93335) for SPARC and SPARC64.

This PR includes:

- General-purpose registers `r[0-31]` (`reg` register class, LLVM/GCC constraint `r`)
  Supported types: i8, i16, i32, i64 (SPARC64-only)
  Aliases: `g[0-7]` (`r[0-7]`), `o[0-7]` (`r[8-15]`), `l[0-7]` (`r[16-23]`), `i[0-7]` (`r[24-31]`)
- `y` register (clobber-only, needed for clobber_abi)
- preserves_flags: Integer condition codes (`icc`, `xcc`) and floating-point condition codes (`fcc*`)

The following are *not* included:

- 64-bit integer support on SPARC-V8+'s global or out registers (`g[0-7]`, `o[0-7]`): GCC's `h` constraint (it seems that there is no corresponding constraint in LLVM?)
- Floating-point registers (LLVM/GCC constraint `e`/`f`):
  I initially tried to implement this, but postponed it for now because there seemed to be several parts in LLVM that behaved differently than in the LangRef's description.
- clobber_abi: Support for floating-point registers is needed.

Refs:
- LLVM
  - Reserved registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L52
  - Register definitions https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.td
  - Supported constraints https://llvm.org/docs/LangRef.html#supported-constraint-code-list
- GCC
  - Reserved registers https://github.com/gcc-mirror/gcc/blob/63b6967b06b5387821c4e5f2c113da6aaeeae2b7/gcc/config/sparc/sparc.h#L633-L658
  - Supported constraints https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
- SPARC ISA/ABI
  - (64-bit ISA) The SPARC Architecture Manual, Version 9
    (32-bit ISA) The SPARC Architecture Manual, Version 8
    (64-bit ABI) System V Application Binary Interface SPARC Version 9 Processor Supplement, Rev 1.35
    (32-bit ABI) System V Application Binary Interface SPARC Processor Supplement, Third Edition
    The above docs can be downloaded from https://sparc.org/technical-documents
  - (32-bit V8+ ABI) The V8+ Technical Specification
    https://temlib.org/pub/SparcStation/Standards/V8plus.pdf

cc `@thejpster` (sparc-unknown-none-elf target maintainer)
(AFAIK, other sparc/sprac64 targets don't have target maintainers)

r? `@Amanieu`

`@rustbot` label +O-SPARC +A-inline-assembly
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!(…)`) merged-by-bors This PR was explicitly merged by bors. O-SPARC Target: SPARC processors 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.

7 participants