This is an archive of the discontinued LLVM Phabricator instance.

[RISCV][NFCI] Set TransientStackAlignment and rely on it rather than RVV-specific logic on RVV-less functions
ClosedPublic

Authored by asb on Jul 19 2022, 2:02 AM.

Details

Summary

This should be a fairly simple refactoring, but anything related to stack frames is fiddly enough I feel it's worth at least a quick review.

  • TargetFrameLowering has a TransientStackAlignment field that "returns the number of bytes to which the stack pointer must be aligned at all times, even between calls.
    • As explained in the RISC-V calling convention, the stack pointer must remain fully aligned throughout execution for compliant code. This is important for embedded targets that might avoid realigning the stack pointer for interrupt service routines. Systems running full OSes may always realign the stack anyway. I've added a FIXME that we may want to revisit it.
  • TransientStackAlignment is used in estimateStackSize in MachineFrameInfo and in PEI::calculateFrameObjectOffsets.
    • estimateStackSize is only used in the RISC-V backend for scavenging slots. It may be possible to craft a function where the difference is observable, but it wouldn't be a meaningful test.
    • calculateFrameObjectOffsets makes use of TransientStackAlignment, but then sets the stack alignment to the max of that alignment and MaxAlign, which is unconditionally set to 16 in RISCVFrameLowering::processFunctionBeforeFrameFinalized
    • I've changed this logic to only set MaxAlign if there are RVV frame objects. There should be no functional change here for either RVV targets (MaxAlign is set as before) or non-RVV targets (TransientStackAlign is now 16 anyway).

I could split this into separate patches for TransientStackAlign and the processFunctionBeforeFrameFinalized change if desired.

Diff Detail

Event Timeline

asb created this revision.Jul 19 2022, 2:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 2:02 AM
asb requested review of this revision.Jul 19 2022, 2:02 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 2:02 AM
asb updated this revision to Diff 445738.Jul 19 2022, 2:04 AM
frasercrmck accepted this revision.Jul 20 2022, 6:30 AM

LGTM, thanks for the well-written description.

This revision is now accepted and ready to land.Jul 20 2022, 6:30 AM
asb added a comment.Jul 21 2022, 2:26 AM

Thanks for the review @frasercrmck. As I'd hate to add a misleading comment to the codebase, perhaps someone (@jrtc27, @kito-cheng perhaps?) could confirm if my understanding that TransientStackAlignment is unlikely to be needed on systems running e.g. Linux or FreeBSD is correct? i.e. they'll always realign or use a separate stack in any interrupt handlers?

asb added a comment.Aug 1 2022, 8:26 AM

Thanks for the review @frasercrmck. As I'd hate to add a misleading comment to the codebase, perhaps someone (@jrtc27, @kito-cheng perhaps?) could confirm if my understanding that TransientStackAlignment is unlikely to be needed on systems running e.g. Linux or FreeBSD is correct? i.e. they'll always realign or use a separate stack in any interrupt handlers?

Friendly to @jrtc27 @kito-cheng on this point. Thanks in advance.

kito-cheng accepted this revision.Aug 1 2022, 8:56 AM

Leave some comment before but apparently I never click submit.


Traced related implementation in LLVM, the comment say it means the number of bytes to stack alignment all the time[1], so according the description this should always set to the stack alignment which psABI required no matter it's baremetal or not:

  • Linux require this be true since the stack space of signal handler will based on the current stack, and signal could be happened in any time, so the stack must align to ABI stack alignment.
  • Bare-metal might also use stack pointer directly in the interrupter handler just like signal handler, so that's same situation as signal handler, we need always make sure this align to ABI stack alignment.

So LGTM, but I think the FIXME could be removed since I think it's also true for non-baremetal - at least for Linux (I don't know too much about other OS like FreeBSD).

[1]
llvm/include/llvm/CodeGen/TargetFrameLowering.h

/// getTransientStackAlignment - This method returns the number of bytes to
/// which the stack pointer must be aligned at all times, even between
/// calls.

More info about linux signal behavior:

Default stack based on normal process stack, but could setup a separated stack if requested

Ref:
https://man7.org/linux/man-pages/man7/signal.7.html

...
       By default, a signal handler is invoked on the normal process
       stack.  It is possible to arrange that the signal handler uses an
       alternate stack; see sigaltstack(2) for a discussion of how to do
       this and when it might be useful.
...
asb added a comment.Aug 2 2022, 1:43 AM

Thanks Kito - I'll drop the FIXME and land this.

This revision was landed with ongoing or failed builds.Aug 2 2022, 1:46 AM
This revision was automatically updated to reflect the committed changes.