[PATCH] D125787: [RISCV] Fix RVV stack frame alignment bugs

Fraser Cormack via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue May 17 07:02:48 PDT 2022


frasercrmck created this revision.
frasercrmck added reviewers: rogfer01, HsiangKai, kito-cheng, craig.topper, StephenFan.
Herald added subscribers: sunshaoce, VincentWu, luke957, vkmr, evandro, luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, edward-jones, zzheng, jrtc27, shiva0217, niosHD, sabuasal, simoncook, johnrusso, rbar, asb, hiraditya, arichardson, qcolombet.
Herald added a project: All.
frasercrmck requested review of this revision.
Herald added subscribers: llvm-commits, pcwang-thead, eopXD, MaskRay.
Herald added a project: LLVM.

This patch addresses several alignment issues in the stack frame when
RVV objects are taken into account.

One bug is that the RVV stack was never guaranteed to keep the alignment
of the stack *as a whole*. We must maintain a 16-byte aligned stack at
all times, especially when calling other functions. With the standard V
extension, this is conveniently happening since VLEN is at least 128 and
always 16-byte aligned. However, we support Zvl64b which does not
guarantee this. To fix this, the RVV stack size is rounded up to be
aligned to 16 bytes. This in practice generally makes us allocate a
stack sized at least 2*VLEN in size, and a multiple of 2.

  |------------------------------| -- <-- FP
  | 8-byte callee-save           | |      |
  |------------------------------| |      |
  | one VLENB-sized RVV object   | |      |
  |------------------------------| |      |
  | 8-byte local variable        | |      |
  |------------------------------| -- <-- SP (must be aligned to 16)

In the example above, with Zvl64b we are decrementing SP by 12 bytes
which does not leave SP correctly aligned. We therefore introduce an
extra VLENB-sized amount used for alignment. This would therefore ensure
the total stack size was 16 bytes (48 for Zvl128b, 80 for Zvl256b, etc):

  |------------------------------| -- <-- FP
  | 8-byte callee-save           | |      |
  |------------------------------| |      |
  | one VLENB-sized padding obj  | |      |
  | one VLENB-sized RVV object   | |      |
  |------------------------------| |      |
  | 8-byte local variable        | |      |
  |------------------------------| -- <-- SP

A new RVV invariant has been introduced in this patch, which is that the
base of the RVV stack itself is now always aligned to 16 bytes, not 8 as
before. This keeps us more in line with the scalar stack and should be
easier to reason about. The calculation of the RVV padding has thus
changed to be the amount required to align the scalar local variable
section to the RVV section's alignment. This amount is further rounded
up when setting up the initial stack to keep everything aligned:

  |------------------------------| -- <-- FP
  | 8-byte callee-save           |
  |------------------------------|
  |                              |
  | RVV objects                  |
  | (aligned to at least 16)     |
  |                              |
  |------------------------------|
  | RVV padding of 8 bytes       |
  |------------------------------|
  | 8-byte local variable        |
  |------------------------------| -- <-- SP

In the example above, it's clear that we need 8 bytes of padding to keep
the RVV section aligned to 16 when using SP. But to keep SP *itself*
aligned to 16 we can't decrement the initial stack pointer by 24 - we
have to round up to 32.

A second bug fixed during this process was that it is not sufficient to
add padding only when there's no FP. We need it any time we address
objects using SP. For example, in the case that the stack is dynamically
realigned, we do have an FP to restore the SP with, but we still require
alignment padding because we use SP to access objects. We were
previously omitting padding here.

With the RVV section correctly aligned, the third and final bug fixed by
this patch is that RVV objects themselves are now correctly aligned. We
were previously only guaranteeing an alignment of 8 bytes, even if they
required a higher alignment. This is relatively simple and in practice
we see more rounding up of VLEN amounts to account for alignment in
between objects:

  |------------------------------|
  | RVV object (aligned to 16)   |
  |------------------------------|
  | no padding necessary         |
  |------------------------------|
  | 2*VLENB RVV object (align 16)|
  |------------------------------|
  | VLENB alignment padding      |
  |------------------------------|
  | RVV object (align 32)        |
  |------------------------------|
  | 3*VLENB alignment padding    |
  |------------------------------|
  | VLENB RVV object (align 32)  |
  |------------------------------| -- <-- base of RVV section

Note that a lot of the regressions in codegen owing to the new alignment
rules are correct but actually only strictly necessary for Zvl64b (and
Zvl32b but that's not really supported). I plan a follow-up patch to
take the known VLEN into account when padding for alignment.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125787

Files:
  llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
  llvm/lib/Target/RISCV/RISCVFrameLowering.h
  llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
  llvm/test/CodeGen/RISCV/rvv/access-fixed-objects-by-rvv.ll
  llvm/test/CodeGen/RISCV/rvv/addi-scalable-offset.mir
  llvm/test/CodeGen/RISCV/rvv/allocate-lmul-2-4-8.ll
  llvm/test/CodeGen/RISCV/rvv/calling-conv-fastcc.ll
  llvm/test/CodeGen/RISCV/rvv/calling-conv.ll
  llvm/test/CodeGen/RISCV/rvv/emergency-slot.mir
  llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert-subvector.ll
  llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpscatter.ll
  llvm/test/CodeGen/RISCV/rvv/localvar.ll
  llvm/test/CodeGen/RISCV/rvv/memory-args.ll
  llvm/test/CodeGen/RISCV/rvv/no-reserved-frame.ll
  llvm/test/CodeGen/RISCV/rvv/rv32-spill-vector-csr.ll
  llvm/test/CodeGen/RISCV/rvv/rv32-spill-vector.ll
  llvm/test/CodeGen/RISCV/rvv/rv32-spill-zvlsseg.ll
  llvm/test/CodeGen/RISCV/rvv/rv64-spill-vector-csr.ll
  llvm/test/CodeGen/RISCV/rvv/rv64-spill-vector.ll
  llvm/test/CodeGen/RISCV/rvv/rv64-spill-zvlsseg.ll
  llvm/test/CodeGen/RISCV/rvv/rvv-args-by-mem.ll
  llvm/test/CodeGen/RISCV/rvv/rvv-framelayout.ll
  llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir
  llvm/test/CodeGen/RISCV/rvv/scalar-stack-align.ll
  llvm/test/CodeGen/RISCV/rvv/wrong-stack-offset-for-rvv-object.mir
  llvm/test/CodeGen/RISCV/rvv/wrong-stack-slot-rv64.mir

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D125787.430046.patch
Type: text/x-patch
Size: 98934 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220517/6d603e06/attachment.bin>


More information about the llvm-commits mailing list