Skip to content

Commit 180397c

Browse files
LiDJinluxufan
and
luxufan
committed
[RISCV] Enable the LocalStackSlotAllocation pass support.
Differential Revision: https://reviews.llvm.org/D98101 Co-authored-by: luxufan <luxufan@iscas.ac.cn>
1 parent 01303f6 commit 180397c

File tree

4 files changed

+139
-9
lines changed

4 files changed

+139
-9
lines changed

llvm/lib/Target/RISCV/RISCVFrameLowering.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ class RISCVFrameLowering : public TargetFrameLowering {
7373
bool isSupportedStackID(TargetStackID::Value ID) const override;
7474
TargetStackID::Value getStackIDForScalableVectors() const override;
7575

76+
bool isStackIdSafeForLocalArea(unsigned StackId) const override {
77+
// We don't support putting RISCV Vector objects into the pre-allocated
78+
// local frame block at the moment.
79+
return StackId != TargetStackID::ScalableVector;
80+
}
81+
7682
protected:
7783
const RISCVSubtarget &STI;
7884

llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,117 @@ bool RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
498498
return false;
499499
}
500500

501+
bool RISCVRegisterInfo::requiresVirtualBaseRegisters(
502+
const MachineFunction &MF) const {
503+
return true;
504+
}
505+
506+
// Returns true if the instruction's frame index reference would be better
507+
// served by a base register other than FP or SP.
508+
// Used by LocalStackSlotAllocation pass to determine which frame index
509+
// references it should create new base registers for.
510+
bool RISCVRegisterInfo::needsFrameBaseReg(MachineInstr *MI,
511+
int64_t Offset) const {
512+
unsigned FIOperandNum = 0;
513+
for (; !MI->getOperand(FIOperandNum).isFI(); FIOperandNum++)
514+
assert(FIOperandNum < MI->getNumOperands() &&
515+
"Instr doesn't have FrameIndex operand");
516+
517+
// For RISC-V, The machine instructions that include a FrameIndex operand
518+
// are load/store, ADDI instructions.
519+
unsigned MIFrm = RISCVII::getFormat(MI->getDesc().TSFlags);
520+
if (MIFrm != RISCVII::InstFormatI && MIFrm != RISCVII::InstFormatS)
521+
return false;
522+
// We only generate virtual base registers for loads and stores, so
523+
// return false for everything else.
524+
if (!MI->mayLoad() && !MI->mayStore())
525+
return false;
526+
527+
const MachineFunction &MF = *MI->getMF();
528+
const MachineFrameInfo &MFI = MF.getFrameInfo();
529+
const RISCVFrameLowering *TFI = getFrameLowering(MF);
530+
const MachineRegisterInfo &MRI = MF.getRegInfo();
531+
unsigned CalleeSavedSize = 0;
532+
Offset += getFrameIndexInstrOffset(MI, FIOperandNum);
533+
534+
// Estimate the stack size used to store callee saved registers(
535+
// excludes reserved registers).
536+
BitVector ReservedRegs = getReservedRegs(MF);
537+
for (const MCPhysReg *R = MRI.getCalleeSavedRegs(); MCPhysReg Reg = *R; ++R) {
538+
if (!ReservedRegs.test(Reg))
539+
CalleeSavedSize += getSpillSize(*getMinimalPhysRegClass(Reg));
540+
}
541+
542+
int64_t MaxFPOffset = Offset - CalleeSavedSize;
543+
if (TFI->hasFP(MF) && !shouldRealignStack(MF))
544+
return !isFrameOffsetLegal(MI, RISCV::X8, MaxFPOffset);
545+
546+
// Assume 128 bytes spill slots size to estimate the maximum possible
547+
// offset relative to the stack pointer.
548+
// FIXME: The 128 is copied from ARM. We should run some statistics and pick a
549+
// real one for RISC-V.
550+
int64_t MaxSPOffset = Offset + 128;
551+
MaxSPOffset += MFI.getLocalFrameSize();
552+
return !isFrameOffsetLegal(MI, RISCV::X2, MaxSPOffset);
553+
}
554+
555+
// Determine whether a given base register plus offset immediate is
556+
// encodable to resolve a frame index.
557+
bool RISCVRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
558+
Register BaseReg,
559+
int64_t Offset) const {
560+
return isInt<12>(Offset);
561+
}
562+
563+
// Insert defining instruction(s) for a pointer to FrameIdx before
564+
// insertion point I.
565+
// Return materialized frame pointer.
566+
Register RISCVRegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB,
567+
int FrameIdx,
568+
int64_t Offset) const {
569+
MachineBasicBlock::iterator MBBI = MBB->begin();
570+
DebugLoc DL;
571+
if (MBBI != MBB->end())
572+
DL = MBBI->getDebugLoc();
573+
MachineFunction *MF = MBB->getParent();
574+
MachineRegisterInfo &MFI = MF->getRegInfo();
575+
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
576+
577+
Register BaseReg = MFI.createVirtualRegister(&RISCV::GPRRegClass);
578+
BuildMI(*MBB, MBBI, DL, TII->get(RISCV::ADDI), BaseReg)
579+
.addFrameIndex(FrameIdx)
580+
.addImm(Offset);
581+
return BaseReg;
582+
}
583+
584+
// Resolve a frame index operand of an instruction to reference the
585+
// indicated base register plus offset instead.
586+
void RISCVRegisterInfo::resolveFrameIndex(MachineInstr &MI, Register BaseReg,
587+
int64_t Offset) const {
588+
unsigned FIOperandNum = 0;
589+
while (!MI.getOperand(FIOperandNum).isFI())
590+
FIOperandNum++;
591+
assert(FIOperandNum < MI.getNumOperands() &&
592+
"Instr does not have a FrameIndex operand!");
593+
Offset += getFrameIndexInstrOffset(&MI, FIOperandNum);
594+
// FrameIndex Operands are always represented as a
595+
// register followed by an immediate.
596+
MI.getOperand(FIOperandNum).ChangeToRegister(BaseReg, false);
597+
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
598+
}
599+
600+
// Get the offset from the referenced frame index in the instruction,
601+
// if there is one.
602+
int64_t RISCVRegisterInfo::getFrameIndexInstrOffset(const MachineInstr *MI,
603+
int Idx) const {
604+
assert((RISCVII::getFormat(MI->getDesc().TSFlags) == RISCVII::InstFormatI ||
605+
RISCVII::getFormat(MI->getDesc().TSFlags) == RISCVII::InstFormatS) &&
606+
"The MI must be I or S format.");
607+
assert(MI->getOperand(Idx).isFI() && "The Idx'th operand of MI is not a "
608+
"FrameIndex operand");
609+
return MI->getOperand(Idx + 1).getImm();
610+
}
611+
501612
Register RISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
502613
const TargetFrameLowering *TFI = getFrameLowering(MF);
503614
return TFI->hasFP(MF) ? RISCV::X8 : RISCV::X2;

