1 | //===- MipsISelLowering.h - Mips DAG Lowering Interface ---------*- C++ -*-===// |
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 defines the interfaces that Mips uses to lower LLVM code into a |
10 | // selection DAG. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H |
15 | #define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H |
16 | |
17 | #include "MCTargetDesc/MipsABIInfo.h" |
18 | #include "MCTargetDesc/MipsBaseInfo.h" |
19 | #include "MCTargetDesc/MipsMCTargetDesc.h" |
20 | #include "Mips.h" |
21 | #include "llvm/CodeGen/CallingConvLower.h" |
22 | #include "llvm/CodeGen/ISDOpcodes.h" |
23 | #include "llvm/CodeGen/MachineMemOperand.h" |
24 | #include "llvm/CodeGen/SelectionDAG.h" |
25 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
26 | #include "llvm/CodeGen/TargetLowering.h" |
27 | #include "llvm/CodeGen/ValueTypes.h" |
28 | #include "llvm/CodeGenTypes/MachineValueType.h" |
29 | #include "llvm/IR/CallingConv.h" |
30 | #include "llvm/IR/InlineAsm.h" |
31 | #include "llvm/IR/Type.h" |
32 | #include "llvm/Target/TargetMachine.h" |
33 | #include <algorithm> |
34 | #include <deque> |
35 | #include <utility> |
36 | #include <vector> |
37 | |
38 | namespace llvm { |
39 | |
40 | class Argument; |
41 | class FastISel; |
42 | class FunctionLoweringInfo; |
43 | class MachineBasicBlock; |
44 | class MachineFrameInfo; |
45 | class MachineInstr; |
46 | class MipsCCState; |
47 | class MipsFunctionInfo; |
48 | class MipsSubtarget; |
49 | class MipsTargetMachine; |
50 | class TargetLibraryInfo; |
51 | class TargetRegisterClass; |
52 | |
53 | namespace MipsISD { |
54 | |
55 | enum NodeType : unsigned { |
56 | // Start the numbering from where ISD NodeType finishes. |
57 | FIRST_NUMBER = ISD::BUILTIN_OP_END, |
58 | |
59 | // Jump and link (call) |
60 | JmpLink, |
61 | |
62 | // Tail call |
63 | TailCall, |
64 | |
65 | // Get the Highest (63-48) 16 bits from a 64-bit immediate |
66 | Highest, |
67 | |
68 | // Get the Higher (47-32) 16 bits from a 64-bit immediate |
69 | Higher, |
70 | |
71 | // Get the High 16 bits from a 32/64-bit immediate |
72 | // No relation with Mips Hi register |
73 | Hi, |
74 | |
75 | // Get the Lower 16 bits from a 32/64-bit immediate |
76 | // No relation with Mips Lo register |
77 | Lo, |
78 | |
79 | // Get the High 16 bits from a 32 bit immediate for accessing the GOT. |
80 | GotHi, |
81 | |
82 | // Get the High 16 bits from a 32-bit immediate for accessing TLS. |
83 | TlsHi, |
84 | |
85 | // Handle gp_rel (small data/bss sections) relocation. |
86 | GPRel, |
87 | |
88 | // Thread Pointer |
89 | ThreadPointer, |
90 | |
91 | // Vector Floating Point Multiply and Subtract |
92 | FMS, |
93 | |
94 | // Floating Point Branch Conditional |
95 | FPBrcond, |
96 | |
97 | // Floating Point Compare |
98 | FPCmp, |
99 | |
100 | // Floating point Abs |
101 | FAbs, |
102 | |
103 | // Floating point select |
104 | FSELECT, |
105 | |
106 | // Node used to generate an MTC1 i32 to f64 instruction |
107 | MTC1_D64, |
108 | |
109 | // Floating Point Conditional Moves |
110 | CMovFP_T, |
111 | CMovFP_F, |
112 | |
113 | // FP-to-int truncation node. |
114 | TruncIntFP, |
115 | |
116 | // Return |
117 | Ret, |
118 | |
119 | // Interrupt, exception, error trap Return |
120 | ERet, |
121 | |
122 | // Software Exception Return. |
123 | EH_RETURN, |
124 | |
125 | // Node used to extract integer from accumulator. |
126 | MFHI, |
127 | MFLO, |
128 | |
129 | // Node used to insert integers to accumulator. |
130 | MTLOHI, |
131 | |
132 | // Mult nodes. |
133 | Mult, |
134 | Multu, |
135 | |
136 | // MAdd/Sub nodes |
137 | MAdd, |
138 | MAddu, |
139 | MSub, |
140 | MSubu, |
141 | |
142 | // DivRem(u) |
143 | DivRem, |
144 | DivRemU, |
145 | DivRem16, |
146 | DivRemU16, |
147 | |
148 | BuildPairF64, |
149 | , |
150 | |
151 | Wrapper, |
152 | |
153 | DynAlloc, |
154 | |
155 | Sync, |
156 | |
157 | Ext, |
158 | Ins, |
159 | CIns, |
160 | |
161 | // EXTR.W intrinsic nodes. |
162 | EXTP, |
163 | EXTPDP, |
164 | EXTR_S_H, |
165 | EXTR_W, |
166 | EXTR_R_W, |
167 | EXTR_RS_W, |
168 | SHILO, |
169 | MTHLIP, |
170 | |
171 | // DPA.W intrinsic nodes. |
172 | MULSAQ_S_W_PH, |
173 | MAQ_S_W_PHL, |
174 | MAQ_S_W_PHR, |
175 | MAQ_SA_W_PHL, |
176 | MAQ_SA_W_PHR, |
177 | DPAU_H_QBL, |
178 | DPAU_H_QBR, |
179 | DPSU_H_QBL, |
180 | DPSU_H_QBR, |
181 | DPAQ_S_W_PH, |
182 | DPSQ_S_W_PH, |
183 | DPAQ_SA_L_W, |
184 | DPSQ_SA_L_W, |
185 | DPA_W_PH, |
186 | DPS_W_PH, |
187 | DPAQX_S_W_PH, |
188 | DPAQX_SA_W_PH, |
189 | DPAX_W_PH, |
190 | DPSX_W_PH, |
191 | DPSQX_S_W_PH, |
192 | DPSQX_SA_W_PH, |
193 | MULSA_W_PH, |
194 | |
195 | MULT, |
196 | MULTU, |
197 | MADD_DSP, |
198 | MADDU_DSP, |
199 | MSUB_DSP, |
200 | MSUBU_DSP, |
201 | |
202 | // DSP shift nodes. |
203 | SHLL_DSP, |
204 | SHRA_DSP, |
205 | SHRL_DSP, |
206 | |
207 | // DSP setcc and select_cc nodes. |
208 | SETCC_DSP, |
209 | SELECT_CC_DSP, |
210 | |
211 | // Vector comparisons. |
212 | // These take a vector and return a boolean. |
213 | VALL_ZERO, |
214 | VANY_ZERO, |
215 | VALL_NONZERO, |
216 | VANY_NONZERO, |
217 | |
218 | // These take a vector and return a vector bitmask. |
219 | VCEQ, |
220 | VCLE_S, |
221 | VCLE_U, |
222 | VCLT_S, |
223 | VCLT_U, |
224 | |
225 | // Vector Shuffle with mask as an operand |
226 | VSHF, // Generic shuffle |
227 | SHF, // 4-element set shuffle. |
228 | ILVEV, // Interleave even elements |
229 | ILVOD, // Interleave odd elements |
230 | ILVL, // Interleave left elements |
231 | ILVR, // Interleave right elements |
232 | PCKEV, // Pack even elements |
233 | PCKOD, // Pack odd elements |
234 | |
235 | // Vector Lane Copy |
236 | INSVE, // Copy element from one vector to another |
237 | |
238 | // Combined (XOR (OR $a, $b), -1) |
239 | VNOR, |
240 | |
241 | // Extended vector element extraction |
242 | , |
243 | , |
244 | |
245 | // Double select nodes for machines without conditional-move. |
246 | DOUBLE_SELECT_I, |
247 | DOUBLE_SELECT_I64, |
248 | |
249 | // Load/Store Left/Right nodes. |
250 | FIRST_MEMORY_OPCODE, |
251 | LWL = FIRST_MEMORY_OPCODE, |
252 | LWR, |
253 | SWL, |
254 | SWR, |
255 | LDL, |
256 | LDR, |
257 | SDL, |
258 | SDR, |
259 | LAST_MEMORY_OPCODE = SDR, |
260 | }; |
261 | |
262 | } // ene namespace MipsISD |
263 | |
264 | //===--------------------------------------------------------------------===// |
265 | // TargetLowering Implementation |
266 | //===--------------------------------------------------------------------===// |
267 | |
268 | class MipsTargetLowering : public TargetLowering { |
269 | bool isMicroMips; |
270 | |
271 | public: |
272 | explicit MipsTargetLowering(const MipsTargetMachine &TM, |
273 | const MipsSubtarget &STI); |
274 | |
275 | static const MipsTargetLowering *create(const MipsTargetMachine &TM, |
276 | const MipsSubtarget &STI); |
277 | |
278 | /// createFastISel - This method returns a target specific FastISel object, |
279 | /// or null if the target does not support "fast" ISel. |
280 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
281 | const TargetLibraryInfo *libInfo) const override; |
282 | |
283 | MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { |
284 | return MVT::i32; |
285 | } |
286 | |
287 | EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, |
288 | ISD::NodeType) const override; |
289 | |
290 | bool isCheapToSpeculateCttz(Type *Ty) const override; |
291 | bool isCheapToSpeculateCtlz(Type *Ty) const override; |
292 | bool hasBitTest(SDValue X, SDValue Y) const override; |
293 | bool shouldFoldConstantShiftPairToMask(const SDNode *N, |
294 | CombineLevel Level) const override; |
295 | |
296 | /// Return the register type for a given MVT, ensuring vectors are treated |
297 | /// as a series of gpr sized integers. |
298 | MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, |
299 | EVT VT) const override; |
300 | |
301 | /// Return the number of registers for a given MVT, ensuring vectors are |
302 | /// treated as a series of gpr sized integers. |
303 | unsigned getNumRegistersForCallingConv(LLVMContext &Context, |
304 | CallingConv::ID CC, |
305 | EVT VT) const override; |
306 | |
307 | /// Break down vectors to the correct number of gpr sized integers. |
308 | unsigned getVectorTypeBreakdownForCallingConv( |
309 | LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, |
310 | unsigned &NumIntermediates, MVT &RegisterVT) const override; |
311 | |
312 | /// Return the correct alignment for the current calling convention. |
313 | Align getABIAlignmentForCallingConv(Type *ArgTy, |
314 | const DataLayout &DL) const override { |
315 | const Align ABIAlign = DL.getABITypeAlign(Ty: ArgTy); |
316 | if (ArgTy->isVectorTy()) |
317 | return std::min(a: ABIAlign, b: Align(8)); |
318 | return ABIAlign; |
319 | } |
320 | |
321 | ISD::NodeType getExtendForAtomicOps() const override { |
322 | return ISD::SIGN_EXTEND; |
323 | } |
324 | |
325 | /// LowerOperation - Provide custom lowering hooks for some operations. |
326 | SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; |
327 | |
328 | /// ReplaceNodeResults - Replace the results of node with an illegal result |
329 | /// type with new values built out of custom code. |
330 | /// |
331 | void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, |
332 | SelectionDAG &DAG) const override; |
333 | |
334 | /// getTargetNodeName - This method returns the name of a target specific |
335 | // DAG node. |
336 | const char *getTargetNodeName(unsigned Opcode) const override; |
337 | |
338 | /// getSetCCResultType - get the ISD::SETCC result ValueType |
339 | EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, |
340 | EVT VT) const override; |
341 | |
342 | SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; |
343 | |
344 | MachineBasicBlock * |
345 | EmitInstrWithCustomInserter(MachineInstr &MI, |
346 | MachineBasicBlock *MBB) const override; |
347 | |
348 | void AdjustInstrPostInstrSelection(MachineInstr &MI, |
349 | SDNode *Node) const override; |
350 | |
351 | void HandleByVal(CCState *, unsigned &, Align) const override; |
352 | |
353 | Register getRegisterByName(const char* RegName, LLT VT, |
354 | const MachineFunction &MF) const override; |
355 | |
356 | /// If a physical register, this returns the register that receives the |
357 | /// exception address on entry to an EH pad. |
358 | Register |
359 | getExceptionPointerRegister(const Constant *PersonalityFn) const override { |
360 | return ABI.IsN64() ? Mips::A0_64 : Mips::A0; |
361 | } |
362 | |
363 | /// If a physical register, this returns the register that receives the |
364 | /// exception typeid on entry to a landing pad. |
365 | Register |
366 | getExceptionSelectorRegister(const Constant *PersonalityFn) const override { |
367 | return ABI.IsN64() ? Mips::A1_64 : Mips::A1; |
368 | } |
369 | |
370 | bool softPromoteHalfType() const override { return true; } |
371 | |
372 | bool isJumpTableRelative() const override { |
373 | return getTargetMachine().isPositionIndependent(); |
374 | } |
375 | |
376 | CCAssignFn *CCAssignFnForCall() const; |
377 | |
378 | CCAssignFn *CCAssignFnForReturn() const; |
379 | |
380 | protected: |
381 | SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; |
382 | |
383 | // This method creates the following nodes, which are necessary for |
384 | // computing a local symbol's address: |
385 | // |
386 | // (add (load (wrapper $gp, %got(sym)), %lo(sym)) |
387 | template <class NodeTy> |
388 | SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, |
389 | bool IsN32OrN64) const { |
390 | unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; |
391 | SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), |
392 | getTargetNode(N, Ty, DAG, GOTFlag)); |
393 | SDValue Load = |
394 | DAG.getLoad(VT: Ty, dl: DL, Chain: DAG.getEntryNode(), Ptr: GOT, |
395 | PtrInfo: MachinePointerInfo::getGOT(MF&: DAG.getMachineFunction())); |
396 | unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; |
397 | SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty, |
398 | getTargetNode(N, Ty, DAG, LoFlag)); |
399 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Load, N2: Lo); |
400 | } |
401 | |
402 | // This method creates the following nodes, which are necessary for |
403 | // computing a global symbol's address: |
404 | // |
405 | // (load (wrapper $gp, %got(sym))) |
406 | template <class NodeTy> |
407 | SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, |
408 | unsigned Flag, SDValue Chain, |
409 | const MachinePointerInfo &PtrInfo) const { |
410 | SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), |
411 | getTargetNode(N, Ty, DAG, Flag)); |
412 | return DAG.getLoad(VT: Ty, dl: DL, Chain, Ptr: Tgt, PtrInfo); |
413 | } |
414 | |
415 | // This method creates the following nodes, which are necessary for |
416 | // computing a global symbol's address in large-GOT mode: |
417 | // |
418 | // (load (wrapper (add %hi(sym), $gp), %lo(sym))) |
419 | template <class NodeTy> |
420 | SDValue getAddrGlobalLargeGOT(NodeTy *N, const SDLoc &DL, EVT Ty, |
421 | SelectionDAG &DAG, unsigned HiFlag, |
422 | unsigned LoFlag, SDValue Chain, |
423 | const MachinePointerInfo &PtrInfo) const { |
424 | SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty, |
425 | getTargetNode(N, Ty, DAG, HiFlag)); |
426 | Hi = DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Hi, N2: getGlobalReg(DAG, Ty)); |
427 | SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, |
428 | getTargetNode(N, Ty, DAG, LoFlag)); |
429 | return DAG.getLoad(VT: Ty, dl: DL, Chain, Ptr: Wrapper, PtrInfo); |
430 | } |
431 | |
432 | // This method creates the following nodes, which are necessary for |
433 | // computing a symbol's address in non-PIC mode: |
434 | // |
435 | // (add %hi(sym), %lo(sym)) |
436 | // |
437 | // This method covers O32, N32 and N64 in sym32 mode. |
438 | template <class NodeTy> |
439 | SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty, |
440 | SelectionDAG &DAG) const { |
441 | SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); |
442 | SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); |
443 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, |
444 | N1: DAG.getNode(Opcode: MipsISD::Hi, DL, VT: Ty, Operand: Hi), |
445 | N2: DAG.getNode(Opcode: MipsISD::Lo, DL, VT: Ty, Operand: Lo)); |
446 | } |
447 | |
448 | // This method creates the following nodes, which are necessary for |
449 | // computing a symbol's address in non-PIC mode for N64. |
450 | // |
451 | // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)), |
452 | // 16), %lo(%sym)) |
453 | // |
454 | // FIXME: This method is not efficent for (micro)MIPS64R6. |
455 | template <class NodeTy> |
456 | SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty, |
457 | SelectionDAG &DAG) const { |
458 | SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); |
459 | SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); |
460 | |
461 | SDValue Highest = |
462 | DAG.getNode(MipsISD::Highest, DL, Ty, |
463 | getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST)); |
464 | SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER); |
465 | SDValue HigherPart = |
466 | DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Highest, |
467 | N2: DAG.getNode(Opcode: MipsISD::Higher, DL, VT: Ty, Operand: Higher)); |
468 | SDValue Cst = DAG.getConstant(Val: 16, DL, VT: MVT::i32); |
469 | SDValue Shift = DAG.getNode(Opcode: ISD::SHL, DL, VT: Ty, N1: HigherPart, N2: Cst); |
470 | SDValue Add = DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Shift, |
471 | N2: DAG.getNode(Opcode: MipsISD::Hi, DL, VT: Ty, Operand: Hi)); |
472 | SDValue Shift2 = DAG.getNode(Opcode: ISD::SHL, DL, VT: Ty, N1: Add, N2: Cst); |
473 | |
474 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Shift2, |
475 | N2: DAG.getNode(Opcode: MipsISD::Lo, DL, VT: Ty, Operand: Lo)); |
476 | } |
477 | |
478 | // This method creates the following nodes, which are necessary for |
479 | // computing a symbol's address using gp-relative addressing: |
480 | // |
481 | // (add $gp, %gp_rel(sym)) |
482 | template <class NodeTy> |
483 | SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty, |
484 | SelectionDAG &DAG, bool IsN64) const { |
485 | SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); |
486 | return DAG.getNode( |
487 | Opcode: ISD::ADD, DL, VT: Ty, |
488 | N1: DAG.getRegister(Reg: IsN64 ? Mips::GP_64 : Mips::GP, VT: Ty), |
489 | N2: DAG.getNode(Opcode: MipsISD::GPRel, DL, VTList: DAG.getVTList(VT: Ty), N: GPRel)); |
490 | } |
491 | |
492 | // This method creates the following nodes, which are necessary for |
493 | // loading a dllimported symbol: |
494 | // |
495 | // (lw (add (shl(%high(sym), 16), %low(sym))) |
496 | template <class NodeTy> |
497 | SDValue getDllimportSymbol(NodeTy *N, const SDLoc &DL, EVT Ty, |
498 | SelectionDAG &DAG) const { |
499 | SDValue Hi = |
500 | getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI | MipsII::MO_DLLIMPORT); |
501 | SDValue Lo = |
502 | getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO | MipsII::MO_DLLIMPORT); |
503 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: DAG.getNode(Opcode: MipsISD::Lo, DL, VT: Ty, Operand: Lo), |
504 | N2: DAG.getNode(Opcode: MipsISD::Hi, DL, VT: Ty, Operand: Hi)); |
505 | } |
506 | |
507 | // This method creates the following nodes, which are necessary for |
508 | // loading a dllimported global variable: |
509 | // |
510 | // (lw (lw (add (shl(%high(sym), 16), %low(sym)))) |
511 | template <class NodeTy> |
512 | SDValue getDllimportVariable(NodeTy *N, const SDLoc &DL, EVT Ty, |
513 | SelectionDAG &DAG, SDValue Chain, |
514 | const MachinePointerInfo &PtrInfo) const { |
515 | return DAG.getLoad(Ty, DL, Chain, getDllimportSymbol(N, DL, Ty, DAG), |
516 | PtrInfo); |
517 | } |
518 | |
519 | /// This function fills Ops, which is the list of operands that will later |
520 | /// be used when a function call node is created. It also generates |
521 | /// copyToReg nodes to set up argument registers. |
522 | virtual void |
523 | getOpndList(SmallVectorImpl<SDValue> &Ops, |
524 | std::deque<std::pair<unsigned, SDValue>> &RegsToPass, |
525 | bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, |
526 | bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, |
527 | SDValue Chain) const; |
528 | |
529 | protected: |
530 | SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; |
531 | SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; |
532 | |
533 | // Subtarget Info |
534 | const MipsSubtarget &Subtarget; |
535 | // Cache the ABI from the TargetMachine, we use it everywhere. |
536 | const MipsABIInfo &ABI; |
537 | |
538 | private: |
539 | // Create a TargetGlobalAddress node. |
540 | SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, |
541 | unsigned Flag) const; |
542 | |
543 | // Create a TargetExternalSymbol node. |
544 | SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, |
545 | unsigned Flag) const; |
546 | |
547 | // Create a TargetBlockAddress node. |
548 | SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, |
549 | unsigned Flag) const; |
550 | |
551 | // Create a TargetJumpTable node. |
552 | SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, |
553 | unsigned Flag) const; |
554 | |
555 | // Create a TargetConstantPool node. |
556 | SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, |
557 | unsigned Flag) const; |
558 | |
559 | // Lower Operand helpers |
560 | SDValue LowerCallResult(SDValue Chain, SDValue InGlue, |
561 | CallingConv::ID CallConv, bool isVarArg, |
562 | const SmallVectorImpl<ISD::InputArg> &Ins, |
563 | const SDLoc &dl, SelectionDAG &DAG, |
564 | SmallVectorImpl<SDValue> &InVals, |
565 | TargetLowering::CallLoweringInfo &CLI) const; |
566 | |
567 | // Lower Operand specifics |
568 | SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const; |
569 | SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; |
570 | SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
571 | SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; |
572 | SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
573 | SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; |
574 | SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; |
575 | SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const; |
576 | SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; |
577 | SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; |
578 | SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; |
579 | SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const; |
580 | SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, |
581 | bool ) const; |
582 | SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG, |
583 | bool ) const; |
584 | SDValue lowerFCANONICALIZE(SDValue Op, SelectionDAG &DAG) const; |
585 | SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; |
586 | SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; |
587 | SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; |
588 | SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; |
589 | SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; |
590 | SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, |
591 | bool IsSRA) const; |
592 | SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; |
593 | SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; |
594 | SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const; |
595 | SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const; |
596 | |
597 | /// isEligibleForTailCallOptimization - Check whether the call is eligible |
598 | /// for tail call optimization. |
599 | virtual bool |
600 | isEligibleForTailCallOptimization(const CCState &CCInfo, |
601 | unsigned NextStackOffset, |
602 | const MipsFunctionInfo &FI) const = 0; |
603 | |
604 | /// copyByValArg - Copy argument registers which were used to pass a byval |
605 | /// argument to the stack. Create a stack frame object for the byval |
606 | /// argument. |
607 | void copyByValRegs(SDValue Chain, const SDLoc &DL, |
608 | std::vector<SDValue> &OutChains, SelectionDAG &DAG, |
609 | const ISD::ArgFlagsTy &Flags, |
610 | SmallVectorImpl<SDValue> &InVals, |
611 | const Argument *FuncArg, unsigned FirstReg, |
612 | unsigned LastReg, const CCValAssign &VA, |
613 | MipsCCState &State) const; |
614 | |
615 | /// passByValArg - Pass a byval argument in registers or on stack. |
616 | void passByValArg(SDValue Chain, const SDLoc &DL, |
617 | std::deque<std::pair<unsigned, SDValue>> &RegsToPass, |
618 | SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, |
619 | MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, |
620 | unsigned FirstReg, unsigned LastReg, |
621 | const ISD::ArgFlagsTy &Flags, bool isLittle, |
622 | const CCValAssign &VA) const; |
623 | |
624 | /// writeVarArgRegs - Write variable function arguments passed in registers |
625 | /// to the stack. Also create a stack frame object for the first variable |
626 | /// argument. |
627 | void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain, |
628 | const SDLoc &DL, SelectionDAG &DAG, |
629 | CCState &State) const; |
630 | |
631 | SDValue |
632 | LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
633 | const SmallVectorImpl<ISD::InputArg> &Ins, |
634 | const SDLoc &dl, SelectionDAG &DAG, |
635 | SmallVectorImpl<SDValue> &InVals) const override; |
636 | |
637 | SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, |
638 | SDValue Arg, const SDLoc &DL, bool IsTailCall, |
639 | SelectionDAG &DAG) const; |
640 | |
641 | SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, |
642 | SmallVectorImpl<SDValue> &InVals) const override; |
643 | |
644 | bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, |
645 | bool isVarArg, |
646 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
647 | LLVMContext &Context, const Type *RetTy) const override; |
648 | |
649 | SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
650 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
651 | const SmallVectorImpl<SDValue> &OutVals, |
652 | const SDLoc &dl, SelectionDAG &DAG) const override; |
653 | |
654 | SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, |
655 | const SDLoc &DL, SelectionDAG &DAG) const; |
656 | |
657 | bool shouldSignExtendTypeInLibCall(Type *Ty, bool IsSigned) const override; |
658 | |
659 | // Inline asm support |
660 | ConstraintType getConstraintType(StringRef Constraint) const override; |
661 | |
662 | /// Examine constraint string and operand type and determine a weight value. |
663 | /// The operand object must already have been set up with the operand type. |
664 | ConstraintWeight getSingleConstraintMatchWeight( |
665 | AsmOperandInfo &info, const char *constraint) const override; |
666 | |
667 | /// This function parses registers that appear in inline-asm constraints. |
668 | /// It returns pair (0, 0) on failure. |
669 | std::pair<unsigned, const TargetRegisterClass *> |
670 | parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; |
671 | |
672 | std::pair<unsigned, const TargetRegisterClass *> |
673 | getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
674 | StringRef Constraint, MVT VT) const override; |
675 | |
676 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops |
677 | /// vector. If it is invalid, don't add anything to Ops. If hasMemory is |
678 | /// true it means one of the asm constraint of the inline asm instruction |
679 | /// being processed is 'm'. |
680 | void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, |
681 | std::vector<SDValue> &Ops, |
682 | SelectionDAG &DAG) const override; |
683 | |
684 | InlineAsm::ConstraintCode |
685 | getInlineAsmMemConstraint(StringRef ConstraintCode) const override { |
686 | if (ConstraintCode == "o" ) |
687 | return InlineAsm::ConstraintCode::o; |
688 | if (ConstraintCode == "R" ) |
689 | return InlineAsm::ConstraintCode::R; |
690 | if (ConstraintCode == "ZC" ) |
691 | return InlineAsm::ConstraintCode::ZC; |
692 | return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); |
693 | } |
694 | |
695 | bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, |
696 | Type *Ty, unsigned AS, |
697 | Instruction *I = nullptr) const override; |
698 | |
699 | bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; |
700 | |
701 | EVT getOptimalMemOpType(const MemOp &Op, |
702 | const AttributeList &FuncAttributes) const override; |
703 | |
704 | /// isFPImmLegal - Returns true if the target can instruction select the |
705 | /// specified FP immediate natively. If false, the legalizer will |
706 | /// materialize the FP immediate as a load from a constant pool. |
707 | bool isFPImmLegal(const APFloat &Imm, EVT VT, |
708 | bool ForCodeSize) const override; |
709 | |
710 | bool isLegalICmpImmediate(int64_t Imm) const override; |
711 | bool isLegalAddImmediate(int64_t Imm) const override; |
712 | |
713 | unsigned getJumpTableEncoding() const override; |
714 | SDValue getPICJumpTableRelocBase(SDValue Table, |
715 | SelectionDAG &DAG) const override; |
716 | bool useSoftFloat() const override; |
717 | |
718 | bool shouldInsertFencesForAtomic(const Instruction *I) const override { |
719 | return true; |
720 | } |
721 | |
722 | /// Emit a sign-extension using sll/sra, seb, or seh appropriately. |
723 | MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, |
724 | MachineBasicBlock *BB, |
725 | unsigned Size, unsigned DstReg, |
726 | unsigned SrcRec) const; |
727 | |
728 | MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, |
729 | MachineBasicBlock *BB) const; |
730 | MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, |
731 | MachineBasicBlock *BB, |
732 | unsigned Size) const; |
733 | MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, |
734 | MachineBasicBlock *BB) const; |
735 | MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, |
736 | MachineBasicBlock *BB, |
737 | unsigned Size) const; |
738 | MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const; |
739 | MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB, |
740 | bool isFPCmp, unsigned Opc) const; |
741 | MachineBasicBlock *emitPseudoD_SELECT(MachineInstr &MI, |
742 | MachineBasicBlock *BB) const; |
743 | MachineBasicBlock *emitLDR_W(MachineInstr &MI, MachineBasicBlock *BB) const; |
744 | MachineBasicBlock *emitLDR_D(MachineInstr &MI, MachineBasicBlock *BB) const; |
745 | MachineBasicBlock *emitSTR_W(MachineInstr &MI, MachineBasicBlock *BB) const; |
746 | MachineBasicBlock *emitSTR_D(MachineInstr &MI, MachineBasicBlock *BB) const; |
747 | }; |
748 | |
749 | /// Create MipsTargetLowering objects. |
750 | const MipsTargetLowering * |
751 | createMips16TargetLowering(const MipsTargetMachine &TM, |
752 | const MipsSubtarget &STI); |
753 | const MipsTargetLowering * |
754 | createMipsSETargetLowering(const MipsTargetMachine &TM, |
755 | const MipsSubtarget &STI); |
756 | |
757 | namespace Mips { |
758 | |
759 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
760 | const TargetLibraryInfo *libInfo); |
761 | |
762 | } // end namespace Mips |
763 | |
764 | } // end namespace llvm |
765 | |
766 | #endif // LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H |
767 | |