1 //===-- VERegisterInfo.cpp - VE Register Information ----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the VE implementation of the TargetRegisterInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "VERegisterInfo.h"
14 #include "VE.h"
15 #include "VESubtarget.h"
16 #include "llvm/ADT/BitVector.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/CodeGen/TargetInstrInfo.h"
23 #include "llvm/IR/Type.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/ErrorHandling.h"
27 
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "ve-register-info"
31 
32 #define GET_REGINFO_TARGET_DESC
33 #include "VEGenRegisterInfo.inc"
34 
35 // VE uses %s10 == %lp to keep return address
36 VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
37 
38 const MCPhysReg *
39 VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
40   switch (MF->getFunction().getCallingConv()) {
41   case CallingConv::Fast:
42     // Being explicit (same as standard CC).
43   default:
44     return CSR_SaveList;
45   case CallingConv::PreserveAll:
46     return CSR_preserve_all_SaveList;
47   }
48 }
49 
50 const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF,
51                                                      CallingConv::ID CC) const {
52   switch (CC) {
53   case CallingConv::Fast:
54     // Being explicit (same as standard CC).
55   default:
56     return CSR_RegMask;
57   case CallingConv::PreserveAll:
58     return CSR_preserve_all_RegMask;
59   }
60 }
61 
62 const uint32_t *VERegisterInfo::getNoPreservedMask() const {
63   return CSR_NoRegs_RegMask;
64 }
65 
66 BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
67   BitVector Reserved(getNumRegs());
68 
69   const Register ReservedRegs[] = {
70       VE::SX8,  // Stack limit
71       VE::SX9,  // Frame pointer
72       VE::SX10, // Link register (return address)
73       VE::SX11, // Stack pointer
74 
75       // FIXME: maybe not need to be reserved
76       VE::SX12, // Outer register
77       VE::SX13, // Id register for dynamic linker
78 
79       VE::SX14, // Thread pointer
80       VE::SX15, // Global offset table register
81       VE::SX16, // Procedure linkage table register
82       VE::SX17, // Linkage-area register
83                 // sx18-sx33 are callee-saved registers
84                 // sx34-sx63 are temporary registers
85   };
86 
87   for (auto R : ReservedRegs)
88     for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid();
89          ++ItAlias)
90       Reserved.set(*ItAlias);
91 
92   // Reserve constant registers.
93   Reserved.set(VE::VM0);
94   Reserved.set(VE::VMP0);
95 
96   return Reserved;
97 }
98 
99 const TargetRegisterClass *
100 VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
101                                    unsigned Kind) const {
102   return &VE::I64RegClass;
103 }
104 
105 static unsigned offsetToDisp(MachineInstr &MI) {
106   // Default offset in instruction's operands (reg+reg+imm).
107   unsigned OffDisp = 2;
108 
109 #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
110 
111   {
112     using namespace llvm::VE;
113     switch (MI.getOpcode()) {
114     case INLINEASM:
115     case RRCAS_multi_cases(TS1AML):
116     case RRCAS_multi_cases(TS1AMW):
117     case RRCAS_multi_cases(CASL):
118     case RRCAS_multi_cases(CASW):
119       // These instructions use AS format (reg+imm).
120       OffDisp = 1;
121       break;
122     }
123   }
124 #undef RRCAS_multi_cases
125 
126   return OffDisp;
127 }
128 
129 namespace {
130 class EliminateFrameIndex {
131   const TargetInstrInfo &TII;
132   const TargetRegisterInfo &TRI;
133   const DebugLoc &DL;
134   MachineBasicBlock &MBB;
135   MachineBasicBlock::iterator II;
136   Register clobber;
137 
138   // Some helper functions for the ease of instruction building.
139   MachineFunction &getFunc() const { return *MBB.getParent(); }
140   inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
141     return TRI.getSubReg(Reg, Idx);
142   }
143   inline const MCInstrDesc &get(unsigned Opcode) const {
144     return TII.get(Opcode);
145   }
146   inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
147     return BuildMI(MBB, II, DL, MCID, DestReg);
148   }
149   inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
150     return build(get(InstOpc), DestReg);
151   }
152   inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
153     return BuildMI(MBB, II, DL, MCID);
154   }
155   inline MachineInstrBuilder build(unsigned InstOpc) {
156     return build(get(InstOpc));
157   }
158 
159   // Calculate an address of frame index from a frame register and a given
160   // offset if the offset doesn't fit in the immediate field.  Use a clobber
161   // register to hold calculated address.
162   void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
163                         int64_t Bytes = 0);
164   // Replace the frame index in \p MI with a frame register and a given offset
165   // if it fits in the immediate field.  Otherwise, use pre-calculated address
166   // in a clobber regsiter.
167   void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
168                  int FIOperandNum);
169 
170   // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
171   void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
172                   int FIOperandNum);
173   void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
174                   int FIOperandNum);
175   // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
176   void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
177                    int FIOperandNum);
178   void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
179                    int FIOperandNum);
180   // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
181   void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
182                       int FIOperandNum);
183   void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
184                       int FIOperandNum);
185 
186 public:
187   EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
188                       const DebugLoc &DL, MachineBasicBlock &MBB,
189                       MachineBasicBlock::iterator II)
190       : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
191 
192   // Expand and eliminate Frame Index from MI
193   void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
194                  int FIOperandNum);
195 };
196 } // namespace
197 
198 // Prepare the frame index if it doesn't fit in the immediate field.  Use
199 // clobber register to hold calculated address.
200 void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
201                                            int64_t &Offset, int64_t Bytes) {
202   if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
203     // If the offset is small enough to fit in the immediate field, directly
204     // encode it.  So, nothing to prepare here.
205     return;
206   }
207 
208   // If the offset doesn't fit, emit following codes.  This clobbers SX13
209   // which we always know is available here.
210   //   lea     %clobber, Offset@lo
211   //   and     %clobber, %clobber, (32)0
212   //   lea.sl  %clobber, Offset@hi(FrameReg, %clobber)
213   build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
214   build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
215   build(VE::LEASLrri, clobber)
216       .addReg(clobber)
217       .addReg(FrameReg)
218       .addImm(Hi_32(Offset));
219 
220   // Use clobber register as a frame register and 0 offset
221   FrameReg = clobber;
222   Offset = 0;
223 }
224 
225 // Replace the frame index in \p MI with a proper byte and framereg offset.
226 void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
227                                     int64_t Offset, int FIOperandNum) {
228   assert(isInt<32>(Offset));
229 
230   // The offset must be small enough to fit in the immediate field after
231   // call of prepareReplaceFI.  Therefore, we directly encode it.
232   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
233   MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
234 }
235 
236 void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
237                                      int64_t Offset, int FIOperandNum) {
238   assert(MI.getOpcode() == VE::STQrii);
239   LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
240 
241   prepareReplaceFI(MI, FrameReg, Offset, 8);
242 
243   Register SrcReg = MI.getOperand(3).getReg();
244   Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
245   Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
246   // VE stores HiReg to 8(addr) and LoReg to 0(addr)
247   MachineInstr *StMI =
248       build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
249   replaceFI(*StMI, FrameReg, Offset, 0);
250   // Mutate to 'hi' store.
251   MI.setDesc(get(VE::STrii));
252   MI.getOperand(3).setReg(SrcHiReg);
253   Offset += 8;
254   replaceFI(MI, FrameReg, Offset, FIOperandNum);
255 }
256 
257 void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
258                                      int64_t Offset, int FIOperandNum) {
259   assert(MI.getOpcode() == VE::LDQrii);
260   LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
261 
262   prepareReplaceFI(MI, FrameReg, Offset, 8);
263 
264   Register DestReg = MI.getOperand(0).getReg();
265   Register DestHiReg = getSubReg(DestReg, VE::sub_even);
266   Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
267   // VE loads HiReg from 8(addr) and LoReg from 0(addr)
268   MachineInstr *StMI =
269       build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
270   replaceFI(*StMI, FrameReg, Offset, 1);
271   MI.setDesc(get(VE::LDrii));
272   MI.getOperand(0).setReg(DestHiReg);
273   Offset += 8;
274   replaceFI(MI, FrameReg, Offset, FIOperandNum);
275 }
276 
277 void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,
278                                       int64_t Offset, int FIOperandNum) {
279   assert(MI.getOpcode() == VE::STVMrii);
280   LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());
281 
282   // Original MI is:
283   //   STVMrii frame-index, 0, offset, reg (, memory operand)
284   // Convert it to:
285   //   SVMi   tmp-reg, reg, 0
286   //   STrii  frame-reg, 0, offset, tmp-reg
287   //   SVMi   tmp-reg, reg, 1
288   //   STrii  frame-reg, 0, offset+8, tmp-reg
289   //   SVMi   tmp-reg, reg, 2
290   //   STrii  frame-reg, 0, offset+16, tmp-reg
291   //   SVMi   tmp-reg, reg, 3
292   //   STrii  frame-reg, 0, offset+24, tmp-reg
293 
294   prepareReplaceFI(MI, FrameReg, Offset, 24);
295 
296   Register SrcReg = MI.getOperand(3).getReg();
297   bool isKill = MI.getOperand(3).isKill();
298   // FIXME: it would be better to scavenge a register here instead of
299   // reserving SX16 all of the time.
300   Register TmpReg = VE::SX16;
301   for (int i = 0; i < 3; ++i) {
302     build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);
303     MachineInstr *StMI =
304         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
305             TmpReg, getKillRegState(true));
306     replaceFI(*StMI, FrameReg, Offset, 0);
307     Offset += 8;
308   }
309   build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);
310   MI.setDesc(get(VE::STrii));
311   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
312   replaceFI(MI, FrameReg, Offset, FIOperandNum);
313 }
314 
315 void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,
316                                       int64_t Offset, int FIOperandNum) {
317   assert(MI.getOpcode() == VE::LDVMrii);
318   LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());
319 
320   // Original MI is:
321   //   LDVMri reg, frame-index, 0, offset (, memory operand)
322   // Convert it to:
323   //   LDrii  tmp-reg, frame-reg, 0, offset
324   //   LVMir vm, 0, tmp-reg
325   //   LDrii  tmp-reg, frame-reg, 0, offset+8
326   //   LVMir_m vm, 1, tmp-reg, vm
327   //   LDrii  tmp-reg, frame-reg, 0, offset+16
328   //   LVMir_m vm, 2, tmp-reg, vm
329   //   LDrii  tmp-reg, frame-reg, 0, offset+24
330   //   LVMir_m vm, 3, tmp-reg, vm
331 
332   prepareReplaceFI(MI, FrameReg, Offset, 24);
333 
334   Register DestReg = MI.getOperand(0).getReg();
335   // FIXME: it would be better to scavenge a register here instead of
336   // reserving SX16 all of the time.
337   unsigned TmpReg = VE::SX16;
338   for (int i = 0; i < 4; ++i) {
339     if (i != 3) {
340       MachineInstr *StMI =
341           build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
342       replaceFI(*StMI, FrameReg, Offset, 1);
343       Offset += 8;
344     } else {
345       // Last LDrii replace the target instruction.
346       MI.setDesc(get(VE::LDrii));
347       MI.getOperand(0).ChangeToRegister(TmpReg, true);
348     }
349     // First LVM is LVMir.  Others are LVMir_m.  Last LVM places at the
350     // next of the target instruction.
351     if (i == 0)
352       build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));
353     else if (i != 3)
354       build(VE::LVMir_m, DestReg)
355           .addImm(i)
356           .addReg(TmpReg, getKillRegState(true))
357           .addReg(DestReg);
358     else
359       BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)
360           .addImm(3)
361           .addReg(TmpReg, getKillRegState(true))
362           .addReg(DestReg);
363   }
364   replaceFI(MI, FrameReg, Offset, FIOperandNum);
365 }
366 
367 void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,
368                                          int64_t Offset, int FIOperandNum) {
369   assert(MI.getOpcode() == VE::STVM512rii);
370   LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());
371 
372   prepareReplaceFI(MI, FrameReg, Offset, 56);
373 
374   Register SrcReg = MI.getOperand(3).getReg();
375   Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);
376   Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);
377   bool isKill = MI.getOperand(3).isKill();
378   // FIXME: it would be better to scavenge a register here instead of
379   // reserving SX16 all of the time.
380   Register TmpReg = VE::SX16;
381   // store low part of VMP
382   MachineInstr *LastMI = nullptr;
383   for (int i = 0; i < 4; ++i) {
384     LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);
385     MachineInstr *StMI =
386         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
387             TmpReg, getKillRegState(true));
388     replaceFI(*StMI, FrameReg, Offset, 0);
389     Offset += 8;
390   }
391   if (isKill)
392     LastMI->addRegisterKilled(SrcLoReg, &TRI, true);
393   // store high part of VMP
394   for (int i = 0; i < 3; ++i) {
395     build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);
396     MachineInstr *StMI =
397         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
398             TmpReg, getKillRegState(true));
399     replaceFI(*StMI, FrameReg, Offset, 0);
400     Offset += 8;
401   }
402   LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);
403   if (isKill) {
404     LastMI->addRegisterKilled(SrcHiReg, &TRI, true);
405     // Add implicit super-register kills to the particular MI.
406     LastMI->addRegisterKilled(SrcReg, &TRI, true);
407   }
408   MI.setDesc(get(VE::STrii));
409   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
410   replaceFI(MI, FrameReg, Offset, FIOperandNum);
411 }
412 
413 void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,
414                                          int64_t Offset, int FIOperandNum) {
415   assert(MI.getOpcode() == VE::LDVM512rii);
416   LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());
417 
418   prepareReplaceFI(MI, FrameReg, Offset, 56);
419 
420   Register DestReg = MI.getOperand(0).getReg();
421   Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);
422   Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);
423   // FIXME: it would be better to scavenge a register here instead of
424   // reserving SX16 all of the time.
425   Register TmpReg = VE::SX16;
426   build(VE::IMPLICIT_DEF, DestReg);
427   for (int i = 0; i < 4; ++i) {
428     MachineInstr *LdMI =
429         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
430     replaceFI(*LdMI, FrameReg, Offset, 1);
431     build(VE::LVMir_m, DestLoReg)
432         .addImm(i)
433         .addReg(TmpReg, getKillRegState(true))
434         .addReg(DestLoReg);
435     Offset += 8;
436   }
437   for (int i = 0; i < 3; ++i) {
438     MachineInstr *LdMI =
439         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
440     replaceFI(*LdMI, FrameReg, Offset, 1);
441     build(VE::LVMir_m, DestHiReg)
442         .addImm(i)
443         .addReg(TmpReg, getKillRegState(true))
444         .addReg(DestHiReg);
445     Offset += 8;
446   }
447   MI.setDesc(get(VE::LDrii));
448   MI.getOperand(0).ChangeToRegister(TmpReg, true);
449   BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)
450       .addImm(3)
451       .addReg(TmpReg, getKillRegState(true))
452       .addReg(DestHiReg);
453   replaceFI(MI, FrameReg, Offset, FIOperandNum);
454 }
455 
456 void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
457                                     int64_t Offset, int FIOperandNum) {
458   switch (MI.getOpcode()) {
459   case VE::STQrii:
460     processSTQ(MI, FrameReg, Offset, FIOperandNum);
461     return;
462   case VE::LDQrii:
463     processLDQ(MI, FrameReg, Offset, FIOperandNum);
464     return;
465   case VE::STVMrii:
466     processSTVM(MI, FrameReg, Offset, FIOperandNum);
467     return;
468   case VE::LDVMrii:
469     processLDVM(MI, FrameReg, Offset, FIOperandNum);
470     return;
471   case VE::STVM512rii:
472     processSTVM512(MI, FrameReg, Offset, FIOperandNum);
473     return;
474   case VE::LDVM512rii:
475     processLDVM512(MI, FrameReg, Offset, FIOperandNum);
476     return;
477   }
478   prepareReplaceFI(MI, FrameReg, Offset);
479   replaceFI(MI, FrameReg, Offset, FIOperandNum);
480 }
481 
482 bool VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
483                                          int SPAdj, unsigned FIOperandNum,
484                                          RegScavenger *RS) const {
485   assert(SPAdj == 0 && "Unexpected");
486 
487   MachineInstr &MI = *II;
488   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
489 
490   MachineFunction &MF = *MI.getParent()->getParent();
491   const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
492   const VEFrameLowering &TFI = *getFrameLowering(MF);
493   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
494   const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
495   DebugLoc DL = MI.getDebugLoc();
496   EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
497 
498   // Retrieve FrameReg and byte offset for stack slot.
499   Register FrameReg;
500   int64_t Offset =
501       TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
502   Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
503 
504   EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
505   return false;
506 }
507 
508 Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
509   return VE::SX9;
510 }
511