]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- MipsSEInstrInfo.cpp - Mips32/64 Instruction Information -----------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file contains the Mips32/64 implementation of the TargetInstrInfo class. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
14 | #include "MipsSEInstrInfo.h" | |
223e47cc | 15 | #include "InstPrinter/MipsInstPrinter.h" |
970d7e83 LB |
16 | #include "MipsMachineFunction.h" |
17 | #include "MipsTargetMachine.h" | |
18 | #include "llvm/ADT/STLExtras.h" | |
223e47cc LB |
19 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
20 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |
1a4d82fc | 21 | #include "llvm/Support/CommandLine.h" |
223e47cc LB |
22 | #include "llvm/Support/ErrorHandling.h" |
23 | #include "llvm/Support/TargetRegistry.h" | |
223e47cc LB |
24 | |
25 | using namespace llvm; | |
26 | ||
1a4d82fc JJ |
27 | MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) |
28 | : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B | |
29 | : Mips::J), | |
85aaf69f | 30 | RI(STI) {} |
223e47cc LB |
31 | |
32 | const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { | |
33 | return RI; | |
34 | } | |
35 | ||
36 | /// isLoadFromStackSlot - If the specified machine instruction is a direct | |
37 | /// load from a stack slot, return the virtual or physical register number of | |
38 | /// the destination along with the FrameIndex of the loaded stack slot. If | |
39 | /// not, return 0. This predicate must return 0 if the instruction has | |
40 | /// any side effects other than loading from the stack slot. | |
85aaf69f SL |
41 | unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, |
42 | int &FrameIndex) const { | |
223e47cc LB |
43 | unsigned Opc = MI->getOpcode(); |
44 | ||
1a4d82fc JJ |
45 | if ((Opc == Mips::LW) || (Opc == Mips::LD) || |
46 | (Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) { | |
223e47cc LB |
47 | if ((MI->getOperand(1).isFI()) && // is a stack slot |
48 | (MI->getOperand(2).isImm()) && // the imm is zero | |
49 | (isZeroImm(MI->getOperand(2)))) { | |
50 | FrameIndex = MI->getOperand(1).getIndex(); | |
51 | return MI->getOperand(0).getReg(); | |
52 | } | |
53 | } | |
54 | ||
55 | return 0; | |
56 | } | |
57 | ||
58 | /// isStoreToStackSlot - If the specified machine instruction is a direct | |
59 | /// store to a stack slot, return the virtual or physical register number of | |
60 | /// the source reg along with the FrameIndex of the loaded stack slot. If | |
61 | /// not, return 0. This predicate must return 0 if the instruction has | |
62 | /// any side effects other than storing to the stack slot. | |
85aaf69f SL |
63 | unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr *MI, |
64 | int &FrameIndex) const { | |
223e47cc LB |
65 | unsigned Opc = MI->getOpcode(); |
66 | ||
1a4d82fc JJ |
67 | if ((Opc == Mips::SW) || (Opc == Mips::SD) || |
68 | (Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) { | |
223e47cc LB |
69 | if ((MI->getOperand(1).isFI()) && // is a stack slot |
70 | (MI->getOperand(2).isImm()) && // the imm is zero | |
71 | (isZeroImm(MI->getOperand(2)))) { | |
72 | FrameIndex = MI->getOperand(1).getIndex(); | |
73 | return MI->getOperand(0).getReg(); | |
74 | } | |
75 | } | |
76 | return 0; | |
77 | } | |
78 | ||
79 | void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, | |
80 | MachineBasicBlock::iterator I, DebugLoc DL, | |
81 | unsigned DestReg, unsigned SrcReg, | |
82 | bool KillSrc) const { | |
83 | unsigned Opc = 0, ZeroReg = 0; | |
1a4d82fc JJ |
84 | bool isMicroMips = Subtarget.inMicroMipsMode(); |
85 | ||
86 | if (Mips::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg. | |
87 | if (Mips::GPR32RegClass.contains(SrcReg)) { | |
88 | if (isMicroMips) | |
89 | Opc = Mips::MOVE16_MM; | |
90 | else | |
91 | Opc = Mips::ADDu, ZeroReg = Mips::ZERO; | |
92 | } else if (Mips::CCRRegClass.contains(SrcReg)) | |
223e47cc LB |
93 | Opc = Mips::CFC1; |
94 | else if (Mips::FGR32RegClass.contains(SrcReg)) | |
95 | Opc = Mips::MFC1; | |
1a4d82fc JJ |
96 | else if (Mips::HI32RegClass.contains(SrcReg)) { |
97 | Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI; | |
98 | SrcReg = 0; | |
99 | } else if (Mips::LO32RegClass.contains(SrcReg)) { | |
100 | Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO; | |
101 | SrcReg = 0; | |
102 | } else if (Mips::HI32DSPRegClass.contains(SrcReg)) | |
103 | Opc = Mips::MFHI_DSP; | |
104 | else if (Mips::LO32DSPRegClass.contains(SrcReg)) | |
105 | Opc = Mips::MFLO_DSP; | |
106 | else if (Mips::DSPCCRegClass.contains(SrcReg)) { | |
107 | BuildMI(MBB, I, DL, get(Mips::RDDSP), DestReg).addImm(1 << 4) | |
108 | .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc)); | |
109 | return; | |
110 | } | |
111 | else if (Mips::MSACtrlRegClass.contains(SrcReg)) | |
112 | Opc = Mips::CFCMSA; | |
223e47cc | 113 | } |
1a4d82fc | 114 | else if (Mips::GPR32RegClass.contains(SrcReg)) { // Copy from CPU Reg. |
223e47cc LB |
115 | if (Mips::CCRRegClass.contains(DestReg)) |
116 | Opc = Mips::CTC1; | |
117 | else if (Mips::FGR32RegClass.contains(DestReg)) | |
118 | Opc = Mips::MTC1; | |
1a4d82fc | 119 | else if (Mips::HI32RegClass.contains(DestReg)) |
223e47cc | 120 | Opc = Mips::MTHI, DestReg = 0; |
1a4d82fc | 121 | else if (Mips::LO32RegClass.contains(DestReg)) |
223e47cc | 122 | Opc = Mips::MTLO, DestReg = 0; |
1a4d82fc JJ |
123 | else if (Mips::HI32DSPRegClass.contains(DestReg)) |
124 | Opc = Mips::MTHI_DSP; | |
125 | else if (Mips::LO32DSPRegClass.contains(DestReg)) | |
126 | Opc = Mips::MTLO_DSP; | |
127 | else if (Mips::DSPCCRegClass.contains(DestReg)) { | |
128 | BuildMI(MBB, I, DL, get(Mips::WRDSP)) | |
129 | .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4) | |
130 | .addReg(DestReg, RegState::ImplicitDefine); | |
131 | return; | |
132 | } | |
133 | else if (Mips::MSACtrlRegClass.contains(DestReg)) | |
134 | Opc = Mips::CTCMSA; | |
223e47cc LB |
135 | } |
136 | else if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) | |
137 | Opc = Mips::FMOV_S; | |
138 | else if (Mips::AFGR64RegClass.contains(DestReg, SrcReg)) | |
139 | Opc = Mips::FMOV_D32; | |
140 | else if (Mips::FGR64RegClass.contains(DestReg, SrcReg)) | |
141 | Opc = Mips::FMOV_D64; | |
1a4d82fc JJ |
142 | else if (Mips::GPR64RegClass.contains(DestReg)) { // Copy to CPU64 Reg. |
143 | if (Mips::GPR64RegClass.contains(SrcReg)) | |
144 | Opc = Mips::DADDu, ZeroReg = Mips::ZERO_64; | |
145 | else if (Mips::HI64RegClass.contains(SrcReg)) | |
223e47cc | 146 | Opc = Mips::MFHI64, SrcReg = 0; |
1a4d82fc | 147 | else if (Mips::LO64RegClass.contains(SrcReg)) |
223e47cc LB |
148 | Opc = Mips::MFLO64, SrcReg = 0; |
149 | else if (Mips::FGR64RegClass.contains(SrcReg)) | |
150 | Opc = Mips::DMFC1; | |
151 | } | |
1a4d82fc JJ |
152 | else if (Mips::GPR64RegClass.contains(SrcReg)) { // Copy from CPU64 Reg. |
153 | if (Mips::HI64RegClass.contains(DestReg)) | |
223e47cc | 154 | Opc = Mips::MTHI64, DestReg = 0; |
1a4d82fc | 155 | else if (Mips::LO64RegClass.contains(DestReg)) |
223e47cc LB |
156 | Opc = Mips::MTLO64, DestReg = 0; |
157 | else if (Mips::FGR64RegClass.contains(DestReg)) | |
158 | Opc = Mips::DMTC1; | |
159 | } | |
1a4d82fc JJ |
160 | else if (Mips::MSA128BRegClass.contains(DestReg)) { // Copy to MSA reg |
161 | if (Mips::MSA128BRegClass.contains(SrcReg)) | |
162 | Opc = Mips::MOVE_V; | |
163 | } | |
223e47cc LB |
164 | |
165 | assert(Opc && "Cannot copy registers"); | |
166 | ||
167 | MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc)); | |
168 | ||
169 | if (DestReg) | |
170 | MIB.addReg(DestReg, RegState::Define); | |
171 | ||
223e47cc LB |
172 | if (SrcReg) |
173 | MIB.addReg(SrcReg, getKillRegState(KillSrc)); | |
970d7e83 LB |
174 | |
175 | if (ZeroReg) | |
176 | MIB.addReg(ZeroReg); | |
223e47cc LB |
177 | } |
178 | ||
179 | void MipsSEInstrInfo:: | |
1a4d82fc JJ |
180 | storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
181 | unsigned SrcReg, bool isKill, int FI, | |
182 | const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, | |
183 | int64_t Offset) const { | |
223e47cc LB |
184 | DebugLoc DL; |
185 | if (I != MBB.end()) DL = I->getDebugLoc(); | |
186 | MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore); | |
187 | ||
188 | unsigned Opc = 0; | |
189 | ||
1a4d82fc JJ |
190 | if (Mips::GPR32RegClass.hasSubClassEq(RC)) |
191 | Opc = Mips::SW; | |
192 | else if (Mips::GPR64RegClass.hasSubClassEq(RC)) | |
193 | Opc = Mips::SD; | |
194 | else if (Mips::ACC64RegClass.hasSubClassEq(RC)) | |
195 | Opc = Mips::STORE_ACC64; | |
196 | else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC)) | |
197 | Opc = Mips::STORE_ACC64DSP; | |
198 | else if (Mips::ACC128RegClass.hasSubClassEq(RC)) | |
199 | Opc = Mips::STORE_ACC128; | |
200 | else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) | |
201 | Opc = Mips::STORE_CCOND_DSP; | |
223e47cc | 202 | else if (Mips::FGR32RegClass.hasSubClassEq(RC)) |
1a4d82fc | 203 | Opc = Mips::SWC1; |
223e47cc LB |
204 | else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) |
205 | Opc = Mips::SDC1; | |
206 | else if (Mips::FGR64RegClass.hasSubClassEq(RC)) | |
1a4d82fc JJ |
207 | Opc = Mips::SDC164; |
208 | else if (RC->hasType(MVT::v16i8)) | |
209 | Opc = Mips::ST_B; | |
210 | else if (RC->hasType(MVT::v8i16) || RC->hasType(MVT::v8f16)) | |
211 | Opc = Mips::ST_H; | |
212 | else if (RC->hasType(MVT::v4i32) || RC->hasType(MVT::v4f32)) | |
213 | Opc = Mips::ST_W; | |
214 | else if (RC->hasType(MVT::v2i64) || RC->hasType(MVT::v2f64)) | |
215 | Opc = Mips::ST_D; | |
223e47cc LB |
216 | |
217 | assert(Opc && "Register class not handled!"); | |
218 | BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill)) | |
1a4d82fc | 219 | .addFrameIndex(FI).addImm(Offset).addMemOperand(MMO); |
223e47cc LB |
220 | } |
221 | ||
222 | void MipsSEInstrInfo:: | |
1a4d82fc JJ |
223 | loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, |
224 | unsigned DestReg, int FI, const TargetRegisterClass *RC, | |
225 | const TargetRegisterInfo *TRI, int64_t Offset) const { | |
223e47cc LB |
226 | DebugLoc DL; |
227 | if (I != MBB.end()) DL = I->getDebugLoc(); | |
228 | MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad); | |
229 | unsigned Opc = 0; | |
230 | ||
1a4d82fc JJ |
231 | if (Mips::GPR32RegClass.hasSubClassEq(RC)) |
232 | Opc = Mips::LW; | |
233 | else if (Mips::GPR64RegClass.hasSubClassEq(RC)) | |
234 | Opc = Mips::LD; | |
235 | else if (Mips::ACC64RegClass.hasSubClassEq(RC)) | |
236 | Opc = Mips::LOAD_ACC64; | |
237 | else if (Mips::ACC64DSPRegClass.hasSubClassEq(RC)) | |
238 | Opc = Mips::LOAD_ACC64DSP; | |
239 | else if (Mips::ACC128RegClass.hasSubClassEq(RC)) | |
240 | Opc = Mips::LOAD_ACC128; | |
241 | else if (Mips::DSPCCRegClass.hasSubClassEq(RC)) | |
242 | Opc = Mips::LOAD_CCOND_DSP; | |
223e47cc | 243 | else if (Mips::FGR32RegClass.hasSubClassEq(RC)) |
1a4d82fc | 244 | Opc = Mips::LWC1; |
223e47cc LB |
245 | else if (Mips::AFGR64RegClass.hasSubClassEq(RC)) |
246 | Opc = Mips::LDC1; | |
247 | else if (Mips::FGR64RegClass.hasSubClassEq(RC)) | |
1a4d82fc JJ |
248 | Opc = Mips::LDC164; |
249 | else if (RC->hasType(MVT::v16i8)) | |
250 | Opc = Mips::LD_B; | |
251 | else if (RC->hasType(MVT::v8i16) || RC->hasType(MVT::v8f16)) | |
252 | Opc = Mips::LD_H; | |
253 | else if (RC->hasType(MVT::v4i32) || RC->hasType(MVT::v4f32)) | |
254 | Opc = Mips::LD_W; | |
255 | else if (RC->hasType(MVT::v2i64) || RC->hasType(MVT::v2f64)) | |
256 | Opc = Mips::LD_D; | |
223e47cc LB |
257 | |
258 | assert(Opc && "Register class not handled!"); | |
1a4d82fc | 259 | BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset) |
223e47cc LB |
260 | .addMemOperand(MMO); |
261 | } | |
262 | ||
263 | bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { | |
264 | MachineBasicBlock &MBB = *MI->getParent(); | |
1a4d82fc JJ |
265 | bool isMicroMips = Subtarget.inMicroMipsMode(); |
266 | unsigned Opc; | |
223e47cc LB |
267 | |
268 | switch(MI->getDesc().getOpcode()) { | |
269 | default: | |
270 | return false; | |
271 | case Mips::RetRA: | |
1a4d82fc JJ |
272 | expandRetRA(MBB, MI); |
273 | break; | |
274 | case Mips::PseudoMFHI: | |
275 | Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI; | |
276 | expandPseudoMFHiLo(MBB, MI, Opc); | |
277 | break; | |
278 | case Mips::PseudoMFLO: | |
279 | Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO; | |
280 | expandPseudoMFHiLo(MBB, MI, Opc); | |
281 | break; | |
282 | case Mips::PseudoMFHI64: | |
283 | expandPseudoMFHiLo(MBB, MI, Mips::MFHI64); | |
284 | break; | |
285 | case Mips::PseudoMFLO64: | |
286 | expandPseudoMFHiLo(MBB, MI, Mips::MFLO64); | |
287 | break; | |
288 | case Mips::PseudoMTLOHI: | |
289 | expandPseudoMTLoHi(MBB, MI, Mips::MTLO, Mips::MTHI, false); | |
290 | break; | |
291 | case Mips::PseudoMTLOHI64: | |
292 | expandPseudoMTLoHi(MBB, MI, Mips::MTLO64, Mips::MTHI64, false); | |
293 | break; | |
294 | case Mips::PseudoMTLOHI_DSP: | |
295 | expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true); | |
296 | break; | |
297 | case Mips::PseudoCVT_S_W: | |
298 | expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); | |
299 | break; | |
300 | case Mips::PseudoCVT_D32_W: | |
301 | expandCvtFPInt(MBB, MI, Mips::CVT_D32_W, Mips::MTC1, false); | |
302 | break; | |
303 | case Mips::PseudoCVT_S_L: | |
304 | expandCvtFPInt(MBB, MI, Mips::CVT_S_L, Mips::DMTC1, true); | |
305 | break; | |
306 | case Mips::PseudoCVT_D64_W: | |
307 | expandCvtFPInt(MBB, MI, Mips::CVT_D64_W, Mips::MTC1, true); | |
308 | break; | |
309 | case Mips::PseudoCVT_D64_L: | |
310 | expandCvtFPInt(MBB, MI, Mips::CVT_D64_L, Mips::DMTC1, true); | |
223e47cc LB |
311 | break; |
312 | case Mips::BuildPairF64: | |
1a4d82fc JJ |
313 | expandBuildPairF64(MBB, MI, false); |
314 | break; | |
315 | case Mips::BuildPairF64_64: | |
316 | expandBuildPairF64(MBB, MI, true); | |
223e47cc LB |
317 | break; |
318 | case Mips::ExtractElementF64: | |
1a4d82fc JJ |
319 | expandExtractElementF64(MBB, MI, false); |
320 | break; | |
321 | case Mips::ExtractElementF64_64: | |
322 | expandExtractElementF64(MBB, MI, true); | |
223e47cc | 323 | break; |
970d7e83 LB |
324 | case Mips::MIPSeh_return32: |
325 | case Mips::MIPSeh_return64: | |
1a4d82fc | 326 | expandEhReturn(MBB, MI); |
970d7e83 | 327 | break; |
223e47cc LB |
328 | } |
329 | ||
330 | MBB.erase(MI); | |
331 | return true; | |
332 | } | |
333 | ||
1a4d82fc | 334 | /// getOppositeBranchOpc - Return the inverse of the specified |
223e47cc | 335 | /// opcode, e.g. turning BEQ to BNE. |
1a4d82fc | 336 | unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { |
223e47cc LB |
337 | switch (Opc) { |
338 | default: llvm_unreachable("Illegal opcode!"); | |
339 | case Mips::BEQ: return Mips::BNE; | |
340 | case Mips::BNE: return Mips::BEQ; | |
341 | case Mips::BGTZ: return Mips::BLEZ; | |
342 | case Mips::BGEZ: return Mips::BLTZ; | |
343 | case Mips::BLTZ: return Mips::BGEZ; | |
344 | case Mips::BLEZ: return Mips::BGTZ; | |
345 | case Mips::BEQ64: return Mips::BNE64; | |
346 | case Mips::BNE64: return Mips::BEQ64; | |
347 | case Mips::BGTZ64: return Mips::BLEZ64; | |
348 | case Mips::BGEZ64: return Mips::BLTZ64; | |
349 | case Mips::BLTZ64: return Mips::BGEZ64; | |
350 | case Mips::BLEZ64: return Mips::BGTZ64; | |
351 | case Mips::BC1T: return Mips::BC1F; | |
352 | case Mips::BC1F: return Mips::BC1T; | |
85aaf69f SL |
353 | case Mips::BEQZC_MM: return Mips::BNEZC_MM; |
354 | case Mips::BNEZC_MM: return Mips::BEQZC_MM; | |
223e47cc LB |
355 | } |
356 | } | |
357 | ||
358 | /// Adjust SP by Amount bytes. | |
359 | void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, | |
360 | MachineBasicBlock &MBB, | |
361 | MachineBasicBlock::iterator I) const { | |
1a4d82fc | 362 | const MipsSubtarget &STI = Subtarget; |
223e47cc LB |
363 | DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); |
364 | unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; | |
365 | unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; | |
366 | ||
367 | if (isInt<16>(Amount))// addi sp, sp, amount | |
368 | BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount); | |
369 | else { // Expand immediate that doesn't fit in 16-bit. | |
1a4d82fc | 370 | unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr); |
970d7e83 | 371 | BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill); |
223e47cc LB |
372 | } |
373 | } | |
374 | ||
375 | /// This function generates the sequence of instructions needed to get the | |
376 | /// result of adding register REG and immediate IMM. | |
377 | unsigned | |
378 | MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, | |
379 | MachineBasicBlock::iterator II, DebugLoc DL, | |
380 | unsigned *NewImm) const { | |
381 | MipsAnalyzeImmediate AnalyzeImm; | |
1a4d82fc | 382 | const MipsSubtarget &STI = Subtarget; |
970d7e83 | 383 | MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); |
223e47cc LB |
384 | unsigned Size = STI.isABI_N64() ? 64 : 32; |
385 | unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; | |
386 | unsigned ZEROReg = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; | |
970d7e83 | 387 | const TargetRegisterClass *RC = STI.isABI_N64() ? |
1a4d82fc | 388 | &Mips::GPR64RegClass : &Mips::GPR32RegClass; |
223e47cc LB |
389 | bool LastInstrIsADDiu = NewImm; |
390 | ||
391 | const MipsAnalyzeImmediate::InstSeq &Seq = | |
392 | AnalyzeImm.Analyze(Imm, Size, LastInstrIsADDiu); | |
393 | MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); | |
394 | ||
395 | assert(Seq.size() && (!LastInstrIsADDiu || (Seq.size() > 1))); | |
396 | ||
397 | // The first instruction can be a LUi, which is different from other | |
398 | // instructions (ADDiu, ORI and SLL) in that it does not have a register | |
399 | // operand. | |
970d7e83 LB |
400 | unsigned Reg = RegInfo.createVirtualRegister(RC); |
401 | ||
223e47cc | 402 | if (Inst->Opc == LUi) |
970d7e83 | 403 | BuildMI(MBB, II, DL, get(LUi), Reg).addImm(SignExtend64<16>(Inst->ImmOpnd)); |
223e47cc | 404 | else |
970d7e83 | 405 | BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(ZEROReg) |
223e47cc LB |
406 | .addImm(SignExtend64<16>(Inst->ImmOpnd)); |
407 | ||
408 | // Build the remaining instructions in Seq. | |
409 | for (++Inst; Inst != Seq.end() - LastInstrIsADDiu; ++Inst) | |
970d7e83 | 410 | BuildMI(MBB, II, DL, get(Inst->Opc), Reg).addReg(Reg, RegState::Kill) |
223e47cc LB |
411 | .addImm(SignExtend64<16>(Inst->ImmOpnd)); |
412 | ||
413 | if (LastInstrIsADDiu) | |
414 | *NewImm = Inst->ImmOpnd; | |
415 | ||
970d7e83 | 416 | return Reg; |
223e47cc LB |
417 | } |
418 | ||
1a4d82fc | 419 | unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { |
223e47cc LB |
420 | return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ || |
421 | Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ || | |
422 | Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || | |
423 | Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || | |
424 | Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || | |
85aaf69f | 425 | Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ? |
223e47cc LB |
426 | Opc : 0; |
427 | } | |
428 | ||
1a4d82fc JJ |
429 | void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, |
430 | MachineBasicBlock::iterator I) const { | |
431 | if (Subtarget.isGP64bit()) | |
432 | BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64)) | |
433 | .addReg(Mips::RA_64); | |
434 | else | |
435 | BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)).addReg(Mips::RA); | |
436 | } | |
437 | ||
438 | std::pair<bool, bool> | |
439 | MipsSEInstrInfo::compareOpndSize(unsigned Opc, | |
440 | const MachineFunction &MF) const { | |
441 | const MCInstrDesc &Desc = get(Opc); | |
442 | assert(Desc.NumOperands == 2 && "Unary instruction expected."); | |
443 | const MipsRegisterInfo *RI = &getRegisterInfo(); | |
444 | unsigned DstRegSize = getRegClass(Desc, 0, RI, MF)->getSize(); | |
445 | unsigned SrcRegSize = getRegClass(Desc, 1, RI, MF)->getSize(); | |
446 | ||
447 | return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize); | |
448 | } | |
449 | ||
450 | void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB, | |
451 | MachineBasicBlock::iterator I, | |
452 | unsigned NewOpc) const { | |
453 | BuildMI(MBB, I, I->getDebugLoc(), get(NewOpc), I->getOperand(0).getReg()); | |
454 | } | |
455 | ||
456 | void MipsSEInstrInfo::expandPseudoMTLoHi(MachineBasicBlock &MBB, | |
457 | MachineBasicBlock::iterator I, | |
458 | unsigned LoOpc, | |
459 | unsigned HiOpc, | |
460 | bool HasExplicitDef) const { | |
461 | // Expand | |
462 | // lo_hi pseudomtlohi $gpr0, $gpr1 | |
463 | // to these two instructions: | |
464 | // mtlo $gpr0 | |
465 | // mthi $gpr1 | |
466 | ||
467 | DebugLoc DL = I->getDebugLoc(); | |
468 | const MachineOperand &SrcLo = I->getOperand(1), &SrcHi = I->getOperand(2); | |
469 | MachineInstrBuilder LoInst = BuildMI(MBB, I, DL, get(LoOpc)); | |
470 | MachineInstrBuilder HiInst = BuildMI(MBB, I, DL, get(HiOpc)); | |
471 | LoInst.addReg(SrcLo.getReg(), getKillRegState(SrcLo.isKill())); | |
472 | HiInst.addReg(SrcHi.getReg(), getKillRegState(SrcHi.isKill())); | |
473 | ||
474 | // Add lo/hi registers if the mtlo/hi instructions created have explicit | |
475 | // def registers. | |
476 | if (HasExplicitDef) { | |
477 | unsigned DstReg = I->getOperand(0).getReg(); | |
478 | unsigned DstLo = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); | |
479 | unsigned DstHi = getRegisterInfo().getSubReg(DstReg, Mips::sub_hi); | |
480 | LoInst.addReg(DstLo, RegState::Define); | |
481 | HiInst.addReg(DstHi, RegState::Define); | |
482 | } | |
223e47cc LB |
483 | } |
484 | ||
1a4d82fc JJ |
485 | void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, |
486 | MachineBasicBlock::iterator I, | |
487 | unsigned CvtOpc, unsigned MovOpc, | |
488 | bool IsI64) const { | |
489 | const MCInstrDesc &CvtDesc = get(CvtOpc), &MovDesc = get(MovOpc); | |
490 | const MachineOperand &Dst = I->getOperand(0), &Src = I->getOperand(1); | |
491 | unsigned DstReg = Dst.getReg(), SrcReg = Src.getReg(), TmpReg = DstReg; | |
492 | unsigned KillSrc = getKillRegState(Src.isKill()); | |
493 | DebugLoc DL = I->getDebugLoc(); | |
494 | bool DstIsLarger, SrcIsLarger; | |
495 | ||
496 | std::tie(DstIsLarger, SrcIsLarger) = | |
497 | compareOpndSize(CvtOpc, *MBB.getParent()); | |
498 | ||
499 | if (DstIsLarger) | |
500 | TmpReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); | |
501 | ||
502 | if (SrcIsLarger) | |
503 | DstReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); | |
504 | ||
505 | BuildMI(MBB, I, DL, MovDesc, TmpReg).addReg(SrcReg, KillSrc); | |
506 | BuildMI(MBB, I, DL, CvtDesc, DstReg).addReg(TmpReg, RegState::Kill); | |
507 | } | |
508 | ||
509 | void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, | |
510 | MachineBasicBlock::iterator I, | |
511 | bool FP64) const { | |
223e47cc LB |
512 | unsigned DstReg = I->getOperand(0).getReg(); |
513 | unsigned SrcReg = I->getOperand(1).getReg(); | |
514 | unsigned N = I->getOperand(2).getImm(); | |
223e47cc LB |
515 | DebugLoc dl = I->getDebugLoc(); |
516 | ||
517 | assert(N < 2 && "Invalid immediate"); | |
1a4d82fc | 518 | unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo; |
223e47cc LB |
519 | unsigned SubReg = getRegisterInfo().getSubReg(SrcReg, SubIdx); |
520 | ||
1a4d82fc JJ |
521 | // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload |
522 | // in MipsSEFrameLowering.cpp. | |
523 | assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); | |
524 | ||
525 | // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload | |
526 | // in MipsSEFrameLowering.cpp. | |
527 | assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); | |
528 | ||
529 | if (SubIdx == Mips::sub_hi && Subtarget.hasMTHC1()) { | |
530 | // FIXME: Strictly speaking MFHC1 only reads the top 32-bits however, we | |
531 | // claim to read the whole 64-bits as part of a white lie used to | |
532 | // temporarily work around a widespread bug in the -mfp64 support. | |
533 | // The problem is that none of the 32-bit fpu ops mention the fact | |
534 | // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that | |
535 | // requires a major overhaul of the FPU implementation which can't | |
536 | // be done right now due to time constraints. | |
537 | // MFHC1 is one of two instructions that are affected since they are | |
538 | // the only instructions that don't read the lower 32-bits. | |
539 | // We therefore pretend that it reads the bottom 32-bits to | |
540 | // artificially create a dependency and prevent the scheduler | |
541 | // changing the behaviour of the code. | |
542 | BuildMI(MBB, I, dl, get(FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32), DstReg) | |
543 | .addReg(SrcReg); | |
544 | } else | |
545 | BuildMI(MBB, I, dl, get(Mips::MFC1), DstReg).addReg(SubReg); | |
223e47cc LB |
546 | } |
547 | ||
1a4d82fc JJ |
548 | void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, |
549 | MachineBasicBlock::iterator I, | |
550 | bool FP64) const { | |
223e47cc LB |
551 | unsigned DstReg = I->getOperand(0).getReg(); |
552 | unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); | |
553 | const MCInstrDesc& Mtc1Tdd = get(Mips::MTC1); | |
554 | DebugLoc dl = I->getDebugLoc(); | |
555 | const TargetRegisterInfo &TRI = getRegisterInfo(); | |
556 | ||
1a4d82fc JJ |
557 | // When mthc1 is available, use: |
558 | // mtc1 Lo, $fp | |
559 | // mthc1 Hi, $fp | |
560 | // | |
561 | // Otherwise, for O32 FPXX ABI: | |
562 | // spill + reload via ldc1 | |
563 | // This case is handled by the frame lowering code. | |
564 | // | |
565 | // Otherwise, for FP32: | |
566 | // mtc1 Lo, $fp | |
567 | // mtc1 Hi, $fp + 1 | |
568 | // | |
569 | // The case where dmtc1 is available doesn't need to be handled here | |
570 | // because it never creates a BuildPairF64 node. | |
571 | ||
572 | // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload | |
573 | // in MipsSEFrameLowering.cpp. | |
574 | assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); | |
575 | ||
576 | // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload | |
577 | // in MipsSEFrameLowering.cpp. | |
578 | assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); | |
579 | ||
580 | BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_lo)) | |
223e47cc | 581 | .addReg(LoReg); |
1a4d82fc JJ |
582 | |
583 | if (Subtarget.hasMTHC1()) { | |
584 | // FIXME: The .addReg(DstReg) is a white lie used to temporarily work | |
585 | // around a widespread bug in the -mfp64 support. | |
586 | // The problem is that none of the 32-bit fpu ops mention the fact | |
587 | // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that | |
588 | // requires a major overhaul of the FPU implementation which can't | |
589 | // be done right now due to time constraints. | |
590 | // MTHC1 is one of two instructions that are affected since they are | |
591 | // the only instructions that don't read the lower 32-bits. | |
592 | // We therefore pretend that it reads the bottom 32-bits to | |
593 | // artificially create a dependency and prevent the scheduler | |
594 | // changing the behaviour of the code. | |
595 | BuildMI(MBB, I, dl, get(FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32), DstReg) | |
596 | .addReg(DstReg) | |
597 | .addReg(HiReg); | |
598 | } else if (Subtarget.isABI_FPXX()) | |
599 | llvm_unreachable("BuildPairF64 not expanded in frame lowering code!"); | |
600 | else | |
601 | BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_hi)) | |
602 | .addReg(HiReg); | |
223e47cc LB |
603 | } |
604 | ||
1a4d82fc | 605 | void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, |
970d7e83 LB |
606 | MachineBasicBlock::iterator I) const { |
607 | // This pseudo instruction is generated as part of the lowering of | |
608 | // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and | |
609 | // indirect jump to TargetReg | |
1a4d82fc JJ |
610 | unsigned ADDU = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; |
611 | unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP; | |
612 | unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA; | |
613 | unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9; | |
614 | unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; | |
970d7e83 LB |
615 | unsigned OffsetReg = I->getOperand(0).getReg(); |
616 | unsigned TargetReg = I->getOperand(1).getReg(); | |
617 | ||
1a4d82fc | 618 | // addu $ra, $v0, $zero |
970d7e83 | 619 | // addu $sp, $sp, $v1 |
1a4d82fc JJ |
620 | // jr $ra (via RetRA) |
621 | const TargetMachine &TM = MBB.getParent()->getTarget(); | |
622 | if (TM.getRelocationModel() == Reloc::PIC_) | |
85aaf69f | 623 | BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9) |
1a4d82fc JJ |
624 | .addReg(TargetReg) |
625 | .addReg(ZERO); | |
85aaf69f | 626 | BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA) |
1a4d82fc JJ |
627 | .addReg(TargetReg) |
628 | .addReg(ZERO); | |
85aaf69f | 629 | BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), SP).addReg(SP).addReg(OffsetReg); |
1a4d82fc | 630 | expandRetRA(MBB, I); |
970d7e83 LB |
631 | } |
632 | ||
1a4d82fc JJ |
633 | const MipsInstrInfo *llvm::createMipsSEInstrInfo(const MipsSubtarget &STI) { |
634 | return new MipsSEInstrInfo(STI); | |
223e47cc | 635 | } |