diff --git a/llvm/lib/Target/VE/VERegisterInfo.cpp b/llvm/lib/Target/VE/VERegisterInfo.cpp --- a/llvm/lib/Target/VE/VERegisterInfo.cpp +++ b/llvm/lib/Target/VE/VERegisterInfo.cpp @@ -133,14 +133,155 @@ 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. - MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); - MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); +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); + // 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); +}; + +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); + + 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); + + 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); +} + +// 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) { + if (isInt<32>(Offset)) { + // 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)); +} + +// 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) { + if (isInt<32>(Offset)) { + // If the offset is small enough to fit in the immediate field, directly + // encode it. + MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); + MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); + return; + } + + // Otherwise, use SX13 which holds calculated the address. The address + // is calculated in prepareReplaceFI(). + MI.getOperand(FIOperandNum).ChangeToRegister(clobber, false); + MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(0); +} + +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, @@ -149,50 +290,23 @@ 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(); + 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 {