Skip to content

Commit c81e5fa

Browse files
authored
[RISCV] Add CFI information for vector callee-saved registers (#86811)
Currently the CFI offset for RVV registers are not handled entirely, this patch add those information for either stack unwinding or debugger to work correctly on RVV callee-saved stack object. Depends On D154576 Differential Revision: https://reviews.llvm.org/D156846
1 parent 3204f3e commit c81e5fa

File tree

4 files changed

+207
-18
lines changed

4 files changed

+207
-18
lines changed

llvm/lib/Target/RISCV/RISCVFrameLowering.cpp

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,33 @@ void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF,
435435
Flag, getStackAlign());
436436
}
437437

438+
static void appendScalableVectorExpression(const TargetRegisterInfo &TRI,
439+
SmallVectorImpl<char> &Expr,
440+
int FixedOffset, int ScalableOffset,
441+
llvm::raw_string_ostream &Comment) {
442+
unsigned DwarfVLenB = TRI.getDwarfRegNum(RISCV::VLENB, true);
443+
uint8_t Buffer[16];
444+
if (FixedOffset) {
445+
Expr.push_back(dwarf::DW_OP_consts);
446+
Expr.append(Buffer, Buffer + encodeSLEB128(FixedOffset, Buffer));
447+
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
448+
Comment << (FixedOffset < 0 ? " - " : " + ") << std::abs(FixedOffset);
449+
}
450+
451+
Expr.push_back((uint8_t)dwarf::DW_OP_consts);
452+
Expr.append(Buffer, Buffer + encodeSLEB128(ScalableOffset, Buffer));
453+
454+
Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
455+
Expr.append(Buffer, Buffer + encodeULEB128(DwarfVLenB, Buffer));
456+
Expr.push_back(0);
457+
458+
Expr.push_back((uint8_t)dwarf::DW_OP_mul);
459+
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
460+
461+
Comment << (ScalableOffset < 0 ? " - " : " + ") << std::abs(ScalableOffset)
462+
<< " * vlenb";
463+
}
464+
438465
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI,
439466
Register Reg,
440467
uint64_t FixedOffset,
@@ -452,30 +479,38 @@ static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI,
452479
else
453480
Comment << printReg(Reg, &TRI);
454481

455-
uint8_t buffer[16];
456-
if (FixedOffset) {
457-
Expr.push_back(dwarf::DW_OP_consts);
458-
Expr.append(buffer, buffer + encodeSLEB128(FixedOffset, buffer));
459-
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
460-
Comment << " + " << FixedOffset;
461-
}
482+
appendScalableVectorExpression(TRI, Expr, FixedOffset, ScalableOffset,
483+
Comment);
462484

463-
Expr.push_back((uint8_t)dwarf::DW_OP_consts);
464-
Expr.append(buffer, buffer + encodeSLEB128(ScalableOffset, buffer));
485+
SmallString<64> DefCfaExpr;
486+
uint8_t Buffer[16];
487+
DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
488+
DefCfaExpr.append(Buffer, Buffer + encodeULEB128(Expr.size(), Buffer));
489+
DefCfaExpr.append(Expr.str());
465490

466-
unsigned DwarfVlenb = TRI.getDwarfRegNum(RISCV::VLENB, true);
467-
Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
468-
Expr.append(buffer, buffer + encodeULEB128(DwarfVlenb, buffer));
469-
Expr.push_back(0);
491+
return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
492+
Comment.str());
493+
}
470494

471-
Expr.push_back((uint8_t)dwarf::DW_OP_mul);
472-
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
495+
static MCCFIInstruction createDefCFAOffset(const TargetRegisterInfo &TRI,
496+
Register Reg, uint64_t FixedOffset,
497+
uint64_t ScalableOffset) {
498+
assert(ScalableOffset != 0 && "Did not need to adjust CFA for RVV");
499+
SmallString<64> Expr;
500+
std::string CommentBuffer;
501+
llvm::raw_string_ostream Comment(CommentBuffer);
502+
Comment << printReg(Reg, &TRI) << " @ cfa";
473503

474-
Comment << " + " << ScalableOffset << " * vlenb";
504+
// Build up the expression (FixedOffset + ScalableOffset * VLENB).
505+
appendScalableVectorExpression(TRI, Expr, FixedOffset, ScalableOffset,
506+
Comment);
475507

476508
SmallString<64> DefCfaExpr;
477-
DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
478-
DefCfaExpr.append(buffer, buffer + encodeULEB128(Expr.size(), buffer));
509+
uint8_t Buffer[16];
510+
unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
511+
DefCfaExpr.push_back(dwarf::DW_CFA_expression);
512+
DefCfaExpr.append(Buffer, Buffer + encodeULEB128(DwarfReg, Buffer));
513+
DefCfaExpr.append(Buffer, Buffer + encodeULEB128(Expr.size(), Buffer));
479514
DefCfaExpr.append(Expr.str());
480515

481516
return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
@@ -671,6 +706,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
671706
.addCFIIndex(CFIIndex)
672707
.setMIFlag(MachineInstr::FrameSetup);
673708
}
709+
710+
std::advance(MBBI, getRVVCalleeSavedInfo(MF, CSI).size());
711+
emitCalleeSavedRVVPrologCFI(MBB, MBBI, hasFP(MF));
674712
}
675713

