Skip to content

[AArch64] Stop reserved registers from being saved in prolog/epilog #138448

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

yasuna-oribe
Copy link

@yasuna-oribe yasuna-oribe commented May 4, 2025

GCC's documentation is clear on how -ffixed-reg must behave:

  Treat the register named reg as a fixed register; generated
  code should never refer to it (except perhaps as a stack pointer,
  frame pointer or in some other fixed role).

This implies prolog/epilog code also must not save/restore explicitly fixed registers, even when it is callee-saved. Some projects rely on this (GCC's) behavior.

For example,

void f() {
  register uint64_t x28 asm("x28") = 0xee;
  asm volatile("" : "+r"(x28)); // avoid mov being eliminated
}

should not touch x28 outside of mov w28,#0xee.

For riscv64, clang behaves the same as GCC, so I am inclined to believe this is indeed a bug.

Fixes #111379.

Copy link

github-actions bot commented May 4, 2025

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented May 4, 2025

@llvm/pr-subscribers-backend-aarch64

Author: None (yasuna-oribe)

Changes

GCC's man page is clear on how -ffixed-reg must behave:

  Treat the register named reg as a fixed register; generated
  code should never refer to it (except perhaps as a stack pointer,
  frame pointer or in some other fixed role).

This implies prolog/epilog code also must not save/restore explicitly fixed registers, even when it is callee-saved. Some projects rely on this (GCC's) behavior.

For example,

void f() {
  register uint64_t x28 asm("x28") = 0xee;
  asm volatile("" : "+r"(x28)); // avoid mov being eliminated
}

should not touch x28 outside of mov w28,#<!-- -->0xee.

For riscv64, clang behaves the same as GCC, so I am inclined to believe this is indeed a bug.

Fixes #111379.


Full diff: https://github.com/llvm/llvm-project/pull/138448.diff

1 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64FrameLowering.cpp (+7)
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 78ac57e3e92a6..2d72f8757d7c0 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -3619,6 +3619,13 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
     if (Reg == BasePointerReg)
       SavedRegs.set(Reg);
 
+    // Don't save fixed registers specified with -ffixed-reg.
+    if (AArch64::GPR64RegClass.contains(Reg) &&
+        RegInfo->isReservedReg(MF, Reg)) {
+      SavedRegs.reset(Reg);
+      continue;
+    }
+
     bool RegUsed = SavedRegs.test(Reg);
     unsigned PairedReg = AArch64::NoRegister;
     const bool RegIsGPR64 = AArch64::GPR64RegClass.contains(Reg);

@yasuna-oribe yasuna-oribe changed the title [AArch64] Fix reserved registers being saved in prolog/epilog [AArch64] Stop reserved registers from being saved in prolog/epilog May 4, 2025
@yasuna-oribe yasuna-oribe marked this pull request as draft May 4, 2025 13:17
@yasuna-oribe

This comment was marked as resolved.

…/epilog

GCC's man page is clear on how -ffixed-reg must behave:
```
  Treat the register named reg as a fixed register; generated
  code should never refer to it (except perhaps as a stack pointer,
  frame pointer or in some other fixed role).
```

This implies prolog/epilog code also must not save/restore explicitly
fixed registers, even when it is callee-saved. Some projects rely on
this (GCC's) behavior.

For example,
```
void f() {
  register uint64_t x28 asm("x28") = 0xee;
  asm volatile("" : "+r"(x28)); // avoid mov being eliminated
}
```
should not touch x28 outside of `mov w28,#0xee`.

For riscv64 clang behaves the same as GCC.

Fixes llvm#111379.
@yasuna-oribe yasuna-oribe marked this pull request as ready for review May 4, 2025 15:40
@yasuna-oribe
Copy link
Author

Yep, tests succeeded now. I'm sorry for the force push, I just noticed I'm supposed to use git --fixup.
ping @davemgreen @sjoerdmeijer @nasherm @smithp35 (Is this how I'm supposed to ping people?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

-ffixed-reg option not respected in function prolog/epilog
2 participants