Skip to content

Commit

Permalink
[VE] Restructure eliminateFrameIndex
Browse files Browse the repository at this point in the history
Restructure the current implementation of eliminateFrameIndex function
in order to support more instructions.

Reviewed By: efocht

Differential Revision: https://reviews.llvm.org/D129034
  • Loading branch information
kaz7 committed Jul 5, 2022
1 parent bc36618 commit da5a6b2
Show file tree
Hide file tree
Showing 3 changed files with 1,762 additions and 44 deletions.
203 changes: 159 additions & 44 deletions llvm/lib/Target/VE/VERegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

using namespace llvm;

#define DEBUG_TYPE "ve-register-info"

#define GET_REGINFO_TARGET_DESC
#include "VEGenRegisterInfo.inc"

Expand Down Expand Up @@ -133,66 +135,179 @@ static unsigned offsetToDisp(MachineInstr &MI) {
return OffDisp;
}

static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,
MachineInstr &MI, const DebugLoc &dl,
unsigned FIOperandNum, int Offset, Register FrameReg) {
// Replace frame index with a frame pointer reference directly.
// VE has 32 bit offset field, so no need to expand a target instruction.
// Directly encode it.
class EliminateFrameIndex {
const TargetInstrInfo &TII;
const TargetRegisterInfo &TRI;
const DebugLoc &DL;
MachineBasicBlock &MBB;
MachineBasicBlock::iterator II;
Register clobber;

// Some helper functions for the ease of instruction building.
MachineFunction &getFunc() const { return *MBB.getParent(); }
inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
return TRI.getSubReg(Reg, Idx);
}
inline const MCInstrDesc &get(unsigned Opcode) const {
return TII.get(Opcode);
}
inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
return BuildMI(MBB, II, DL, MCID, DestReg);
}
inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
return build(get(InstOpc), DestReg);
}
inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
return BuildMI(MBB, II, DL, MCID);
}
inline MachineInstrBuilder build(unsigned InstOpc) {
return build(get(InstOpc));
}

// Calculate an address of frame index from a frame register and a given
// offset if the offset doesn't fit in the immediate field. Use a clobber
// register to hold calculated address.
void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
int64_t Bytes = 0);
// Replace the frame index in \p MI with a frame register and a given offset
// if it fits in the immediate field. Otherwise, use pre-calculated address
// in a clobber regsiter.
void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
int FIOperandNum);

// Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
int FIOperandNum);
void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
int FIOperandNum);

public:
EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
const DebugLoc &DL, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II)
: TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}

// Expand and eliminate Frame Index from MI
void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
int FIOperandNum);
};

// Prepare the frame index if it doesn't fit in the immediate field. Use
// clobber register to hold calculated address.
void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
int64_t &Offset, int64_t Bytes) {
if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
// If the offset is small enough to fit in the immediate field, directly
// encode it. So, nothing to prepare here.
return;
}

// If the offset doesn't fit, emit following codes. This clobbers SX13
// which we always know is available here.
// lea %clobber, Offset@lo
// and %clobber, %clobber, (32)0
// lea.sl %clobber, Offset@hi(FrameReg, %clobber)
build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
build(VE::LEASLrri, clobber)
.addReg(clobber)
.addReg(FrameReg)
.addImm(Hi_32(Offset));

// Use clobber register as a frame register and 0 offset
FrameReg = clobber;
Offset = 0;
}

// Replace the frame index in \p MI with a proper byte and framereg offset.
void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
int64_t Offset, int FIOperandNum) {
assert(isInt<32>(Offset));

// The offset must be small enough to fit in the immediate field after
// call of prepareReplaceFI. Therefore, we directly encode it.
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
}

void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
int64_t Offset, int FIOperandNum) {
assert(MI.getOpcode() == VE::STQrii);
LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());

prepareReplaceFI(MI, FrameReg, Offset, 8);

Register SrcReg = MI.getOperand(3).getReg();
Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
// VE stores HiReg to 8(addr) and LoReg to 0(addr)
MachineInstr *StMI =
build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
replaceFI(*StMI, FrameReg, Offset, 0);
// Mutate to 'hi' store.
MI.setDesc(get(VE::STrii));
MI.getOperand(3).setReg(SrcHiReg);
Offset += 8;
replaceFI(MI, FrameReg, Offset, FIOperandNum);
}

void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
int64_t Offset, int FIOperandNum) {
assert(MI.getOpcode() == VE::LDQrii);
LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());

prepareReplaceFI(MI, FrameReg, Offset, 8);

Register DestReg = MI.getOperand(0).getReg();
Register DestHiReg = getSubReg(DestReg, VE::sub_even);
Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
// VE loads HiReg from 8(addr) and LoReg from 0(addr)
MachineInstr *StMI =
build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
replaceFI(*StMI, FrameReg, Offset, 1);
MI.setDesc(get(VE::LDrii));
MI.getOperand(0).setReg(DestHiReg);
Offset += 8;
replaceFI(MI, FrameReg, Offset, FIOperandNum);
}

void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
int64_t Offset, int FIOperandNum) {
switch (MI.getOpcode()) {
case VE::STQrii:
processSTQ(MI, FrameReg, Offset, FIOperandNum);
return;
case VE::LDQrii:
processLDQ(MI, FrameReg, Offset, FIOperandNum);
return;
}
prepareReplaceFI(MI, FrameReg, Offset);
replaceFI(MI, FrameReg, Offset, FIOperandNum);
}

void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");

MachineInstr &MI = *II;
DebugLoc dl = MI.getDebugLoc();
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();

MachineFunction &MF = *MI.getParent()->getParent();
const VEFrameLowering *TFI = getFrameLowering(MF);
const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
const VEFrameLowering &TFI = *getFrameLowering(MF);
const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
DebugLoc DL = MI.getDebugLoc();
EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);

// Retrieve FrameReg and byte offset for stack slot.
Register FrameReg;
int Offset;
Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();

int64_t Offset =
TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();

if (MI.getOpcode() == VE::STQrii) {
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register SrcReg = MI.getOperand(3).getReg();
Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
// VE stores HiReg to 8(addr) and LoReg to 0(addr)
MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(VE::STrii))
.addReg(FrameReg)
.addImm(0)
.addImm(0)
.addReg(SrcLoReg);
replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg);
MI.setDesc(TII.get(VE::STrii));
MI.getOperand(3).setReg(SrcHiReg);
Offset += 8;
} else if (MI.getOpcode() == VE::LDQrii) {
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register DestReg = MI.getOperand(0).getReg();
Register DestHiReg = getSubReg(DestReg, VE::sub_even);
Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
// VE loads HiReg from 8(addr) and LoReg from 0(addr)
MachineInstr *StMI =
BuildMI(*MI.getParent(), II, dl, TII.get(VE::LDrii), DestLoReg)
.addReg(FrameReg)
.addImm(0)
.addImm(0);
replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg);
MI.setDesc(TII.get(VE::LDrii));
MI.getOperand(0).setReg(DestHiReg);
Offset += 8;
}

replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);
EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
}

Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
Expand Down
Loading

0 comments on commit da5a6b2

Please sign in to comment.