676714
if (hasFP(MF)) {
@@ -1492,6 +1530,41 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
14921530
return true;
14931531
}
14941532

1533+
void RISCVFrameLowering::emitCalleeSavedRVVPrologCFI(
1534+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, bool HasFP) const {
1535+
MachineFunction *MF = MBB.getParent();
1536+
const MachineFrameInfo &MFI = MF->getFrameInfo();
1537+
RISCVMachineFunctionInfo *RVFI = MF->getInfo<RISCVMachineFunctionInfo>();
1538+
const TargetInstrInfo &TII = *STI.getInstrInfo();
1539+
DebugLoc DL = MBB.findDebugLoc(MI);
1540+
1541+
const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, MFI.getCalleeSavedInfo());
1542+
if (RVVCSI.empty())
1543+
return;
1544+
1545+
uint64_t FixedSize = getStackSizeWithRVVPadding(*MF);
1546+
if (!HasFP) {
1547+
uint64_t ScalarLocalVarSize =
1548+
MFI.getStackSize() - RVFI->getCalleeSavedStackSize() -
1549+
RVFI->getRVPushStackSize() - RVFI->getVarArgsSaveSize() +
1550+
RVFI->getRVVPadding();
1551+
FixedSize -= ScalarLocalVarSize;
1552+
}
1553+
1554+
for (auto &CS : RVVCSI) {
1555+
// Insert the spill to the stack frame.
1556+
int FI = CS.getFrameIdx();
1557+
if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) {
1558+
unsigned CFIIndex = MF->addFrameInst(
1559+
createDefCFAOffset(*STI.getRegisterInfo(), CS.getReg(), -FixedSize,
1560+
MFI.getObjectOffset(FI) / 8));
1561+
BuildMI(MBB, MI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
1562+
.addCFIIndex(CFIIndex)
1563+
.setMIFlag(MachineInstr::FrameSetup);
1564+
}
1565+
}
1566+
}
1567+
14951568
bool RISCVFrameLowering::restoreCalleeSavedRegisters(
14961569
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
14971570
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {

llvm/lib/Target/RISCV/RISCVFrameLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ class RISCVFrameLowering : public TargetFrameLowering {
8888
void adjustStackForRVV(MachineFunction &MF, MachineBasicBlock &MBB,
8989
MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
9090
int64_t Amount, MachineInstr::MIFlag Flag) const;
91+
void emitCalleeSavedRVVPrologCFI(MachineBasicBlock &MBB,
92+
MachineBasicBlock::iterator MI,
93+
bool HasFP) const;
9194
std::pair<int64_t, Align>
9295
assignRVVStackObjectOffsets(MachineFunction &MF) const;
9396
};
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv64 -mattr=+v,+m -verify-machineinstrs < %s \
3+
; RUN: | FileCheck -check-prefix=OMIT-FP %s
4+
; RUN: llc -mtriple=riscv64 -mattr=+v,+m -verify-machineinstrs -frame-pointer=all < %s \
5+
; RUN: | FileCheck -check-prefix=NO-OMIT-FP %s
6+
7+
define riscv_vector_cc <vscale x 1 x i32> @test_vector_callee_cfi(<vscale x 1 x i32> %va) {
8+
; OMIT-FP-LABEL: test_vector_callee_cfi:
9+
; OMIT-FP: # %bb.0: # %entry
10+
; OMIT-FP-NEXT: addi sp, sp, -16
11+
; OMIT-FP-NEXT: .cfi_def_cfa_offset 16
12+
; OMIT-FP-NEXT: csrr a0, vlenb
13+
; OMIT-FP-NEXT: slli a0, a0, 3
14+
; OMIT-FP-NEXT: sub sp, sp, a0
15+
; OMIT-FP-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x08, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 8 * vlenb
16+
; OMIT-FP-NEXT: csrr a0, vlenb
17+
; OMIT-FP-NEXT: li a1, 6
18+
; OMIT-FP-NEXT: mul a0, a0, a1
19+
; OMIT-FP-NEXT: add a0, sp, a0
20+
; OMIT-FP-NEXT: addi a0, a0, 16
21+
; OMIT-FP-NEXT: vs1r.v v1, (a0) # Unknown-size Folded Spill
22+
; OMIT-FP-NEXT: csrr a0, vlenb
23+
; OMIT-FP-NEXT: slli a0, a0, 2
24+
; OMIT-FP-NEXT: add a0, sp, a0
25+
; OMIT-FP-NEXT: addi a0, a0, 16
26+
; OMIT-FP-NEXT: vs2r.v v2, (a0) # Unknown-size Folded Spill
27+
; OMIT-FP-NEXT: addi a0, sp, 16
28+
; OMIT-FP-NEXT: vs4r.v v4, (a0) # Unknown-size Folded Spill
29+
; OMIT-FP-NEXT: .cfi_escape 0x10, 0x61, 0x08, 0x11, 0x7e, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # $v1 @ cfa - 2 * vlenb
30+
; OMIT-FP-NEXT: .cfi_escape 0x10, 0x62, 0x08, 0x11, 0x7c, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # $v2m2 @ cfa - 4 * vlenb
31+
; OMIT-FP-NEXT: .cfi_escape 0x10, 0x64, 0x08, 0x11, 0x78, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # $v4m4 @ cfa - 8 * vlenb
32+
; OMIT-FP-NEXT: #APP
33+
; OMIT-FP-NEXT: #NO_APP
34+
; OMIT-FP-NEXT: csrr a0, vlenb
35+
; OMIT-FP-NEXT: li a1, 6
36+
; OMIT-FP-NEXT: mul a0, a0, a1
37+
; OMIT-FP-NEXT: add a0, sp, a0
38+
; OMIT-FP-NEXT: addi a0, a0, 16
39+
; OMIT-FP-NEXT: vl1r.v v1, (a0) # Unknown-size Folded Reload
40+
; OMIT-FP-NEXT: csrr a0, vlenb
41+
; OMIT-FP-NEXT: slli a0, a0, 2
42+
; OMIT-FP-NEXT: add a0, sp, a0
43+
; OMIT-FP-NEXT: addi a0, a0, 16
44+
; OMIT-FP-NEXT: vl2r.v v2, (a0) # Unknown-size Folded Reload
45+
; OMIT-FP-NEXT: addi a0, sp, 16
46+
; OMIT-FP-NEXT: vl4r.v v4, (a0) # Unknown-size Folded Reload
47+
; OMIT-FP-NEXT: csrr a0, vlenb
48+
; OMIT-FP-NEXT: slli a0, a0, 3
49+
; OMIT-FP-NEXT: add sp, sp, a0
50+
; OMIT-FP-NEXT: addi sp, sp, 16
51+
; OMIT-FP-NEXT: ret
52+
;
53+
; NO-OMIT-FP-LABEL: test_vector_callee_cfi:
54+
; NO-OMIT-FP: # %bb.0: # %entry
55+
; NO-OMIT-FP-NEXT: addi sp, sp, -32
56+
; NO-OMIT-FP-NEXT: .cfi_def_cfa_offset 32
57+
; NO-OMIT-FP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
58+
; NO-OMIT-FP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
59+
; NO-OMIT-FP-NEXT: .cfi_offset ra, -8
60+
; NO-OMIT-FP-NEXT: .cfi_offset s0, -16
61+
; NO-OMIT-FP-NEXT: addi s0, sp, 32
62+
; NO-OMIT-FP-NEXT: .cfi_def_cfa s0, 0
63+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
64+
; NO-OMIT-FP-NEXT: slli a0, a0, 3
65+
; NO-OMIT-FP-NEXT: sub sp, sp, a0
66+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
67+
; NO-OMIT-FP-NEXT: slli a0, a0, 1
68+
; NO-OMIT-FP-NEXT: sub a0, s0, a0
69+
; NO-OMIT-FP-NEXT: addi a0, a0, -32
70+
; NO-OMIT-FP-NEXT: vs1r.v v1, (a0) # Unknown-size Folded Spill
71+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
72+
; NO-OMIT-FP-NEXT: slli a0, a0, 2
73+
; NO-OMIT-FP-NEXT: sub a0, s0, a0
74+
; NO-OMIT-FP-NEXT: addi a0, a0, -32
75+
; NO-OMIT-FP-NEXT: vs2r.v v2, (a0) # Unknown-size Folded Spill
76+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
77+
; NO-OMIT-FP-NEXT: slli a0, a0, 3
78+
; NO-OMIT-FP-NEXT: sub a0, s0, a0
79+
; NO-OMIT-FP-NEXT: addi a0, a0, -32
80+
; NO-OMIT-FP-NEXT: vs4r.v v4, (a0) # Unknown-size Folded Spill
81+
; NO-OMIT-FP-NEXT: .cfi_escape 0x10, 0x61, 0x0b, 0x11, 0x60, 0x22, 0x11, 0x7e, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # $v1 @ cfa - 32 - 2 * vlenb
82+
; NO-OMIT-FP-NEXT: .cfi_escape 0x10, 0x62, 0x0b, 0x11, 0x60, 0x22, 0x11, 0x7c, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # $v2m2 @ cfa - 32 - 4 * vlenb
83+
; NO-OMIT-FP-NEXT: .cfi_escape 0x10, 0x64, 0x0b, 0x11, 0x60, 0x22, 0x11, 0x78, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # $v4m4 @ cfa - 32 - 8 * vlenb
84+
; NO-OMIT-FP-NEXT: #APP
85+
; NO-OMIT-FP-NEXT: #NO_APP
86+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
87+
; NO-OMIT-FP-NEXT: slli a0, a0, 1
88+
; NO-OMIT-FP-NEXT: sub a0, s0, a0
89+
; NO-OMIT-FP-NEXT: addi a0, a0, -32
90+
; NO-OMIT-FP-NEXT: vl1r.v v1, (a0) # Unknown-size Folded Reload
91+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
92+
; NO-OMIT-FP-NEXT: slli a0, a0, 2
93+
; NO-OMIT-FP-NEXT: sub a0, s0, a0
94+
; NO-OMIT-FP-NEXT: addi a0, a0, -32
95+
; NO-OMIT-FP-NEXT: vl2r.v v2, (a0) # Unknown-size Folded Reload
96+
; NO-OMIT-FP-NEXT: csrr a0, vlenb
97+
; NO-OMIT-FP-NEXT: slli a0, a0, 3
98+
; NO-OMIT-FP-NEXT: sub a0, s0, a0
99+
; NO-OMIT-FP-NEXT: addi a0, a0, -32
100+
; NO-OMIT-FP-NEXT: vl4r.v v4, (a0) # Unknown-size Folded Reload
101+
; NO-OMIT-FP-NEXT: addi sp, s0, -32
102+
; NO-OMIT-FP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
103+
; NO-OMIT-FP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
104+
; NO-OMIT-FP-NEXT: addi sp, sp, 32
105+
; NO-OMIT-FP-NEXT: ret
106+
entry:
107+
call void asm sideeffect "",
108+
"~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7}"()
109+
110+
ret <vscale x 1 x i32> %va
111+
}

llvm/test/CodeGen/RISCV/rvv/fixed-vectors-insert-subvector.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ define void @insert_v2i64_nxv16i64_hi(ptr %psv, ptr %out) {
628628
; RV32-NEXT: vs8r.v v8, (a0)
629629
; RV32-NEXT: vs8r.v v16, (a1)
630630
; RV32-NEXT: addi sp, s0, -80
631+
; RV32-NEXT: .cfi_def_cfa sp, 80
631632
; RV32-NEXT: lw ra, 76(sp) # 4-byte Folded Reload
632633
; RV32-NEXT: lw s0, 72(sp) # 4-byte Folded Reload
633634
; RV32-NEXT: addi sp, sp, 80
@@ -661,6 +662,7 @@ define void @insert_v2i64_nxv16i64_hi(ptr %psv, ptr %out) {
661662
; RV64-NEXT: vs8r.v v8, (a0)
662663
; RV64-NEXT: vs8r.v v16, (a1)
663664
; RV64-NEXT: addi sp, s0, -80
665+
; RV64-NEXT: .cfi_def_cfa sp, 80
664666
; RV64-NEXT: ld ra, 72(sp) # 8-byte Folded Reload
665667
; RV64-NEXT: ld s0, 64(sp) # 8-byte Folded Reload
666668
; RV64-NEXT: addi sp, sp, 80

0 commit comments

Comments
 (0)