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 GET_REGINFO_TARGET_DESC
31 #include "VEGenRegisterInfo.inc"
32 
33 // VE uses %s10 == %lp to keep return address
VERegisterInfo()34 VERegisterInfo::VERegisterInfo() : VEGenRegisterInfo(VE::SX10) {}
35 
36 const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const37 VERegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
38   switch (MF->getFunction().getCallingConv()) {
39   case CallingConv::Fast:
40     // Being explicit (same as standard CC).
41   default:
42     return CSR_SaveList;
43   case CallingConv::PreserveAll:
44     return CSR_preserve_all_SaveList;
45   }
46 }
47 
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const48 const uint32_t *VERegisterInfo::getCallPreservedMask(const MachineFunction &MF,
49                                                      CallingConv::ID CC) const {
50   switch (CC) {
51   case CallingConv::Fast:
52     // Being explicit (same as standard CC).
53   default:
54     return CSR_RegMask;
55   case CallingConv::PreserveAll:
56     return CSR_preserve_all_RegMask;
57   }
58 }
59 
getNoPreservedMask() const60 const uint32_t *VERegisterInfo::getNoPreservedMask() const {
61   return CSR_NoRegs_RegMask;
62 }
63 
getReservedRegs(const MachineFunction & MF) const64 BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
65   BitVector Reserved(getNumRegs());
66 
67   const Register ReservedRegs[] = {
68       VE::SX8,  // Stack limit
69       VE::SX9,  // Frame pointer
70       VE::SX10, // Link register (return address)
71       VE::SX11, // Stack pointer
72 
73       // FIXME: maybe not need to be reserved
74       VE::SX12, // Outer register
75       VE::SX13, // Id register for dynamic linker
76 
77       VE::SX14, // Thread pointer
78       VE::SX15, // Global offset table register
79       VE::SX16, // Procedure linkage table register
80       VE::SX17, // Linkage-area register
81                 // sx18-sx33 are callee-saved registers
82                 // sx34-sx63 are temporary registers
83   };
84 
85   for (auto R : ReservedRegs)
86     for (MCRegAliasIterator ItAlias(R, this, true); ItAlias.isValid();
87          ++ItAlias)
88       Reserved.set(*ItAlias);
89 
90   // Reserve constant registers.
91   Reserved.set(VE::VM0);
92   Reserved.set(VE::VMP0);
93 
94   return Reserved;
95 }
96 
isConstantPhysReg(MCRegister PhysReg) const97 bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
98   switch (PhysReg) {
99   case VE::VM0:
100   case VE::VMP0:
101     return true;
102   default:
103     return false;
104   }
105 }
106 
107 const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const108 VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
109                                    unsigned Kind) const {
110   return &VE::I64RegClass;
111 }
112 
offsetToDisp(MachineInstr & MI)113 static unsigned offsetToDisp(MachineInstr &MI) {
114   // Default offset in instruction's operands (reg+reg+imm).
115   unsigned OffDisp = 2;
116 
117 #define RRCAS_multi_cases(NAME) NAME##rir : case NAME##rii
118 
119   {
120     using namespace llvm::VE;
121     switch (MI.getOpcode()) {
122     case RRCAS_multi_cases(TS1AML):
123     case RRCAS_multi_cases(TS1AMW):
124     case RRCAS_multi_cases(CASL):
125     case RRCAS_multi_cases(CASW):
126       // These instructions use AS format (reg+imm).
127       OffDisp = 1;
128       break;
129     }
130   }
131 #undef RRCAS_multi_cases
132 
133   return OffDisp;
134 }
135 
replaceFI(MachineFunction & MF,MachineBasicBlock::iterator II,MachineInstr & MI,const DebugLoc & dl,unsigned FIOperandNum,int Offset,Register FrameReg)136 static void replaceFI(MachineFunction &MF, MachineBasicBlock::iterator II,
137                       MachineInstr &MI, const DebugLoc &dl,
138                       unsigned FIOperandNum, int Offset, Register FrameReg) {
139   // Replace frame index with a frame pointer reference directly.
140   // VE has 32 bit offset field, so no need to expand a target instruction.
141   // Directly encode it.
142   MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
143   MI.getOperand(FIOperandNum + offsetToDisp(MI)).ChangeToImmediate(Offset);
144 }
145 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const146 void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
147                                          int SPAdj, unsigned FIOperandNum,
148                                          RegScavenger *RS) const {
149   assert(SPAdj == 0 && "Unexpected");
150 
151   MachineInstr &MI = *II;
152   DebugLoc dl = MI.getDebugLoc();
153   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
154   MachineFunction &MF = *MI.getParent()->getParent();
155   const VEFrameLowering *TFI = getFrameLowering(MF);
156 
157   Register FrameReg;
158   int Offset;
159   Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg).getFixed();
160 
161   Offset += MI.getOperand(FIOperandNum + offsetToDisp(MI)).getImm();
162 
163   if (MI.getOpcode() == VE::STQrii) {
164     const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
165     Register SrcReg = MI.getOperand(3).getReg();
166     Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
167     Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
168     // VE stores HiReg to 8(addr) and LoReg to 0(addr)
169     MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(VE::STrii))
170                              .addReg(FrameReg)
171                              .addImm(0)
172                              .addImm(0)
173                              .addReg(SrcLoReg);
174     replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg);
175     MI.setDesc(TII.get(VE::STrii));
176     MI.getOperand(3).setReg(SrcHiReg);
177     Offset += 8;
178   } else if (MI.getOpcode() == VE::LDQrii) {
179     const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
180     Register DestReg = MI.getOperand(0).getReg();
181     Register DestHiReg = getSubReg(DestReg, VE::sub_even);
182     Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
183     // VE loads HiReg from 8(addr) and LoReg from 0(addr)
184     MachineInstr *StMI =
185         BuildMI(*MI.getParent(), II, dl, TII.get(VE::LDrii), DestLoReg)
186             .addReg(FrameReg)
187             .addImm(0)
188             .addImm(0);
189     replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg);
190     MI.setDesc(TII.get(VE::LDrii));
191     MI.getOperand(0).setReg(DestHiReg);
192     Offset += 8;
193   }
194 
195   replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);
196 }
197 
getFrameRegister(const MachineFunction & MF) const198 Register VERegisterInfo::getFrameRegister(const MachineFunction &MF) const {
199   return VE::SX9;
200 }
201