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 bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
100   switch (PhysReg) {
101   case VE::VM0:
102   case VE::VMP0:
103     return true;
104   default:
105     return false;
106   }
107 }
108 
109 const TargetRegisterClass *
110 VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
111                                    unsigned Kind) const {
112   return &VE::I64RegClass;
113 }
114 
115 static unsigned offsetToDisp(MachineInstr &MI) {
116   // Default offset in instruction's operands (reg+reg+imm).
117   unsigned OffDisp = 2;
118 
119 #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
120 
121   {
122     using namespace llvm::VE;
123     switch (MI.getOpcode()) {
124     case RRCAS_multi_cases(TS1AML):
125     case RRCAS_multi_cases(TS1AMW):
126     case RRCAS_multi_cases(CASL):
127     case RRCAS_multi_cases(CASW):
128       // These instructions use AS format (reg+imm).
129       OffDisp = 1;
130       break;
131     }
132   }
133 #undef RRCAS_multi_cases
134 
135   return OffDisp;
136 }
137 
138 class EliminateFrameIndex {
139   const TargetInstrInfo &TII;
140   const TargetRegisterInfo &TRI;
141   const DebugLoc &DL;
142   MachineBasicBlock &MBB;
143   MachineBasicBlock::iterator II;
144   Register clobber;
145 
146   // Some helper functions for the ease of instruction building.
147   MachineFunction &getFunc() const { return *MBB.getParent(); }
148   inline MCRegister getSubReg(MCRegister Reg, unsigned Idx) const {
149     return TRI.getSubReg(Reg, Idx);
150   }
151   inline const MCInstrDesc &get(unsigned Opcode) const {
152     return TII.get(Opcode);
153   }
154   inline MachineInstrBuilder build(const MCInstrDesc &MCID, Register DestReg) {
155     return BuildMI(MBB, II, DL, MCID, DestReg);
156   }
157   inline MachineInstrBuilder build(unsigned InstOpc, Register DestReg) {
158     return build(get(InstOpc), DestReg);
159   }
160   inline MachineInstrBuilder build(const MCInstrDesc &MCID) {
161     return BuildMI(MBB, II, DL, MCID);
162   }
163   inline MachineInstrBuilder build(unsigned InstOpc) {
164     return build(get(InstOpc));
165   }
166 
167   // Calculate an address of frame index from a frame register and a given
168   // offset if the offset doesn't fit in the immediate field.  Use a clobber
169   // register to hold calculated address.
170   void prepareReplaceFI(MachineInstr &MI, Register &FrameReg, int64_t &Offset,
171                         int64_t Bytes = 0);
172   // Replace the frame index in \p MI with a frame register and a given offset
173   // if it fits in the immediate field.  Otherwise, use pre-calculated address
174   // in a clobber regsiter.
175   void replaceFI(MachineInstr &MI, Register FrameReg, int64_t Offset,
176                  int FIOperandNum);
177 
178   // Expand and eliminate Frame Index of pseudo STQrii and LDQrii.
179   void processSTQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
180                   int FIOperandNum);
181   void processLDQ(MachineInstr &MI, Register FrameReg, int64_t Offset,
182                   int FIOperandNum);
183   // Expand and eliminate Frame Index of pseudo STVMrii and LDVMrii.
184   void processSTVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
185                    int FIOperandNum);
186   void processLDVM(MachineInstr &MI, Register FrameReg, int64_t Offset,
187                    int FIOperandNum);
188   // Expand and eliminate Frame Index of pseudo STVM512rii and LDVM512rii.
189   void processSTVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
190                       int FIOperandNum);
191   void processLDVM512(MachineInstr &MI, Register FrameReg, int64_t Offset,
192                       int FIOperandNum);
193 
194 public:
195   EliminateFrameIndex(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,
196                       const DebugLoc &DL, MachineBasicBlock &MBB,
197                       MachineBasicBlock::iterator II)
198       : TII(TII), TRI(TRI), DL(DL), MBB(MBB), II(II), clobber(VE::SX13) {}
199 
200   // Expand and eliminate Frame Index from MI
201   void processMI(MachineInstr &MI, Register FrameReg, int64_t Offset,
202                  int FIOperandNum);
203 };
204 
205 // Prepare the frame index if it doesn't fit in the immediate field.  Use
206 // clobber register to hold calculated address.
207 void EliminateFrameIndex::prepareReplaceFI(MachineInstr &MI, Register &FrameReg,
208                                            int64_t &Offset, int64_t Bytes) {
209   if (isInt<32>(Offset) && isInt<32>(Offset + Bytes)) {
210     // If the offset is small enough to fit in the immediate field, directly
211     // encode it.  So, nothing to prepare here.
212     return;
213   }
214 
215   // If the offset doesn't fit, emit following codes.  This clobbers SX13
216   // which we always know is available here.
217   //   lea     %clobber, Offset@lo
218   //   and     %clobber, %clobber, (32)0
219   //   lea.sl  %clobber, Offset@hi(FrameReg, %clobber)
220   build(VE::LEAzii, clobber).addImm(0).addImm(0).addImm(Lo_32(Offset));
221   build(VE::ANDrm, clobber).addReg(clobber).addImm(M0(32));
222   build(VE::LEASLrri, clobber)
223       .addReg(clobber)
224       .addReg(FrameReg)
225       .addImm(Hi_32(Offset));
226 
227   // Use clobber register as a frame register and 0 offset
228   FrameReg = clobber;
229   Offset = 0;
230 }
231 
232 // Replace the frame index in \p MI with a proper byte and framereg offset.
233 void EliminateFrameIndex::replaceFI(MachineInstr &MI, Register FrameReg,
234                                     int64_t Offset, int FIOperandNum) {
235   assert(isInt<32>(Offset));
236 
237   // The offset must be small enough to fit in the immediate field after
238   // call of prepareReplaceFI.  Therefore, we directly encode it.
239   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
240   MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
241 }
242 
243 void EliminateFrameIndex::processSTQ(MachineInstr &MI, Register FrameReg,
244                                      int64_t Offset, int FIOperandNum) {
245   assert(MI.getOpcode() == VE::STQrii);
246   LLVM_DEBUG(dbgs() << "processSTQ: "; MI.dump());
247 
248   prepareReplaceFI(MI, FrameReg, Offset, 8);
249 
250   Register SrcReg = MI.getOperand(3).getReg();
251   Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
252   Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
253   // VE stores HiReg to 8(addr) and LoReg to 0(addr)
254   MachineInstr *StMI =
255       build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(SrcLoReg);
256   replaceFI(*StMI, FrameReg, Offset, 0);
257   // Mutate to 'hi' store.
258   MI.setDesc(get(VE::STrii));
259   MI.getOperand(3).setReg(SrcHiReg);
260   Offset += 8;
261   replaceFI(MI, FrameReg, Offset, FIOperandNum);
262 }
263 
264 void EliminateFrameIndex::processLDQ(MachineInstr &MI, Register FrameReg,
265                                      int64_t Offset, int FIOperandNum) {
266   assert(MI.getOpcode() == VE::LDQrii);
267   LLVM_DEBUG(dbgs() << "processLDQ: "; MI.dump());
268 
269   prepareReplaceFI(MI, FrameReg, Offset, 8);
270 
271   Register DestReg = MI.getOperand(0).getReg();
272   Register DestHiReg = getSubReg(DestReg, VE::sub_even);
273   Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
274   // VE loads HiReg from 8(addr) and LoReg from 0(addr)
275   MachineInstr *StMI =
276       build(VE::LDrii, DestLoReg).addReg(FrameReg).addImm(0).addImm(0);
277   replaceFI(*StMI, FrameReg, Offset, 1);
278   MI.setDesc(get(VE::LDrii));
279   MI.getOperand(0).setReg(DestHiReg);
280   Offset += 8;
281   replaceFI(MI, FrameReg, Offset, FIOperandNum);
282 }
283 
284 void EliminateFrameIndex::processSTVM(MachineInstr &MI, Register FrameReg,
285                                       int64_t Offset, int FIOperandNum) {
286   assert(MI.getOpcode() == VE::STVMrii);
287   LLVM_DEBUG(dbgs() << "processSTVM: "; MI.dump());
288 
289   // Original MI is:
290   //   STVMrii frame-index, 0, offset, reg (, memory operand)
291   // Convert it to:
292   //   SVMi   tmp-reg, reg, 0
293   //   STrii  frame-reg, 0, offset, tmp-reg
294   //   SVMi   tmp-reg, reg, 1
295   //   STrii  frame-reg, 0, offset+8, tmp-reg
296   //   SVMi   tmp-reg, reg, 2
297   //   STrii  frame-reg, 0, offset+16, tmp-reg
298   //   SVMi   tmp-reg, reg, 3
299   //   STrii  frame-reg, 0, offset+24, tmp-reg
300 
301   prepareReplaceFI(MI, FrameReg, Offset, 24);
302 
303   Register SrcReg = MI.getOperand(3).getReg();
304   bool isKill = MI.getOperand(3).isKill();
305   // FIXME: it would be better to scavenge a register here instead of
306   // reserving SX16 all of the time.
307   Register TmpReg = VE::SX16;
308   for (int i = 0; i < 3; ++i) {
309     build(VE::SVMmr, TmpReg).addReg(SrcReg).addImm(i);
310     MachineInstr *StMI =
311         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
312             TmpReg, getKillRegState(true));
313     replaceFI(*StMI, FrameReg, Offset, 0);
314     Offset += 8;
315   }
316   build(VE::SVMmr, TmpReg).addReg(SrcReg, getKillRegState(isKill)).addImm(3);
317   MI.setDesc(get(VE::STrii));
318   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
319   replaceFI(MI, FrameReg, Offset, FIOperandNum);
320 }
321 
322 void EliminateFrameIndex::processLDVM(MachineInstr &MI, Register FrameReg,
323                                       int64_t Offset, int FIOperandNum) {
324   assert(MI.getOpcode() == VE::LDVMrii);
325   LLVM_DEBUG(dbgs() << "processLDVM: "; MI.dump());
326 
327   // Original MI is:
328   //   LDVMri reg, frame-index, 0, offset (, memory operand)
329   // Convert it to:
330   //   LDrii  tmp-reg, frame-reg, 0, offset
331   //   LVMir vm, 0, tmp-reg
332   //   LDrii  tmp-reg, frame-reg, 0, offset+8
333   //   LVMir_m vm, 1, tmp-reg, vm
334   //   LDrii  tmp-reg, frame-reg, 0, offset+16
335   //   LVMir_m vm, 2, tmp-reg, vm
336   //   LDrii  tmp-reg, frame-reg, 0, offset+24
337   //   LVMir_m vm, 3, tmp-reg, vm
338 
339   prepareReplaceFI(MI, FrameReg, Offset, 24);
340 
341   Register DestReg = MI.getOperand(0).getReg();
342   // FIXME: it would be better to scavenge a register here instead of
343   // reserving SX16 all of the time.
344   unsigned TmpReg = VE::SX16;
345   for (int i = 0; i < 4; ++i) {
346     if (i != 3) {
347       MachineInstr *StMI =
348           build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
349       replaceFI(*StMI, FrameReg, Offset, 1);
350       Offset += 8;
351     } else {
352       // Last LDrii replace the target instruction.
353       MI.setDesc(get(VE::LDrii));
354       MI.getOperand(0).ChangeToRegister(TmpReg, true);
355     }
356     // First LVM is LVMir.  Others are LVMir_m.  Last LVM places at the
357     // next of the target instruction.
358     if (i == 0)
359       build(VE::LVMir, DestReg).addImm(i).addReg(TmpReg, getKillRegState(true));
360     else if (i != 3)
361       build(VE::LVMir_m, DestReg)
362           .addImm(i)
363           .addReg(TmpReg, getKillRegState(true))
364           .addReg(DestReg);
365     else
366       BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestReg)
367           .addImm(3)
368           .addReg(TmpReg, getKillRegState(true))
369           .addReg(DestReg);
370   }
371   replaceFI(MI, FrameReg, Offset, FIOperandNum);
372 }
373 
374 void EliminateFrameIndex::processSTVM512(MachineInstr &MI, Register FrameReg,
375                                          int64_t Offset, int FIOperandNum) {
376   assert(MI.getOpcode() == VE::STVM512rii);
377   LLVM_DEBUG(dbgs() << "processSTVM512: "; MI.dump());
378 
379   prepareReplaceFI(MI, FrameReg, Offset, 56);
380 
381   Register SrcReg = MI.getOperand(3).getReg();
382   Register SrcLoReg = getSubReg(SrcReg, VE::sub_vm_odd);
383   Register SrcHiReg = getSubReg(SrcReg, VE::sub_vm_even);
384   bool isKill = MI.getOperand(3).isKill();
385   // FIXME: it would be better to scavenge a register here instead of
386   // reserving SX16 all of the time.
387   Register TmpReg = VE::SX16;
388   // store low part of VMP
389   MachineInstr *LastMI = nullptr;
390   for (int i = 0; i < 4; ++i) {
391     LastMI = build(VE::SVMmr, TmpReg).addReg(SrcLoReg).addImm(i);
392     MachineInstr *StMI =
393         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
394             TmpReg, getKillRegState(true));
395     replaceFI(*StMI, FrameReg, Offset, 0);
396     Offset += 8;
397   }
398   if (isKill)
399     LastMI->addRegisterKilled(SrcLoReg, &TRI, true);
400   // store high part of VMP
401   for (int i = 0; i < 3; ++i) {
402     build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(i);
403     MachineInstr *StMI =
404         build(VE::STrii).addReg(FrameReg).addImm(0).addImm(0).addReg(
405             TmpReg, getKillRegState(true));
406     replaceFI(*StMI, FrameReg, Offset, 0);
407     Offset += 8;
408   }
409   LastMI = build(VE::SVMmr, TmpReg).addReg(SrcHiReg).addImm(3);
410   if (isKill) {
411     LastMI->addRegisterKilled(SrcHiReg, &TRI, true);
412     // Add implicit super-register kills to the particular MI.
413     LastMI->addRegisterKilled(SrcReg, &TRI, true);
414   }
415   MI.setDesc(get(VE::STrii));
416   MI.getOperand(3).ChangeToRegister(TmpReg, false, false, true);
417   replaceFI(MI, FrameReg, Offset, FIOperandNum);
418 }
419 
420 void EliminateFrameIndex::processLDVM512(MachineInstr &MI, Register FrameReg,
421                                          int64_t Offset, int FIOperandNum) {
422   assert(MI.getOpcode() == VE::LDVM512rii);
423   LLVM_DEBUG(dbgs() << "processLDVM512: "; MI.dump());
424 
425   prepareReplaceFI(MI, FrameReg, Offset, 56);
426 
427   Register DestReg = MI.getOperand(0).getReg();
428   Register DestLoReg = getSubReg(DestReg, VE::sub_vm_odd);
429   Register DestHiReg = getSubReg(DestReg, VE::sub_vm_even);
430   // FIXME: it would be better to scavenge a register here instead of
431   // reserving SX16 all of the time.
432   Register TmpReg = VE::SX16;
433   build(VE::IMPLICIT_DEF, DestReg);
434   for (int i = 0; i < 4; ++i) {
435     MachineInstr *LdMI =
436         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
437     replaceFI(*LdMI, FrameReg, Offset, 1);
438     build(VE::LVMir_m, DestLoReg)
439         .addImm(i)
440         .addReg(TmpReg, getKillRegState(true))
441         .addReg(DestLoReg);
442     Offset += 8;
443   }
444   for (int i = 0; i < 3; ++i) {
445     MachineInstr *LdMI =
446         build(VE::LDrii, TmpReg).addReg(FrameReg).addImm(0).addImm(0);
447     replaceFI(*LdMI, FrameReg, Offset, 1);
448     build(VE::LVMir_m, DestHiReg)
449         .addImm(i)
450         .addReg(TmpReg, getKillRegState(true))
451         .addReg(DestHiReg);
452     Offset += 8;
453   }
454   MI.setDesc(get(VE::LDrii));
455   MI.getOperand(0).ChangeToRegister(TmpReg, true);
456   BuildMI(*MI.getParent(), std::next(II), DL, get(VE::LVMir_m), DestHiReg)
457       .addImm(3)
458       .addReg(TmpReg, getKillRegState(true))
459       .addReg(DestHiReg);
460   replaceFI(MI, FrameReg, Offset, FIOperandNum);
461 }
462 
463 void EliminateFrameIndex::processMI(MachineInstr &MI, Register FrameReg,
464                                     int64_t Offset, int FIOperandNum) {
465   switch (MI.getOpcode()) {
466   case VE::STQrii:
467     processSTQ(MI, FrameReg, Offset, FIOperandNum);
468     return;
469   case VE::LDQrii:
470     processLDQ(MI, FrameReg, Offset, FIOperandNum);
471     return;
472   case VE::STVMrii:
473     processSTVM(MI, FrameReg, Offset, FIOperandNum);
474     return;
475   case VE::LDVMrii:
476     processLDVM(MI, FrameReg, Offset, FIOperandNum);
477     return;
478   case VE::STVM512rii:
479     processSTVM512(MI, FrameReg, Offset, FIOperandNum);
480     return;
481   case VE::LDVM512rii:
482     processLDVM512(MI, FrameReg, Offset, FIOperandNum);
483     return;
484   }
485   prepareReplaceFI(MI, FrameReg, Offset);
486   replaceFI(MI, FrameReg, Offset, FIOperandNum);
487 }
488 
489 void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
490                                          int SPAdj, unsigned FIOperandNum,
491                                          RegScavenger *RS) const {
492   assert(SPAdj == 0 && "Unexpected");
493 
494   MachineInstr &MI = *II;
495   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
496 
497   MachineFunction &MF = *MI.getParent()->getParent();
498   const VESubtarget &Subtarget = MF.getSubtarget<VESubtarget>();
499   const VEFrameLowering &TFI = *getFrameLowering(MF);
500   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
501   const VERegisterInfo &TRI = *Subtarget.getRegisterInfo();
502   DebugLoc DL = MI.getDebugLoc();
503   EliminateFrameIndex EFI(TII, TRI, DL, *MI.getParent(), II);
504 
505   // Retrieve FrameReg and byte offset for stack slot.
506   Register FrameReg;
507   int64_t Offset =
508       TFI.getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
509   Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
510 
511   EFI.processMI(MI, FrameReg, Offset, FIOperandNum);
512 }
513 
514 Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
515   return VE::SX9;
516 }
517