1480093f4SDimitry Andric //===-- VERegisterInfo.cpp - VE Register Information ----------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric // This file contains the VE implementation of the TargetRegisterInfo class. 10480093f4SDimitry Andric // 11480093f4SDimitry Andric //===----------------------------------------------------------------------===// 12480093f4SDimitry Andric 13480093f4SDimitry Andric #include "VERegisterInfo.h" 14480093f4SDimitry Andric #include "VE.h" 15480093f4SDimitry Andric #include "VESubtarget.h" 16480093f4SDimitry Andric #include "llvm/ADT/BitVector.h" 17480093f4SDimitry Andric #include "llvm/ADT/STLExtras.h" 18480093f4SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 19480093f4SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 20480093f4SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 21480093f4SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 22480093f4SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 23480093f4SDimitry Andric #include "llvm/IR/Type.h" 24480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 25e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h" 26480093f4SDimitry Andric #include "llvm/Support/ErrorHandling.h" 27480093f4SDimitry Andric 28480093f4SDimitry Andric using namespace llvm; 29480093f4SDimitry Andric 30753f127fSDimitry Andric #define DEBUG_TYPE "ve-register-info" 31753f127fSDimitry Andric 32480093f4SDimitry Andric #define GET_REGINFO_TARGET_DESC 33480093f4SDimitry Andric #include "VEGenRegisterInfo.inc" 34480093f4SDimitry Andric 35480093f4SDimitry Andric // VE uses %s10 == %lp to keep return address 36480093f4SDimitry Andric VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {} 37480093f4SDimitry Andric 38480093f4SDimitry Andric const MCPhysReg * 39480093f4SDimitry Andric VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { 405ffd83dbSDimitry Andric switch (MF->getFunction().getCallingConv()) { 41e8d8bef9SDimitry Andric case CallingConv::Fast: 42e8d8bef9SDimitry Andric // Being explicit (same as standard CC). 435ffd83dbSDimitry Andric default: 44480093f4SDimitry Andric return CSR_SaveList; 455ffd83dbSDimitry Andric case CallingConv::PreserveAll: 465ffd83dbSDimitry Andric return CSR_preserve_all_SaveList; 475ffd83dbSDimitry Andric } 48480093f4SDimitry Andric } 49480093f4SDimitry Andric 50480093f4SDimitry Andric const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF, 51480093f4SDimitry Andric CallingConv::ID CC) const { 525ffd83dbSDimitry Andric switch (CC) { 53e8d8bef9SDimitry Andric case CallingConv::Fast: 54e8d8bef9SDimitry Andric // Being explicit (same as standard CC). 555ffd83dbSDimitry Andric default: 56480093f4SDimitry Andric return CSR_RegMask; 575ffd83dbSDimitry Andric case CallingConv::PreserveAll: 585ffd83dbSDimitry Andric return CSR_preserve_all_RegMask; 595ffd83dbSDimitry Andric } 60480093f4SDimitry Andric } 61480093f4SDimitry Andric 62480093f4SDimitry Andric const uint32_t *VERegisterInfo::getNoPreservedMask() const { 63480093f4SDimitry Andric return CSR_NoRegs_RegMask; 64480093f4SDimitry Andric } 65480093f4SDimitry Andric 66480093f4SDimitry Andric BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const { 67480093f4SDimitry Andric BitVector Reserved(getNumRegs()); 68480093f4SDimitry Andric 695ffd83dbSDimitry Andric const Register ReservedRegs[] = { 705ffd83dbSDimitry Andric VE::SX8, // Stack limit 715ffd83dbSDimitry Andric VE::SX9, // Frame pointer 725ffd83dbSDimitry Andric VE::SX10, // Link register (return address) 735ffd83dbSDimitry Andric VE::SX11, // Stack pointer 74480093f4SDimitry Andric 755ffd83dbSDimitry Andric // FIXME: maybe not need to be reserved 765ffd83dbSDimitry Andric VE::SX12, // Outer register 775ffd83dbSDimitry Andric VE::SX13, // Id register for dynamic linker 78480093f4SDimitry Andric 795ffd83dbSDimitry Andric VE::SX14, // Thread pointer 805ffd83dbSDimitry Andric VE::SX15, // Global offset table register 815ffd83dbSDimitry Andric VE::SX16, // Procedure linkage table register 825ffd83dbSDimitry Andric VE::SX17, // Linkage-area register 83480093f4SDimitry Andric // sx18-sx33 are callee-saved registers 84480093f4SDimitry Andric // sx34-sx63 are temporary registers 855ffd83dbSDimitry Andric }; 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric for (auto R : ReservedRegs) 885ffd83dbSDimitry Andric for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid(); 895ffd83dbSDimitry Andric ++ItAlias) 905ffd83dbSDimitry Andric Reserved.set(*ItAlias); 91480093f4SDimitry Andric 92e8d8bef9SDimitry Andric // Reserve constant registers. 93e8d8bef9SDimitry Andric Reserved.set(VE::VM0); 94e8d8bef9SDimitry Andric Reserved.set(VE::VMP0); 95e8d8bef9SDimitry Andric 96480093f4SDimitry Andric return Reserved; 97480093f4SDimitry Andric } 98480093f4SDimitry Andric 99e8d8bef9SDimitry Andric bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { 100e8d8bef9SDimitry Andric switch (PhysReg) { 101e8d8bef9SDimitry Andric case VE::VM0: 102e8d8bef9SDimitry Andric case VE::VMP0: 103e8d8bef9SDimitry Andric return true; 104e8d8bef9SDimitry Andric default: 105e8d8bef9SDimitry Andric return false; 106e8d8bef9SDimitry Andric } 107e8d8bef9SDimitry Andric } 108480093f4SDimitry Andric 109480093f4SDimitry Andric const TargetRegisterClass * 110480093f4SDimitry Andric VERegisterInfo::getPointerRegClass(const MachineFunction &MF, 111480093f4SDimitry Andric unsigned Kind) const { 112480093f4SDimitry Andric return &VE::I64RegClass; 113480093f4SDimitry Andric } 114480093f4SDimitry Andric 115e8d8bef9SDimitry Andric static unsigned offsetToDisp(MachineInstr &MI) { 116e8d8bef9SDimitry Andric // Default offset in instruction's operands (reg+reg+imm). 117e8d8bef9SDimitry Andric unsigned OffDisp = 2; 118e8d8bef9SDimitry Andric 119e8d8bef9SDimitry Andric #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii 120e8d8bef9SDimitry Andric 121e8d8bef9SDimitry Andric { 122e8d8bef9SDimitry Andric using namespace llvm::VE; 123e8d8bef9SDimitry Andric switch (MI.getOpcode()) { 124e8d8bef9SDimitry Andric case RRCAS_multi_cases(TS1AML): 125e8d8bef9SDimitry Andric case RRCAS_multi_cases(TS1AMW): 126e8d8bef9SDimitry Andric case RRCAS_multi_cases(CASL): 127e8d8bef9SDimitry Andric case RRCAS_multi_cases(CASW): 128e8d8bef9SDimitry Andric // These instructions use AS format (reg+imm). 129e8d8bef9SDimitry Andric OffDisp = 1; 130e8d8bef9SDimitry Andric break; 131e8d8bef9SDimitry Andric } 132e8d8bef9SDimitry Andric } 133e8d8bef9SDimitry Andric #undef RRCAS_multi_cases 134e8d8bef9SDimitry Andric 135e8d8bef9SDimitry Andric return OffDisp; 136e8d8bef9SDimitry Andric } 137e8d8bef9SDimitry Andric 138753f127fSDimitry Andric class EliminateFrameIndex { 139753f127fSDimitry Andric const TargetInstrInfo &TII; 140753f127fSDimitry Andric const TargetRegisterInfo &TRI; 141753f127fSDimitry Andric const DebugLoc &DL; 142753f127fSDimitry Andric MachineBasicBlock &MBB; 143753f127fSDimitry Andric MachineBasicBlock::iterator II; 144753f127fSDimitry Andric Register clobber; 145753f127fSDimitry Andric 146753f127fSDimitry Andric // Some helper functions for the ease of instruction building. 147753f127fSDimitry Andric MachineFunction &getFunc() const { return *MBB.getParent(); } 148753f127fSDimitry Andric inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const { 149753f127fSDimitry Andric return TRI.getSubReg(Reg, Idx); 150753f127fSDimitry Andric } 151753f127fSDimitry Andric inline const MCInstrDesc &get(unsigned Opcode) const { 152753f127fSDimitry Andric return TII.get(Opcode); 153753f127fSDimitry Andric } 154753f127fSDimitry Andric inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) { 155753f127fSDimitry Andric return BuildMI(MBB, II, DL, MCID, DestReg); 156753f127fSDimitry Andric } 157753f127fSDimitry Andric inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) { 158753f127fSDimitry Andric return build(get(InstOpc), DestReg); 159753f127fSDimitry Andric } 160753f127fSDimitry Andric inline MachineInstrBuilder build(const MCInstrDesc &MCID) { 161753f127fSDimitry Andric return BuildMI(MBB, II, DL, MCID); 162753f127fSDimitry Andric } 163753f127fSDimitry Andric inline MachineInstrBuilder build(unsigned InstOpc) { 164753f127fSDimitry Andric return build(get(InstOpc)); 165753f127fSDimitry Andric } 166753f127fSDimitry Andric 167753f127fSDimitry Andric // Calculate an address of frame index from a frame register and a given 168753f127fSDimitry Andric // offset if the offset doesn't fit in the immediate field. Use a clobber 169753f127fSDimitry Andric // register to hold calculated address. 170753f127fSDimitry Andric void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset, 171753f127fSDimitry Andric int64_t Bytes = 0); 172753f127fSDimitry Andric // Replace the frame index in \p MI with a frame register and a given offset 173753f127fSDimitry Andric // if it fits in the immediate field. Otherwise, use pre-calculated address 174753f127fSDimitry Andric // in a clobber regsiter. 175753f127fSDimitry Andric void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset, 176753f127fSDimitry Andric int FIOperandNum); 177753f127fSDimitry Andric 178753f127fSDimitry Andric // Expand and eliminate Frame Index of pseudo STQrii and LDQrii. 179753f127fSDimitry Andric void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset, 180753f127fSDimitry Andric int FIOperandNum); 181753f127fSDimitry Andric void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset, 182753f127fSDimitry Andric int FIOperandNum); 183*fcaf7f86SDimitry Andric // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii. 184*fcaf7f86SDimitry Andric void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset, 185*fcaf7f86SDimitry Andric int FIOperandNum); 186*fcaf7f86SDimitry Andric void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset, 187*fcaf7f86SDimitry Andric int FIOperandNum); 188*fcaf7f86SDimitry Andric // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii. 189*fcaf7f86SDimitry Andric void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, 190*fcaf7f86SDimitry Andric int FIOperandNum); 191*fcaf7f86SDimitry Andric void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset, 192*fcaf7f86SDimitry Andric int FIOperandNum); 193753f127fSDimitry Andric 194753f127fSDimitry Andric public: 195753f127fSDimitry Andric EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, 196753f127fSDimitry Andric const DebugLoc &DL, MachineBasicBlock &MBB, 197753f127fSDimitry Andric MachineBasicBlock::iterator II) 198753f127fSDimitry Andric : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {} 199753f127fSDimitry Andric 200753f127fSDimitry Andric // Expand and eliminate Frame Index from MI 201753f127fSDimitry Andric void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset, 202753f127fSDimitry Andric int FIOperandNum); 203753f127fSDimitry Andric }; 204753f127fSDimitry Andric 205753f127fSDimitry Andric // Prepare the frame index if it doesn't fit in the immediate field. Use 206753f127fSDimitry Andric // clobber register to hold calculated address. 207753f127fSDimitry Andric void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg, 208753f127fSDimitry Andric int64_t &Offset, int64_t Bytes) { 209753f127fSDimitry Andric if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) { 210753f127fSDimitry Andric // If the offset is small enough to fit in the immediate field, directly 211753f127fSDimitry Andric // encode it. So, nothing to prepare here. 212753f127fSDimitry Andric return; 213753f127fSDimitry Andric } 214753f127fSDimitry Andric 215753f127fSDimitry Andric // If the offset doesn't fit, emit following codes. This clobbers SX13 216753f127fSDimitry Andric // which we always know is available here. 217753f127fSDimitry Andric // lea %clobber, Offset@lo 218753f127fSDimitry Andric // and %clobber, %clobber, (32)0 219753f127fSDimitry Andric // lea.sl %clobber, Offset@hi(FrameReg, %clobber) 220753f127fSDimitry Andric build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset)); 221753f127fSDimitry Andric build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32)); 222753f127fSDimitry Andric build(VE::LEASLrri, clobber) 223753f127fSDimitry Andric .addReg(clobber) 224753f127fSDimitry Andric .addReg(FrameReg) 225753f127fSDimitry Andric .addImm(Hi_32(Offset)); 226753f127fSDimitry Andric 227753f127fSDimitry Andric // Use clobber register as a frame register and 0 offset 228753f127fSDimitry Andric FrameReg = clobber; 229753f127fSDimitry Andric Offset = 0; 230753f127fSDimitry Andric } 231753f127fSDimitry Andric 232753f127fSDimitry Andric // Replace the frame index in \p MI with a proper byte and framereg offset. 233753f127fSDimitry Andric void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg, 234753f127fSDimitry Andric int64_t Offset, int FIOperandNum) { 235753f127fSDimitry Andric assert(isInt<32>(Offset)); 236753f127fSDimitry Andric 237753f127fSDimitry Andric // The offset must be small enough to fit in the immediate field after 238753f127fSDimitry Andric // call of prepareReplaceFI. Therefore, we directly encode it. 2395ffd83dbSDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); 240e8d8bef9SDimitry Andric MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset); 241480093f4SDimitry Andric } 242480093f4SDimitry Andric 243753f127fSDimitry Andric void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg, 244753f127fSDimitry Andric int64_t Offset, int FIOperandNum) { 245753f127fSDimitry Andric assert(MI.getOpcode() == VE::STQrii); 246753f127fSDimitry Andric LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump()); 247753f127fSDimitry Andric 248753f127fSDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 8); 249753f127fSDimitry Andric 250753f127fSDimitry Andric Register SrcReg = MI.getOperand(3).getReg(); 251753f127fSDimitry Andric Register SrcHiReg = getSubReg(SrcReg, VE::sub_even); 252753f127fSDimitry Andric Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd); 253753f127fSDimitry Andric // VE stores HiReg to 8(addr) and LoReg to 0(addr) 254753f127fSDimitry Andric MachineInstr *StMI = 255753f127fSDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg); 256753f127fSDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0); 257753f127fSDimitry Andric // Mutate to 'hi' store. 258753f127fSDimitry Andric MI.setDesc(get(VE::STrii)); 259753f127fSDimitry Andric MI.getOperand(3).setReg(SrcHiReg); 260753f127fSDimitry Andric Offset += 8; 261753f127fSDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 262753f127fSDimitry Andric } 263753f127fSDimitry Andric 264753f127fSDimitry Andric void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg, 265753f127fSDimitry Andric int64_t Offset, int FIOperandNum) { 266753f127fSDimitry Andric assert(MI.getOpcode() == VE::LDQrii); 267753f127fSDimitry Andric LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump()); 268753f127fSDimitry Andric 269753f127fSDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 8); 270753f127fSDimitry Andric 271753f127fSDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 272753f127fSDimitry Andric Register DestHiReg = getSubReg(DestReg, VE::sub_even); 273753f127fSDimitry Andric Register DestLoReg = getSubReg(DestReg, VE::sub_odd); 274753f127fSDimitry Andric // VE loads HiReg from 8(addr) and LoReg from 0(addr) 275753f127fSDimitry Andric MachineInstr *StMI = 276753f127fSDimitry Andric build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0); 277753f127fSDimitry Andric replaceFI(*StMI, FrameReg, Offset, 1); 278753f127fSDimitry Andric MI.setDesc(get(VE::LDrii)); 279753f127fSDimitry Andric MI.getOperand(0).setReg(DestHiReg); 280753f127fSDimitry Andric Offset += 8; 281753f127fSDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 282753f127fSDimitry Andric } 283753f127fSDimitry Andric 284*fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg, 285*fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) { 286*fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::STVMrii); 287*fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump()); 288*fcaf7f86SDimitry Andric 289*fcaf7f86SDimitry Andric // Original MI is: 290*fcaf7f86SDimitry Andric // STVMrii frame-index, 0, offset, reg (, memory operand) 291*fcaf7f86SDimitry Andric // Convert it to: 292*fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 0 293*fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset, tmp-reg 294*fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 1 295*fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset+8, tmp-reg 296*fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 2 297*fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset+16, tmp-reg 298*fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 3 299*fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset+24, tmp-reg 300*fcaf7f86SDimitry Andric 301*fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 24); 302*fcaf7f86SDimitry Andric 303*fcaf7f86SDimitry Andric Register SrcReg = MI.getOperand(3).getReg(); 304*fcaf7f86SDimitry Andric bool isKill = MI.getOperand(3).isKill(); 305*fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of 306*fcaf7f86SDimitry Andric // reserving SX16 all of the time. 307*fcaf7f86SDimitry Andric Register TmpReg = VE::SX16; 308*fcaf7f86SDimitry Andric for (int i = 0; i < 3; ++i) { 309*fcaf7f86SDimitry Andric build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i); 310*fcaf7f86SDimitry Andric MachineInstr *StMI = 311*fcaf7f86SDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 312*fcaf7f86SDimitry Andric TmpReg, getKillRegState(true)); 313*fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0); 314*fcaf7f86SDimitry Andric Offset += 8; 315*fcaf7f86SDimitry Andric } 316*fcaf7f86SDimitry Andric build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3); 317*fcaf7f86SDimitry Andric MI.setDesc(get(VE::STrii)); 318*fcaf7f86SDimitry Andric MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true); 319*fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 320*fcaf7f86SDimitry Andric } 321*fcaf7f86SDimitry Andric 322*fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg, 323*fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) { 324*fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::LDVMrii); 325*fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump()); 326*fcaf7f86SDimitry Andric 327*fcaf7f86SDimitry Andric // Original MI is: 328*fcaf7f86SDimitry Andric // LDVMri reg, frame-index, 0, offset (, memory operand) 329*fcaf7f86SDimitry Andric // Convert it to: 330*fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset 331*fcaf7f86SDimitry Andric // LVMir vm, 0, tmp-reg 332*fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset+8 333*fcaf7f86SDimitry Andric // LVMir_m vm, 1, tmp-reg, vm 334*fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset+16 335*fcaf7f86SDimitry Andric // LVMir_m vm, 2, tmp-reg, vm 336*fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset+24 337*fcaf7f86SDimitry Andric // LVMir_m vm, 3, tmp-reg, vm 338*fcaf7f86SDimitry Andric 339*fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 24); 340*fcaf7f86SDimitry Andric 341*fcaf7f86SDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 342*fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of 343*fcaf7f86SDimitry Andric // reserving SX16 all of the time. 344*fcaf7f86SDimitry Andric unsigned TmpReg = VE::SX16; 345*fcaf7f86SDimitry Andric for (int i = 0; i < 4; ++i) { 346*fcaf7f86SDimitry Andric if (i != 3) { 347*fcaf7f86SDimitry Andric MachineInstr *StMI = 348*fcaf7f86SDimitry Andric build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 349*fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 1); 350*fcaf7f86SDimitry Andric Offset += 8; 351*fcaf7f86SDimitry Andric } else { 352*fcaf7f86SDimitry Andric // Last LDrii replace the target instruction. 353*fcaf7f86SDimitry Andric MI.setDesc(get(VE::LDrii)); 354*fcaf7f86SDimitry Andric MI.getOperand(0).ChangeToRegister(TmpReg, true); 355*fcaf7f86SDimitry Andric } 356*fcaf7f86SDimitry Andric // First LVM is LVMir. Others are LVMir_m. Last LVM places at the 357*fcaf7f86SDimitry Andric // next of the target instruction. 358*fcaf7f86SDimitry Andric if (i == 0) 359*fcaf7f86SDimitry Andric build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true)); 360*fcaf7f86SDimitry Andric else if (i != 3) 361*fcaf7f86SDimitry Andric build(VE::LVMir_m, DestReg) 362*fcaf7f86SDimitry Andric .addImm(i) 363*fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true)) 364*fcaf7f86SDimitry Andric .addReg(DestReg); 365*fcaf7f86SDimitry Andric else 366*fcaf7f86SDimitry Andric BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg) 367*fcaf7f86SDimitry Andric .addImm(3) 368*fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true)) 369*fcaf7f86SDimitry Andric .addReg(DestReg); 370*fcaf7f86SDimitry Andric } 371*fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 372*fcaf7f86SDimitry Andric } 373*fcaf7f86SDimitry Andric 374*fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg, 375*fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) { 376*fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::STVM512rii); 377*fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump()); 378*fcaf7f86SDimitry Andric 379*fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 56); 380*fcaf7f86SDimitry Andric 381*fcaf7f86SDimitry Andric Register SrcReg = MI.getOperand(3).getReg(); 382*fcaf7f86SDimitry Andric Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd); 383*fcaf7f86SDimitry Andric Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even); 384*fcaf7f86SDimitry Andric bool isKill = MI.getOperand(3).isKill(); 385*fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of 386*fcaf7f86SDimitry Andric // reserving SX16 all of the time. 387*fcaf7f86SDimitry Andric Register TmpReg = VE::SX16; 388*fcaf7f86SDimitry Andric // store low part of VMP 389*fcaf7f86SDimitry Andric MachineInstr *LastMI = nullptr; 390*fcaf7f86SDimitry Andric for (int i = 0; i < 4; ++i) { 391*fcaf7f86SDimitry Andric LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i); 392*fcaf7f86SDimitry Andric MachineInstr *StMI = 393*fcaf7f86SDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 394*fcaf7f86SDimitry Andric TmpReg, getKillRegState(true)); 395*fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0); 396*fcaf7f86SDimitry Andric Offset += 8; 397*fcaf7f86SDimitry Andric } 398*fcaf7f86SDimitry Andric if (isKill) 399*fcaf7f86SDimitry Andric LastMI->addRegisterKilled(SrcLoReg, &TRI, true); 400*fcaf7f86SDimitry Andric // store high part of VMP 401*fcaf7f86SDimitry Andric for (int i = 0; i < 3; ++i) { 402*fcaf7f86SDimitry Andric build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i); 403*fcaf7f86SDimitry Andric MachineInstr *StMI = 404*fcaf7f86SDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg( 405*fcaf7f86SDimitry Andric TmpReg, getKillRegState(true)); 406*fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0); 407*fcaf7f86SDimitry Andric Offset += 8; 408*fcaf7f86SDimitry Andric } 409*fcaf7f86SDimitry Andric LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3); 410*fcaf7f86SDimitry Andric if (isKill) { 411*fcaf7f86SDimitry Andric LastMI->addRegisterKilled(SrcHiReg, &TRI, true); 412*fcaf7f86SDimitry Andric // Add implicit super-register kills to the particular MI. 413*fcaf7f86SDimitry Andric LastMI->addRegisterKilled(SrcReg, &TRI, true); 414*fcaf7f86SDimitry Andric } 415*fcaf7f86SDimitry Andric MI.setDesc(get(VE::STrii)); 416*fcaf7f86SDimitry Andric MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true); 417*fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 418*fcaf7f86SDimitry Andric } 419*fcaf7f86SDimitry Andric 420*fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg, 421*fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) { 422*fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::LDVM512rii); 423*fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump()); 424*fcaf7f86SDimitry Andric 425*fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 56); 426*fcaf7f86SDimitry Andric 427*fcaf7f86SDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 428*fcaf7f86SDimitry Andric Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd); 429*fcaf7f86SDimitry Andric Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even); 430*fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of 431*fcaf7f86SDimitry Andric // reserving SX16 all of the time. 432*fcaf7f86SDimitry Andric Register TmpReg = VE::SX16; 433*fcaf7f86SDimitry Andric build(VE::IMPLICIT_DEF, DestReg); 434*fcaf7f86SDimitry Andric for (int i = 0; i < 4; ++i) { 435*fcaf7f86SDimitry Andric MachineInstr *LdMI = 436*fcaf7f86SDimitry Andric build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 437*fcaf7f86SDimitry Andric replaceFI(*LdMI, FrameReg, Offset, 1); 438*fcaf7f86SDimitry Andric build(VE::LVMir_m, DestLoReg) 439*fcaf7f86SDimitry Andric .addImm(i) 440*fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true)) 441*fcaf7f86SDimitry Andric .addReg(DestLoReg); 442*fcaf7f86SDimitry Andric Offset += 8; 443*fcaf7f86SDimitry Andric } 444*fcaf7f86SDimitry Andric for (int i = 0; i < 3; ++i) { 445*fcaf7f86SDimitry Andric MachineInstr *LdMI = 446*fcaf7f86SDimitry Andric build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0); 447*fcaf7f86SDimitry Andric replaceFI(*LdMI, FrameReg, Offset, 1); 448*fcaf7f86SDimitry Andric build(VE::LVMir_m, DestHiReg) 449*fcaf7f86SDimitry Andric .addImm(i) 450*fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true)) 451*fcaf7f86SDimitry Andric .addReg(DestHiReg); 452*fcaf7f86SDimitry Andric Offset += 8; 453*fcaf7f86SDimitry Andric } 454*fcaf7f86SDimitry Andric MI.setDesc(get(VE::LDrii)); 455*fcaf7f86SDimitry Andric MI.getOperand(0).ChangeToRegister(TmpReg, true); 456*fcaf7f86SDimitry Andric BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg) 457*fcaf7f86SDimitry Andric .addImm(3) 458*fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true)) 459*fcaf7f86SDimitry Andric .addReg(DestHiReg); 460*fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 461*fcaf7f86SDimitry Andric } 462*fcaf7f86SDimitry Andric 463753f127fSDimitry Andric void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg, 464753f127fSDimitry Andric int64_t Offset, int FIOperandNum) { 465753f127fSDimitry Andric switch (MI.getOpcode()) { 466753f127fSDimitry Andric case VE::STQrii: 467753f127fSDimitry Andric processSTQ(MI, FrameReg, Offset, FIOperandNum); 468753f127fSDimitry Andric return; 469753f127fSDimitry Andric case VE::LDQrii: 470753f127fSDimitry Andric processLDQ(MI, FrameReg, Offset, FIOperandNum); 471753f127fSDimitry Andric return; 472*fcaf7f86SDimitry Andric case VE::STVMrii: 473*fcaf7f86SDimitry Andric processSTVM(MI, FrameReg, Offset, FIOperandNum); 474*fcaf7f86SDimitry Andric return; 475*fcaf7f86SDimitry Andric case VE::LDVMrii: 476*fcaf7f86SDimitry Andric processLDVM(MI, FrameReg, Offset, FIOperandNum); 477*fcaf7f86SDimitry Andric return; 478*fcaf7f86SDimitry Andric case VE::STVM512rii: 479*fcaf7f86SDimitry Andric processSTVM512(MI, FrameReg, Offset, FIOperandNum); 480*fcaf7f86SDimitry Andric return; 481*fcaf7f86SDimitry Andric case VE::LDVM512rii: 482*fcaf7f86SDimitry Andric processLDVM512(MI, FrameReg, Offset, FIOperandNum); 483*fcaf7f86SDimitry Andric return; 484753f127fSDimitry Andric } 485753f127fSDimitry Andric prepareReplaceFI(MI, FrameReg, Offset); 486753f127fSDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum); 487753f127fSDimitry Andric } 488753f127fSDimitry Andric 489480093f4SDimitry Andric void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, 490480093f4SDimitry Andric int SPAdj, unsigned FIOperandNum, 491480093f4SDimitry Andric RegScavenger *RS) const { 492480093f4SDimitry Andric assert(SPAdj == 0 && "Unexpected"); 493480093f4SDimitry Andric 494480093f4SDimitry Andric MachineInstr &MI = *II; 495480093f4SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); 496753f127fSDimitry Andric 497480093f4SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 498753f127fSDimitry Andric const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>(); 499753f127fSDimitry Andric const VEFrameLowering &TFI = *getFrameLowering(MF); 500753f127fSDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 501753f127fSDimitry Andric const VERegisterInfo &TRI = *Subtarget.getRegisterInfo(); 502753f127fSDimitry Andric DebugLoc DL = MI.getDebugLoc(); 503753f127fSDimitry Andric EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II); 504480093f4SDimitry Andric 505753f127fSDimitry Andric // Retrieve FrameReg and byte offset for stack slot. 5065ffd83dbSDimitry Andric Register FrameReg; 507753f127fSDimitry Andric int64_t Offset = 508753f127fSDimitry Andric TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed(); 509e8d8bef9SDimitry Andric Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm(); 510e8d8bef9SDimitry Andric 511753f127fSDimitry Andric EFI.processMI(MI, FrameReg, Offset, FIOperandNum); 512480093f4SDimitry Andric } 513480093f4SDimitry Andric 514480093f4SDimitry Andric Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const { 515480093f4SDimitry Andric return VE::SX9; 516480093f4SDimitry Andric } 517