Skip to content

Commit

Permalink
[RISCV] Fix the CFI offset for callee-saved registers stored by Zcmp …
Browse files Browse the repository at this point in the history
…push.

Issue mentioned: riscvarchive/riscv-code-size-reduction#182

The order of callee-saved registers stored by Zcmp push in memory is reversed.

Pseudo code for cm.push in https://github.com/riscv/riscv-code-size-reduction/releases/download/v1.0.4-1/Zc.1.0.4-1.pdf

```
if (XLEN==32) bytes=4; else bytes=8;

addr=sp-bytes;
for(i in 27,26,25,24,23,22,21,20,19,18,9,8,1)  {
  //if register i is in xreg_list
  if (xreg_list[i]) {
    switch(bytes) {
      4:  asm("sw x[i], 0(addr)");
      8:  asm("sd x[i], 0(addr)");
    }
    addr-=bytes;
  }
}
```

The placement order for push is s11, s10, ..., ra.

CFI offset should be calculed as reversed order for correct stack unwinding.

Reviewed By: fakepaper56, kito-cheng

Differential Revision: https://reviews.llvm.org/D156437
  • Loading branch information
tclin914 committed Aug 2, 2023
1 parent 9c38a17 commit d6a48a3
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 67 deletions.
13 changes: 10 additions & 3 deletions llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,11 +581,18 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
int64_t Offset;
// Offsets for objects with fixed locations (IE: those saved by libcall) are
// simply calculated from the frame index.
if (FrameIdx < 0)
Offset = FrameIdx * (int64_t) STI.getXLen() / 8;
else
if (FrameIdx < 0) {
if (RVFI->isPushable(MF)) {
// Callee-saved register stored by Zcmp push is in reverse order.
Offset = -(FrameIdx + RVFI->getRVPushRegs() + 1) *
(int64_t)STI.getXLen() / 8;
} else {
Offset = FrameIdx * (int64_t)STI.getXLen() / 8;
}
} else {
Offset = MFI.getObjectOffset(FrameIdx) -
RVFI->getLibCallStackSize();
}
Register Reg = Entry.getReg();
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
nullptr, RI->getDwarfRegNum(Reg, true), Offset));
Expand Down
128 changes: 64 additions & 64 deletions llvm/test/CodeGen/RISCV/push-pop-popret.ll
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ define i32 @pushpopret0(i32 signext %size){
; RV32IZCMP: # %bb.0: # %entry
; RV32IZCMP-NEXT: cm.push {ra, s0}, -16
; RV32IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: .cfi_offset s0, -8
; RV32IZCMP-NEXT: .cfi_offset ra, -8
; RV32IZCMP-NEXT: .cfi_offset s0, -4
; RV32IZCMP-NEXT: addi s0, sp, 16
; RV32IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-NEXT: addi a0, a0, 15
Expand All @@ -115,8 +115,8 @@ define i32 @pushpopret0(i32 signext %size){
; RV64IZCMP: # %bb.0: # %entry
; RV64IZCMP-NEXT: cm.push {ra, s0}, -16
; RV64IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: .cfi_offset s0, -16
; RV64IZCMP-NEXT: .cfi_offset ra, -16
; RV64IZCMP-NEXT: .cfi_offset s0, -8
; RV64IZCMP-NEXT: addi s0, sp, 16
; RV64IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-NEXT: slli a0, a0, 32
Expand Down Expand Up @@ -221,8 +221,8 @@ define i32 @pushpopret1(i32 signext %size) {
; RV32IZCMP: # %bb.0: # %entry
; RV32IZCMP-NEXT: cm.push {ra, s0}, -16
; RV32IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: .cfi_offset s0, -8
; RV32IZCMP-NEXT: .cfi_offset ra, -8
; RV32IZCMP-NEXT: .cfi_offset s0, -4
; RV32IZCMP-NEXT: addi s0, sp, 16
; RV32IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-NEXT: addi a0, a0, 15
Expand All @@ -238,8 +238,8 @@ define i32 @pushpopret1(i32 signext %size) {
; RV64IZCMP: # %bb.0: # %entry
; RV64IZCMP-NEXT: cm.push {ra, s0}, -16
; RV64IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: .cfi_offset s0, -16
; RV64IZCMP-NEXT: .cfi_offset ra, -16
; RV64IZCMP-NEXT: .cfi_offset s0, -8
; RV64IZCMP-NEXT: addi s0, sp, 16
; RV64IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-NEXT: slli a0, a0, 32
Expand Down Expand Up @@ -345,8 +345,8 @@ define i32 @pushpopretneg1(i32 signext %size) {
; RV32IZCMP: # %bb.0: # %entry
; RV32IZCMP-NEXT: cm.push {ra, s0}, -16
; RV32IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: .cfi_offset s0, -8
; RV32IZCMP-NEXT: .cfi_offset ra, -8
; RV32IZCMP-NEXT: .cfi_offset s0, -4
; RV32IZCMP-NEXT: addi s0, sp, 16
; RV32IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-NEXT: addi a0, a0, 15
Expand All @@ -362,8 +362,8 @@ define i32 @pushpopretneg1(i32 signext %size) {
; RV64IZCMP: # %bb.0: # %entry
; RV64IZCMP-NEXT: cm.push {ra, s0}, -16
; RV64IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: .cfi_offset s0, -16
; RV64IZCMP-NEXT: .cfi_offset ra, -16
; RV64IZCMP-NEXT: .cfi_offset s0, -8
; RV64IZCMP-NEXT: addi s0, sp, 16
; RV64IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-NEXT: slli a0, a0, 32
Expand Down Expand Up @@ -469,8 +469,8 @@ define i32 @pushpopret2(i32 signext %size) {
; RV32IZCMP: # %bb.0: # %entry
; RV32IZCMP-NEXT: cm.push {ra, s0}, -16
; RV32IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: .cfi_offset s0, -8
; RV32IZCMP-NEXT: .cfi_offset ra, -8
; RV32IZCMP-NEXT: .cfi_offset s0, -4
; RV32IZCMP-NEXT: addi s0, sp, 16
; RV32IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-NEXT: addi a0, a0, 15
Expand All @@ -486,8 +486,8 @@ define i32 @pushpopret2(i32 signext %size) {
; RV64IZCMP: # %bb.0: # %entry
; RV64IZCMP-NEXT: cm.push {ra, s0}, -16
; RV64IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: .cfi_offset s0, -16
; RV64IZCMP-NEXT: .cfi_offset ra, -16
; RV64IZCMP-NEXT: .cfi_offset s0, -8
; RV64IZCMP-NEXT: addi s0, sp, 16
; RV64IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-NEXT: slli a0, a0, 32
Expand Down Expand Up @@ -593,8 +593,8 @@ define dso_local i32 @tailcall(i32 signext %size) local_unnamed_addr #0 {
; RV32IZCMP: # %bb.0: # %entry
; RV32IZCMP-NEXT: cm.push {ra, s0}, -16
; RV32IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: .cfi_offset s0, -8
; RV32IZCMP-NEXT: .cfi_offset ra, -8
; RV32IZCMP-NEXT: .cfi_offset s0, -4
; RV32IZCMP-NEXT: addi s0, sp, 16
; RV32IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-NEXT: addi a0, a0, 15
Expand All @@ -609,8 +609,8 @@ define dso_local i32 @tailcall(i32 signext %size) local_unnamed_addr #0 {
; RV64IZCMP: # %bb.0: # %entry
; RV64IZCMP-NEXT: cm.push {ra, s0}, -16
; RV64IZCMP-NEXT: .cfi_def_cfa_offset 16
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: .cfi_offset s0, -16
; RV64IZCMP-NEXT: .cfi_offset ra, -16
; RV64IZCMP-NEXT: .cfi_offset s0, -8
; RV64IZCMP-NEXT: addi s0, sp, 16
; RV64IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-NEXT: slli a0, a0, 32
Expand All @@ -627,8 +627,8 @@ define dso_local i32 @tailcall(i32 signext %size) local_unnamed_addr #0 {
; RV32IZCMP-SR: # %bb.0: # %entry
; RV32IZCMP-SR-NEXT: cm.push {ra, s0}, -16
; RV32IZCMP-SR-NEXT: .cfi_def_cfa_offset 16
; RV32IZCMP-SR-NEXT: .cfi_offset ra, -4
; RV32IZCMP-SR-NEXT: .cfi_offset s0, -8
; RV32IZCMP-SR-NEXT: .cfi_offset ra, -8
; RV32IZCMP-SR-NEXT: .cfi_offset s0, -4
; RV32IZCMP-SR-NEXT: addi s0, sp, 16
; RV32IZCMP-SR-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-SR-NEXT: addi a0, a0, 15
Expand All @@ -643,8 +643,8 @@ define dso_local i32 @tailcall(i32 signext %size) local_unnamed_addr #0 {
; RV64IZCMP-SR: # %bb.0: # %entry
; RV64IZCMP-SR-NEXT: cm.push {ra, s0}, -16
; RV64IZCMP-SR-NEXT: .cfi_def_cfa_offset 16
; RV64IZCMP-SR-NEXT: .cfi_offset ra, -8
; RV64IZCMP-SR-NEXT: .cfi_offset s0, -16
; RV64IZCMP-SR-NEXT: .cfi_offset ra, -16
; RV64IZCMP-SR-NEXT: .cfi_offset s0, -8
; RV64IZCMP-SR-NEXT: addi s0, sp, 16
; RV64IZCMP-SR-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-SR-NEXT: slli a0, a0, 32
Expand Down Expand Up @@ -710,16 +710,16 @@ define i32 @nocompress(i32 signext %size) {
; RV32IZCMP: # %bb.0: # %entry
; RV32IZCMP-NEXT: cm.push {ra, s0-s8}, -48
; RV32IZCMP-NEXT: .cfi_def_cfa_offset 48
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: .cfi_offset s0, -8
; RV32IZCMP-NEXT: .cfi_offset s1, -12
; RV32IZCMP-NEXT: .cfi_offset s2, -16
; RV32IZCMP-NEXT: .cfi_offset s3, -20
; RV32IZCMP-NEXT: .cfi_offset s4, -24
; RV32IZCMP-NEXT: .cfi_offset s5, -28
; RV32IZCMP-NEXT: .cfi_offset s6, -32
; RV32IZCMP-NEXT: .cfi_offset s7, -36
; RV32IZCMP-NEXT: .cfi_offset s8, -40
; RV32IZCMP-NEXT: .cfi_offset ra, -40
; RV32IZCMP-NEXT: .cfi_offset s0, -36
; RV32IZCMP-NEXT: .cfi_offset s1, -32
; RV32IZCMP-NEXT: .cfi_offset s2, -28
; RV32IZCMP-NEXT: .cfi_offset s3, -24
; RV32IZCMP-NEXT: .cfi_offset s4, -20
; RV32IZCMP-NEXT: .cfi_offset s5, -16
; RV32IZCMP-NEXT: .cfi_offset s6, -12
; RV32IZCMP-NEXT: .cfi_offset s7, -8
; RV32IZCMP-NEXT: .cfi_offset s8, -4
; RV32IZCMP-NEXT: addi s0, sp, 48
; RV32IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-NEXT: addi a0, a0, 15
Expand Down Expand Up @@ -749,16 +749,16 @@ define i32 @nocompress(i32 signext %size) {
; RV64IZCMP: # %bb.0: # %entry
; RV64IZCMP-NEXT: cm.push {ra, s0-s8}, -80
; RV64IZCMP-NEXT: .cfi_def_cfa_offset 80
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: .cfi_offset s0, -16
; RV64IZCMP-NEXT: .cfi_offset s1, -24
; RV64IZCMP-NEXT: .cfi_offset s2, -32
; RV64IZCMP-NEXT: .cfi_offset s3, -40
; RV64IZCMP-NEXT: .cfi_offset s4, -48
; RV64IZCMP-NEXT: .cfi_offset s5, -56
; RV64IZCMP-NEXT: .cfi_offset s6, -64
; RV64IZCMP-NEXT: .cfi_offset s7, -72
; RV64IZCMP-NEXT: .cfi_offset s8, -80
; RV64IZCMP-NEXT: .cfi_offset ra, -80
; RV64IZCMP-NEXT: .cfi_offset s0, -72
; RV64IZCMP-NEXT: .cfi_offset s1, -64
; RV64IZCMP-NEXT: .cfi_offset s2, -56
; RV64IZCMP-NEXT: .cfi_offset s3, -48
; RV64IZCMP-NEXT: .cfi_offset s4, -40
; RV64IZCMP-NEXT: .cfi_offset s5, -32
; RV64IZCMP-NEXT: .cfi_offset s6, -24
; RV64IZCMP-NEXT: .cfi_offset s7, -16
; RV64IZCMP-NEXT: .cfi_offset s8, -8
; RV64IZCMP-NEXT: addi s0, sp, 80
; RV64IZCMP-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-NEXT: slli a0, a0, 32
Expand Down Expand Up @@ -790,16 +790,16 @@ define i32 @nocompress(i32 signext %size) {
; RV32IZCMP-SR: # %bb.0: # %entry
; RV32IZCMP-SR-NEXT: cm.push {ra, s0-s8}, -48
; RV32IZCMP-SR-NEXT: .cfi_def_cfa_offset 48
; RV32IZCMP-SR-NEXT: .cfi_offset ra, -4
; RV32IZCMP-SR-NEXT: .cfi_offset s0, -8
; RV32IZCMP-SR-NEXT: .cfi_offset s1, -12
; RV32IZCMP-SR-NEXT: .cfi_offset s2, -16
; RV32IZCMP-SR-NEXT: .cfi_offset s3, -20
; RV32IZCMP-SR-NEXT: .cfi_offset s4, -24
; RV32IZCMP-SR-NEXT: .cfi_offset s5, -28
; RV32IZCMP-SR-NEXT: .cfi_offset s6, -32
; RV32IZCMP-SR-NEXT: .cfi_offset s7, -36
; RV32IZCMP-SR-NEXT: .cfi_offset s8, -40
; RV32IZCMP-SR-NEXT: .cfi_offset ra, -40
; RV32IZCMP-SR-NEXT: .cfi_offset s0, -36
; RV32IZCMP-SR-NEXT: .cfi_offset s1, -32
; RV32IZCMP-SR-NEXT: .cfi_offset s2, -28
; RV32IZCMP-SR-NEXT: .cfi_offset s3, -24
; RV32IZCMP-SR-NEXT: .cfi_offset s4, -20
; RV32IZCMP-SR-NEXT: .cfi_offset s5, -16
; RV32IZCMP-SR-NEXT: .cfi_offset s6, -12
; RV32IZCMP-SR-NEXT: .cfi_offset s7, -8
; RV32IZCMP-SR-NEXT: .cfi_offset s8, -4
; RV32IZCMP-SR-NEXT: addi s0, sp, 48
; RV32IZCMP-SR-NEXT: .cfi_def_cfa s0, 0
; RV32IZCMP-SR-NEXT: addi a0, a0, 15
Expand Down Expand Up @@ -829,16 +829,16 @@ define i32 @nocompress(i32 signext %size) {
; RV64IZCMP-SR: # %bb.0: # %entry
; RV64IZCMP-SR-NEXT: cm.push {ra, s0-s8}, -80
; RV64IZCMP-SR-NEXT: .cfi_def_cfa_offset 80
; RV64IZCMP-SR-NEXT: .cfi_offset ra, -8
; RV64IZCMP-SR-NEXT: .cfi_offset s0, -16
; RV64IZCMP-SR-NEXT: .cfi_offset s1, -24
; RV64IZCMP-SR-NEXT: .cfi_offset s2, -32
; RV64IZCMP-SR-NEXT: .cfi_offset s3, -40
; RV64IZCMP-SR-NEXT: .cfi_offset s4, -48
; RV64IZCMP-SR-NEXT: .cfi_offset s5, -56
; RV64IZCMP-SR-NEXT: .cfi_offset s6, -64
; RV64IZCMP-SR-NEXT: .cfi_offset s7, -72
; RV64IZCMP-SR-NEXT: .cfi_offset s8, -80
; RV64IZCMP-SR-NEXT: .cfi_offset ra, -80
; RV64IZCMP-SR-NEXT: .cfi_offset s0, -72
; RV64IZCMP-SR-NEXT: .cfi_offset s1, -64
; RV64IZCMP-SR-NEXT: .cfi_offset s2, -56
; RV64IZCMP-SR-NEXT: .cfi_offset s3, -48
; RV64IZCMP-SR-NEXT: .cfi_offset s4, -40
; RV64IZCMP-SR-NEXT: .cfi_offset s5, -32
; RV64IZCMP-SR-NEXT: .cfi_offset s6, -24
; RV64IZCMP-SR-NEXT: .cfi_offset s7, -16
; RV64IZCMP-SR-NEXT: .cfi_offset s8, -8
; RV64IZCMP-SR-NEXT: addi s0, sp, 80
; RV64IZCMP-SR-NEXT: .cfi_def_cfa s0, 0
; RV64IZCMP-SR-NEXT: slli a0, a0, 32
Expand Down

0 comments on commit d6a48a3

Please sign in to comment.