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
VERegisterInfo()36480093f4SDimitry Andric VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
37480093f4SDimitry Andric
38480093f4SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const39480093f4SDimitry 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
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const50480093f4SDimitry 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
getNoPreservedMask() const62480093f4SDimitry Andric const uint32_t *VERegisterInfo::getNoPreservedMask() const {
63480093f4SDimitry Andric return CSR_NoRegs_RegMask;
64480093f4SDimitry Andric }
65480093f4SDimitry Andric
getReservedRegs(const MachineFunction & MF) const66480093f4SDimitry 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
99480093f4SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const100480093f4SDimitry Andric VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
101480093f4SDimitry Andric unsigned Kind) const {
102480093f4SDimitry Andric return &VE::I64RegClass;
103480093f4SDimitry Andric }
104480093f4SDimitry Andric
offsetToDisp(MachineInstr & MI)105e8d8bef9SDimitry Andric static unsigned offsetToDisp(MachineInstr &MI) {
106e8d8bef9SDimitry Andric // Default offset in instruction's operands (reg+reg+imm).
107e8d8bef9SDimitry Andric unsigned OffDisp = 2;
108e8d8bef9SDimitry Andric
109e8d8bef9SDimitry Andric #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
110e8d8bef9SDimitry Andric
111e8d8bef9SDimitry Andric {
112e8d8bef9SDimitry Andric using namespace llvm::VE;
113e8d8bef9SDimitry Andric switch (MI.getOpcode()) {
114*bdd1243dSDimitry Andric case INLINEASM:
115e8d8bef9SDimitry Andric case RRCAS_multi_cases(TS1AML):
116e8d8bef9SDimitry Andric case RRCAS_multi_cases(TS1AMW):
117e8d8bef9SDimitry Andric case RRCAS_multi_cases(CASL):
118e8d8bef9SDimitry Andric case RRCAS_multi_cases(CASW):
119e8d8bef9SDimitry Andric // These instructions use AS format (reg+imm).
120e8d8bef9SDimitry Andric OffDisp = 1;
121e8d8bef9SDimitry Andric break;
122e8d8bef9SDimitry Andric }
123e8d8bef9SDimitry Andric }
124e8d8bef9SDimitry Andric #undef RRCAS_multi_cases
125e8d8bef9SDimitry Andric
126e8d8bef9SDimitry Andric return OffDisp;
127e8d8bef9SDimitry Andric }
128e8d8bef9SDimitry Andric
129*bdd1243dSDimitry Andric namespace {
130753f127fSDimitry Andric class EliminateFrameIndex {
131753f127fSDimitry Andric const TargetInstrInfo &TII;
132753f127fSDimitry Andric const TargetRegisterInfo &TRI;
133753f127fSDimitry Andric const DebugLoc &DL;
134753f127fSDimitry Andric MachineBasicBlock &MBB;
135753f127fSDimitry Andric MachineBasicBlock::iterator II;
136753f127fSDimitry Andric Register clobber;
137753f127fSDimitry Andric
138753f127fSDimitry Andric // Some helper functions for the ease of instruction building.
getFunc() const139753f127fSDimitry Andric MachineFunction &getFunc() const { return *MBB.getParent(); }
getSubReg(MCRegister Reg,unsigned Idx) const140753f127fSDimitry Andric inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
141753f127fSDimitry Andric return TRI.getSubReg(Reg, Idx);
142753f127fSDimitry Andric }
get(unsigned Opcode) const143753f127fSDimitry Andric inline const MCInstrDesc &get(unsigned Opcode) const {
144753f127fSDimitry Andric return TII.get(Opcode);
145753f127fSDimitry Andric }
build(const MCInstrDesc & MCID,Register DestReg)146753f127fSDimitry Andric inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
147753f127fSDimitry Andric return BuildMI(MBB, II, DL, MCID, DestReg);
148753f127fSDimitry Andric }
build(unsigned InstOpc,Register DestReg)149753f127fSDimitry Andric inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
150753f127fSDimitry Andric return build(get(InstOpc), DestReg);
151753f127fSDimitry Andric }
build(const MCInstrDesc & MCID)152753f127fSDimitry Andric inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
153753f127fSDimitry Andric return BuildMI(MBB, II, DL, MCID);
154753f127fSDimitry Andric }
build(unsigned InstOpc)155753f127fSDimitry Andric inline MachineInstrBuilder build(unsigned InstOpc) {
156753f127fSDimitry Andric return build(get(InstOpc));
157753f127fSDimitry Andric }
158753f127fSDimitry Andric
159753f127fSDimitry Andric // Calculate an address of frame index from a frame register and a given
160753f127fSDimitry Andric // offset if the offset doesn't fit in the immediate field. Use a clobber
161753f127fSDimitry Andric // register to hold calculated address.
162753f127fSDimitry Andric void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
163753f127fSDimitry Andric int64_t Bytes = 0);
164753f127fSDimitry Andric // Replace the frame index in \p MI with a frame register and a given offset
165753f127fSDimitry Andric // if it fits in the immediate field. Otherwise, use pre-calculated address
166753f127fSDimitry Andric // in a clobber regsiter.
167753f127fSDimitry Andric void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
168753f127fSDimitry Andric int FIOperandNum);
169753f127fSDimitry Andric
170753f127fSDimitry Andric // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
171753f127fSDimitry Andric void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
172753f127fSDimitry Andric int FIOperandNum);
173753f127fSDimitry Andric void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
174753f127fSDimitry Andric int FIOperandNum);
175fcaf7f86SDimitry Andric // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
176fcaf7f86SDimitry Andric void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
177fcaf7f86SDimitry Andric int FIOperandNum);
178fcaf7f86SDimitry Andric void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
179fcaf7f86SDimitry Andric int FIOperandNum);
180fcaf7f86SDimitry Andric // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
181fcaf7f86SDimitry Andric void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
182fcaf7f86SDimitry Andric int FIOperandNum);
183fcaf7f86SDimitry Andric void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
184fcaf7f86SDimitry Andric int FIOperandNum);
185753f127fSDimitry Andric
186753f127fSDimitry Andric public:
EliminateFrameIndex(const TargetInstrInfo & TII,const TargetRegisterInfo & TRI,const DebugLoc & DL,MachineBasicBlock & MBB,MachineBasicBlock::iterator II)187753f127fSDimitry Andric EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
188753f127fSDimitry Andric const DebugLoc &DL, MachineBasicBlock &MBB,
189753f127fSDimitry Andric MachineBasicBlock::iterator II)
190753f127fSDimitry Andric : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
191753f127fSDimitry Andric
192753f127fSDimitry Andric // Expand and eliminate Frame Index from MI
193753f127fSDimitry Andric void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
194753f127fSDimitry Andric int FIOperandNum);
195753f127fSDimitry Andric };
196*bdd1243dSDimitry Andric } // namespace
197753f127fSDimitry Andric
198753f127fSDimitry Andric // Prepare the frame index if it doesn't fit in the immediate field. Use
199753f127fSDimitry Andric // clobber register to hold calculated address.
prepareReplaceFI(MachineInstr & MI,Register & FrameReg,int64_t & Offset,int64_t Bytes)200753f127fSDimitry Andric void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
201753f127fSDimitry Andric int64_t &Offset, int64_t Bytes) {
202753f127fSDimitry Andric if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
203753f127fSDimitry Andric // If the offset is small enough to fit in the immediate field, directly
204753f127fSDimitry Andric // encode it. So, nothing to prepare here.
205753f127fSDimitry Andric return;
206753f127fSDimitry Andric }
207753f127fSDimitry Andric
208753f127fSDimitry Andric // If the offset doesn't fit, emit following codes. This clobbers SX13
209753f127fSDimitry Andric // which we always know is available here.
210753f127fSDimitry Andric // lea %clobber, Offset@lo
211753f127fSDimitry Andric // and %clobber, %clobber, (32)0
212753f127fSDimitry Andric // lea.sl %clobber, Offset@hi(FrameReg, %clobber)
213753f127fSDimitry Andric build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
214753f127fSDimitry Andric build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
215753f127fSDimitry Andric build(VE::LEASLrri, clobber)
216753f127fSDimitry Andric .addReg(clobber)
217753f127fSDimitry Andric .addReg(FrameReg)
218753f127fSDimitry Andric .addImm(Hi_32(Offset));
219753f127fSDimitry Andric
220753f127fSDimitry Andric // Use clobber register as a frame register and 0 offset
221753f127fSDimitry Andric FrameReg = clobber;
222753f127fSDimitry Andric Offset = 0;
223753f127fSDimitry Andric }
224753f127fSDimitry Andric
225753f127fSDimitry Andric // Replace the frame index in \p MI with a proper byte and framereg offset.
replaceFI(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)226753f127fSDimitry Andric void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
227753f127fSDimitry Andric int64_t Offset, int FIOperandNum) {
228753f127fSDimitry Andric assert(isInt<32>(Offset));
229753f127fSDimitry Andric
230753f127fSDimitry Andric // The offset must be small enough to fit in the immediate field after
231753f127fSDimitry Andric // call of prepareReplaceFI. Therefore, we directly encode it.
2325ffd83dbSDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
233e8d8bef9SDimitry Andric MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
234480093f4SDimitry Andric }
235480093f4SDimitry Andric
processSTQ(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)236753f127fSDimitry Andric void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
237753f127fSDimitry Andric int64_t Offset, int FIOperandNum) {
238753f127fSDimitry Andric assert(MI.getOpcode() == VE::STQrii);
239753f127fSDimitry Andric LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
240753f127fSDimitry Andric
241753f127fSDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 8);
242753f127fSDimitry Andric
243753f127fSDimitry Andric Register SrcReg = MI.getOperand(3).getReg();
244753f127fSDimitry Andric Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
245753f127fSDimitry Andric Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
246753f127fSDimitry Andric // VE stores HiReg to 8(addr) and LoReg to 0(addr)
247753f127fSDimitry Andric MachineInstr *StMI =
248753f127fSDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
249753f127fSDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0);
250753f127fSDimitry Andric // Mutate to 'hi' store.
251753f127fSDimitry Andric MI.setDesc(get(VE::STrii));
252753f127fSDimitry Andric MI.getOperand(3).setReg(SrcHiReg);
253753f127fSDimitry Andric Offset += 8;
254753f127fSDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
255753f127fSDimitry Andric }
256753f127fSDimitry Andric
processLDQ(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)257753f127fSDimitry Andric void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
258753f127fSDimitry Andric int64_t Offset, int FIOperandNum) {
259753f127fSDimitry Andric assert(MI.getOpcode() == VE::LDQrii);
260753f127fSDimitry Andric LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
261753f127fSDimitry Andric
262753f127fSDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 8);
263753f127fSDimitry Andric
264753f127fSDimitry Andric Register DestReg = MI.getOperand(0).getReg();
265753f127fSDimitry Andric Register DestHiReg = getSubReg(DestReg, VE::sub_even);
266753f127fSDimitry Andric Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
267753f127fSDimitry Andric // VE loads HiReg from 8(addr) and LoReg from 0(addr)
268753f127fSDimitry Andric MachineInstr *StMI =
269753f127fSDimitry Andric build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
270753f127fSDimitry Andric replaceFI(*StMI, FrameReg, Offset, 1);
271753f127fSDimitry Andric MI.setDesc(get(VE::LDrii));
272753f127fSDimitry Andric MI.getOperand(0).setReg(DestHiReg);
273753f127fSDimitry Andric Offset += 8;
274753f127fSDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
275753f127fSDimitry Andric }
276753f127fSDimitry Andric
processSTVM(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)277fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,
278fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) {
279fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::STVMrii);
280fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());
281fcaf7f86SDimitry Andric
282fcaf7f86SDimitry Andric // Original MI is:
283fcaf7f86SDimitry Andric // STVMrii frame-index, 0, offset, reg (, memory operand)
284fcaf7f86SDimitry Andric // Convert it to:
285fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 0
286fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset, tmp-reg
287fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 1
288fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset+8, tmp-reg
289fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 2
290fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset+16, tmp-reg
291fcaf7f86SDimitry Andric // SVMi tmp-reg, reg, 3
292fcaf7f86SDimitry Andric // STrii frame-reg, 0, offset+24, tmp-reg
293fcaf7f86SDimitry Andric
294fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 24);
295fcaf7f86SDimitry Andric
296fcaf7f86SDimitry Andric Register SrcReg = MI.getOperand(3).getReg();
297fcaf7f86SDimitry Andric bool isKill = MI.getOperand(3).isKill();
298fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of
299fcaf7f86SDimitry Andric // reserving SX16 all of the time.
300fcaf7f86SDimitry Andric Register TmpReg = VE::SX16;
301fcaf7f86SDimitry Andric for (int i = 0; i < 3; ++i) {
302fcaf7f86SDimitry Andric build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);
303fcaf7f86SDimitry Andric MachineInstr *StMI =
304fcaf7f86SDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
305fcaf7f86SDimitry Andric TmpReg, getKillRegState(true));
306fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0);
307fcaf7f86SDimitry Andric Offset += 8;
308fcaf7f86SDimitry Andric }
309fcaf7f86SDimitry Andric build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);
310fcaf7f86SDimitry Andric MI.setDesc(get(VE::STrii));
311fcaf7f86SDimitry Andric MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
312fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
313fcaf7f86SDimitry Andric }
314fcaf7f86SDimitry Andric
processLDVM(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)315fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,
316fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) {
317fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::LDVMrii);
318fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());
319fcaf7f86SDimitry Andric
320fcaf7f86SDimitry Andric // Original MI is:
321fcaf7f86SDimitry Andric // LDVMri reg, frame-index, 0, offset (, memory operand)
322fcaf7f86SDimitry Andric // Convert it to:
323fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset
324fcaf7f86SDimitry Andric // LVMir vm, 0, tmp-reg
325fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset+8
326fcaf7f86SDimitry Andric // LVMir_m vm, 1, tmp-reg, vm
327fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset+16
328fcaf7f86SDimitry Andric // LVMir_m vm, 2, tmp-reg, vm
329fcaf7f86SDimitry Andric // LDrii tmp-reg, frame-reg, 0, offset+24
330fcaf7f86SDimitry Andric // LVMir_m vm, 3, tmp-reg, vm
331fcaf7f86SDimitry Andric
332fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 24);
333fcaf7f86SDimitry Andric
334fcaf7f86SDimitry Andric Register DestReg = MI.getOperand(0).getReg();
335fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of
336fcaf7f86SDimitry Andric // reserving SX16 all of the time.
337fcaf7f86SDimitry Andric unsigned TmpReg = VE::SX16;
338fcaf7f86SDimitry Andric for (int i = 0; i < 4; ++i) {
339fcaf7f86SDimitry Andric if (i != 3) {
340fcaf7f86SDimitry Andric MachineInstr *StMI =
341fcaf7f86SDimitry Andric build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
342fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 1);
343fcaf7f86SDimitry Andric Offset += 8;
344fcaf7f86SDimitry Andric } else {
345fcaf7f86SDimitry Andric // Last LDrii replace the target instruction.
346fcaf7f86SDimitry Andric MI.setDesc(get(VE::LDrii));
347fcaf7f86SDimitry Andric MI.getOperand(0).ChangeToRegister(TmpReg, true);
348fcaf7f86SDimitry Andric }
349fcaf7f86SDimitry Andric // First LVM is LVMir. Others are LVMir_m. Last LVM places at the
350fcaf7f86SDimitry Andric // next of the target instruction.
351fcaf7f86SDimitry Andric if (i == 0)
352fcaf7f86SDimitry Andric build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));
353fcaf7f86SDimitry Andric else if (i != 3)
354fcaf7f86SDimitry Andric build(VE::LVMir_m, DestReg)
355fcaf7f86SDimitry Andric .addImm(i)
356fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true))
357fcaf7f86SDimitry Andric .addReg(DestReg);
358fcaf7f86SDimitry Andric else
359fcaf7f86SDimitry Andric BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)
360fcaf7f86SDimitry Andric .addImm(3)
361fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true))
362fcaf7f86SDimitry Andric .addReg(DestReg);
363fcaf7f86SDimitry Andric }
364fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
365fcaf7f86SDimitry Andric }
366fcaf7f86SDimitry Andric
processSTVM512(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)367fcaf7f86SDimitry Andric void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,
368fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) {
369fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::STVM512rii);
370fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());
371fcaf7f86SDimitry Andric
372fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 56);
373fcaf7f86SDimitry Andric
374fcaf7f86SDimitry Andric Register SrcReg = MI.getOperand(3).getReg();
375fcaf7f86SDimitry Andric Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);
376fcaf7f86SDimitry Andric Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);
377fcaf7f86SDimitry Andric bool isKill = MI.getOperand(3).isKill();
378fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of
379fcaf7f86SDimitry Andric // reserving SX16 all of the time.
380fcaf7f86SDimitry Andric Register TmpReg = VE::SX16;
381fcaf7f86SDimitry Andric // store low part of VMP
382fcaf7f86SDimitry Andric MachineInstr *LastMI = nullptr;
383fcaf7f86SDimitry Andric for (int i = 0; i < 4; ++i) {
384fcaf7f86SDimitry Andric LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);
385fcaf7f86SDimitry Andric MachineInstr *StMI =
386fcaf7f86SDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
387fcaf7f86SDimitry Andric TmpReg, getKillRegState(true));
388fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0);
389fcaf7f86SDimitry Andric Offset += 8;
390fcaf7f86SDimitry Andric }
391fcaf7f86SDimitry Andric if (isKill)
392fcaf7f86SDimitry Andric LastMI->addRegisterKilled(SrcLoReg, &TRI, true);
393fcaf7f86SDimitry Andric // store high part of VMP
394fcaf7f86SDimitry Andric for (int i = 0; i < 3; ++i) {
395fcaf7f86SDimitry Andric build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);
396fcaf7f86SDimitry Andric MachineInstr *StMI =
397fcaf7f86SDimitry Andric build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
398fcaf7f86SDimitry Andric TmpReg, getKillRegState(true));
399fcaf7f86SDimitry Andric replaceFI(*StMI, FrameReg, Offset, 0);
400fcaf7f86SDimitry Andric Offset += 8;
401fcaf7f86SDimitry Andric }
402fcaf7f86SDimitry Andric LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);
403fcaf7f86SDimitry Andric if (isKill) {
404fcaf7f86SDimitry Andric LastMI->addRegisterKilled(SrcHiReg, &TRI, true);
405fcaf7f86SDimitry Andric // Add implicit super-register kills to the particular MI.
406fcaf7f86SDimitry Andric LastMI->addRegisterKilled(SrcReg, &TRI, true);
407fcaf7f86SDimitry Andric }
408fcaf7f86SDimitry Andric MI.setDesc(get(VE::STrii));
409fcaf7f86SDimitry Andric MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
410fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
411fcaf7f86SDimitry Andric }
412fcaf7f86SDimitry Andric
processLDVM512(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)413fcaf7f86SDimitry Andric void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,
414fcaf7f86SDimitry Andric int64_t Offset, int FIOperandNum) {
415fcaf7f86SDimitry Andric assert(MI.getOpcode() == VE::LDVM512rii);
416fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());
417fcaf7f86SDimitry Andric
418fcaf7f86SDimitry Andric prepareReplaceFI(MI, FrameReg, Offset, 56);
419fcaf7f86SDimitry Andric
420fcaf7f86SDimitry Andric Register DestReg = MI.getOperand(0).getReg();
421fcaf7f86SDimitry Andric Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);
422fcaf7f86SDimitry Andric Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);
423fcaf7f86SDimitry Andric // FIXME: it would be better to scavenge a register here instead of
424fcaf7f86SDimitry Andric // reserving SX16 all of the time.
425fcaf7f86SDimitry Andric Register TmpReg = VE::SX16;
426fcaf7f86SDimitry Andric build(VE::IMPLICIT_DEF, DestReg);
427fcaf7f86SDimitry Andric for (int i = 0; i < 4; ++i) {
428fcaf7f86SDimitry Andric MachineInstr *LdMI =
429fcaf7f86SDimitry Andric build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
430fcaf7f86SDimitry Andric replaceFI(*LdMI, FrameReg, Offset, 1);
431fcaf7f86SDimitry Andric build(VE::LVMir_m, DestLoReg)
432fcaf7f86SDimitry Andric .addImm(i)
433fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true))
434fcaf7f86SDimitry Andric .addReg(DestLoReg);
435fcaf7f86SDimitry Andric Offset += 8;
436fcaf7f86SDimitry Andric }
437fcaf7f86SDimitry Andric for (int i = 0; i < 3; ++i) {
438fcaf7f86SDimitry Andric MachineInstr *LdMI =
439fcaf7f86SDimitry Andric build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
440fcaf7f86SDimitry Andric replaceFI(*LdMI, FrameReg, Offset, 1);
441fcaf7f86SDimitry Andric build(VE::LVMir_m, DestHiReg)
442fcaf7f86SDimitry Andric .addImm(i)
443fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true))
444fcaf7f86SDimitry Andric .addReg(DestHiReg);
445fcaf7f86SDimitry Andric Offset += 8;
446fcaf7f86SDimitry Andric }
447fcaf7f86SDimitry Andric MI.setDesc(get(VE::LDrii));
448fcaf7f86SDimitry Andric MI.getOperand(0).ChangeToRegister(TmpReg, true);
449fcaf7f86SDimitry Andric BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)
450fcaf7f86SDimitry Andric .addImm(3)
451fcaf7f86SDimitry Andric .addReg(TmpReg, getKillRegState(true))
452fcaf7f86SDimitry Andric .addReg(DestHiReg);
453fcaf7f86SDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
454fcaf7f86SDimitry Andric }
455fcaf7f86SDimitry Andric
processMI(MachineInstr & MI,Register FrameReg,int64_t Offset,int FIOperandNum)456753f127fSDimitry Andric void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
457753f127fSDimitry Andric int64_t Offset, int FIOperandNum) {
458753f127fSDimitry Andric switch (MI.getOpcode()) {
459753f127fSDimitry Andric case VE::STQrii:
460753f127fSDimitry Andric processSTQ(MI, FrameReg, Offset, FIOperandNum);
461753f127fSDimitry Andric return;
462753f127fSDimitry Andric case VE::LDQrii:
463753f127fSDimitry Andric processLDQ(MI, FrameReg, Offset, FIOperandNum);
464753f127fSDimitry Andric return;
465fcaf7f86SDimitry Andric case VE::STVMrii:
466fcaf7f86SDimitry Andric processSTVM(MI, FrameReg, Offset, FIOperandNum);
467fcaf7f86SDimitry Andric return;
468fcaf7f86SDimitry Andric case VE::LDVMrii:
469fcaf7f86SDimitry Andric processLDVM(MI, FrameReg, Offset, FIOperandNum);
470fcaf7f86SDimitry Andric return;
471fcaf7f86SDimitry Andric case VE::STVM512rii:
472fcaf7f86SDimitry Andric processSTVM512(MI, FrameReg, Offset, FIOperandNum);
473fcaf7f86SDimitry Andric return;
474fcaf7f86SDimitry Andric case VE::LDVM512rii:
475fcaf7f86SDimitry Andric processLDVM512(MI, FrameReg, Offset, FIOperandNum);
476fcaf7f86SDimitry Andric return;
477753f127fSDimitry Andric }
478753f127fSDimitry Andric prepareReplaceFI(MI, FrameReg, Offset);
479753f127fSDimitry Andric replaceFI(MI, FrameReg, Offset, FIOperandNum);
480753f127fSDimitry Andric }
481753f127fSDimitry Andric
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const482*bdd1243dSDimitry Andric bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
483480093f4SDimitry Andric int SPAdj, unsigned FIOperandNum,
484480093f4SDimitry Andric RegScavenger *RS) const {
485480093f4SDimitry Andric assert(SPAdj == 0 && "Unexpected");
486480093f4SDimitry Andric
487480093f4SDimitry Andric MachineInstr &MI = *II;
488480093f4SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
489753f127fSDimitry Andric
490480093f4SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent();
491753f127fSDimitry Andric const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
492753f127fSDimitry Andric const VEFrameLowering &TFI = *getFrameLowering(MF);
493753f127fSDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
494753f127fSDimitry Andric const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
495753f127fSDimitry Andric DebugLoc DL = MI.getDebugLoc();
496753f127fSDimitry Andric EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
497480093f4SDimitry Andric
498753f127fSDimitry Andric // Retrieve FrameReg and byte offset for stack slot.
4995ffd83dbSDimitry Andric Register FrameReg;
500753f127fSDimitry Andric int64_t Offset =
501753f127fSDimitry Andric TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
502e8d8bef9SDimitry Andric Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
503e8d8bef9SDimitry Andric
504753f127fSDimitry Andric EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
505*bdd1243dSDimitry Andric return false;
506480093f4SDimitry Andric }
507480093f4SDimitry Andric
getFrameRegister(const MachineFunction & MF) const508480093f4SDimitry Andric Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
509480093f4SDimitry Andric return VE::SX9;
510480093f4SDimitry Andric }
511