llvm/lib/Target/RISCV/RISCVRegisterInfo.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,22 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
5151
unsigned FIOperandNum,
5252
RegScavenger *RS = nullptr) const override;
5353

54+
bool requiresVirtualBaseRegisters(const MachineFunction &MF) const override;
55+
56+
bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override;
57+
58+
bool isFrameOffsetLegal(const MachineInstr *MI, Register BaseReg,
59+
int64_t Offset) const override;
60+
61+
Register materializeFrameBaseRegister(MachineBasicBlock *MBB, int FrameIdx,
62+
int64_t Offset) const override;
63+
64+
void resolveFrameIndex(MachineInstr &MI, Register BaseReg,
65+
int64_t Offset) const override;
66+
67+
int64_t getFrameIndexInstrOffset(const MachineInstr *MI,
68+
int Idx) const override;
69+
5470
void lowerVSPILL(MachineBasicBlock::iterator II) const;
5571
void lowerVRELOAD(MachineBasicBlock::iterator II) const;
5672

llvm/test/CodeGen/RISCV/local-stack-slot-allocation.ll

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
; This test case test the LocalStackSlotAllocation pass that use a base register
66
; for the frame index that its offset is out-of-range (for RISC-V. the immediate
77
; is 12 bits for the load store instruction (excludes vector load / store))
8-
; TODO: Enable LocalStackSlotAllocation pass.
98
define void @use_frame_base_reg() {
109
; RV32I-LABEL: use_frame_base_reg:
1110
; RV32I: # %bb.0:
@@ -14,11 +13,10 @@ define void @use_frame_base_reg() {
1413
; RV32I-NEXT: sub sp, sp, a0
1514
; RV32I-NEXT: .cfi_def_cfa_offset 100016
1615
; RV32I-NEXT: lui a0, 24
16+
; RV32I-NEXT: addi a0, a0, 1704
1717
; RV32I-NEXT: add a0, sp, a0
18-
; RV32I-NEXT: lb a0, 1708(a0)
19-
; RV32I-NEXT: lui a0, 24
20-
; RV32I-NEXT: add a0, sp, a0
21-
; RV32I-NEXT: lb a0, 1704(a0)
18+
; RV32I-NEXT: lb a1, 4(a0)
19+
; RV32I-NEXT: lb a0, 0(a0)
2220
; RV32I-NEXT: lui a0, 24
2321
; RV32I-NEXT: addi a0, a0, 1712
2422
; RV32I-NEXT: add sp, sp, a0
@@ -31,11 +29,10 @@ define void @use_frame_base_reg() {
3129
; RV64I-NEXT: sub sp, sp, a0
3230
; RV64I-NEXT: .cfi_def_cfa_offset 100016
3331
; RV64I-NEXT: lui a0, 24
32+
; RV64I-NEXT: addiw a0, a0, 1704
3433
; RV64I-NEXT: add a0, sp, a0
35-
; RV64I-NEXT: lb a0, 1708(a0)
36-
; RV64I-NEXT: lui a0, 24
37-
; RV64I-NEXT: add a0, sp, a0
38-
; RV64I-NEXT: lb a0, 1704(a0)
34+
; RV64I-NEXT: lb a1, 4(a0)
35+
; RV64I-NEXT: lb a0, 0(a0)
3936
; RV64I-NEXT: lui a0, 24
4037
; RV64I-NEXT: addiw a0, a0, 1712
4138
; RV64I-NEXT: add sp, sp, a0

0 commit comments

Comments
 (0)