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 | LWL = ISD::FIRST_TARGET_MEMORY_OPCODE, |
251 | LWR, |
252 | SWL, |
253 | SWR, |
254 | LDL, |
255 | LDR, |
256 | SDL, |
257 | SDR |
258 | }; |
259 | |
260 | } // ene namespace MipsISD |
261 | |
262 | //===--------------------------------------------------------------------===// |
263 | // TargetLowering Implementation |
264 | //===--------------------------------------------------------------------===// |
265 | |
266 | class MipsTargetLowering : public TargetLowering { |
267 | bool isMicroMips; |
268 | |
269 | public: |
270 | explicit MipsTargetLowering(const MipsTargetMachine &TM, |
271 | const MipsSubtarget &STI); |
272 | |
273 | static const MipsTargetLowering *create(const MipsTargetMachine &TM, |
274 | const MipsSubtarget &STI); |
275 | |
276 | /// createFastISel - This method returns a target specific FastISel object, |
277 | /// or null if the target does not support "fast" ISel. |
278 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
279 | const TargetLibraryInfo *libInfo) const override; |
280 | |
281 | MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { |
282 | return MVT::i32; |
283 | } |
284 | |
285 | EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, |
286 | ISD::NodeType) const override; |
287 | |
288 | bool isCheapToSpeculateCttz(Type *Ty) const override; |
289 | bool isCheapToSpeculateCtlz(Type *Ty) const override; |
290 | bool hasBitTest(SDValue X, SDValue Y) const override; |
291 | bool shouldFoldConstantShiftPairToMask(const SDNode *N, |
292 | CombineLevel Level) const override; |
293 | |
294 | /// Return the register type for a given MVT, ensuring vectors are treated |
295 | /// as a series of gpr sized integers. |
296 | MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, |
297 | EVT VT) const override; |
298 | |
299 | /// Return the number of registers for a given MVT, ensuring vectors are |
300 | /// treated as a series of gpr sized integers. |
301 | unsigned getNumRegistersForCallingConv(LLVMContext &Context, |
302 | CallingConv::ID CC, |
303 | EVT VT) const override; |
304 | |
305 | /// Break down vectors to the correct number of gpr sized integers. |
306 | unsigned getVectorTypeBreakdownForCallingConv( |
307 | LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, |
308 | unsigned &NumIntermediates, MVT &RegisterVT) const override; |
309 | |
310 | /// Return the correct alignment for the current calling convention. |
311 | Align getABIAlignmentForCallingConv(Type *ArgTy, |
312 | const DataLayout &DL) const override { |
313 | const Align ABIAlign = DL.getABITypeAlign(Ty: ArgTy); |
314 | if (ArgTy->isVectorTy()) |
315 | return std::min(a: ABIAlign, b: Align(8)); |
316 | return ABIAlign; |
317 | } |
318 | |
319 | ISD::NodeType getExtendForAtomicOps() const override { |
320 | return ISD::SIGN_EXTEND; |
321 | } |
322 | |
323 | /// LowerOperation - Provide custom lowering hooks for some operations. |
324 | SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; |
325 | |
326 | /// ReplaceNodeResults - Replace the results of node with an illegal result |
327 | /// type with new values built out of custom code. |
328 | /// |
329 | void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results, |
330 | SelectionDAG &DAG) const override; |
331 | |
332 | /// getTargetNodeName - This method returns the name of a target specific |
333 | // DAG node. |
334 | const char *getTargetNodeName(unsigned Opcode) const override; |
335 | |
336 | /// getSetCCResultType - get the ISD::SETCC result ValueType |
337 | EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, |
338 | EVT VT) const override; |
339 | |
340 | SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; |
341 | |
342 | MachineBasicBlock * |
343 | EmitInstrWithCustomInserter(MachineInstr &MI, |
344 | MachineBasicBlock *MBB) const override; |
345 | |
346 | void AdjustInstrPostInstrSelection(MachineInstr &MI, |
347 | SDNode *Node) const override; |
348 | |
349 | void HandleByVal(CCState *, unsigned &, Align) const override; |
350 | |
351 | Register getRegisterByName(const char* RegName, LLT VT, |
352 | const MachineFunction &MF) const override; |
353 | |
354 | /// If a physical register, this returns the register that receives the |
355 | /// exception address on entry to an EH pad. |
356 | Register |
357 | getExceptionPointerRegister(const Constant *PersonalityFn) const override { |
358 | return ABI.IsN64() ? Mips::A0_64 : Mips::A0; |
359 | } |
360 | |
361 | /// If a physical register, this returns the register that receives the |
362 | /// exception typeid on entry to a landing pad. |
363 | Register |
364 | getExceptionSelectorRegister(const Constant *PersonalityFn) const override { |
365 | return ABI.IsN64() ? Mips::A1_64 : Mips::A1; |
366 | } |
367 | |
368 | bool isJumpTableRelative() const override { |
369 | return getTargetMachine().isPositionIndependent(); |
370 | } |
371 | |
372 | CCAssignFn *CCAssignFnForCall() const; |
373 | |
374 | CCAssignFn *CCAssignFnForReturn() const; |
375 | |
376 | protected: |
377 | SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; |
378 | |
379 | // This method creates the following nodes, which are necessary for |
380 | // computing a local symbol's address: |
381 | // |
382 | // (add (load (wrapper $gp, %got(sym)), %lo(sym)) |
383 | template <class NodeTy> |
384 | SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, |
385 | bool IsN32OrN64) const { |
386 | unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; |
387 | SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), |
388 | getTargetNode(N, Ty, DAG, GOTFlag)); |
389 | SDValue Load = |
390 | DAG.getLoad(VT: Ty, dl: DL, Chain: DAG.getEntryNode(), Ptr: GOT, |
391 | PtrInfo: MachinePointerInfo::getGOT(MF&: DAG.getMachineFunction())); |
392 | unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; |
393 | SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty, |
394 | getTargetNode(N, Ty, DAG, LoFlag)); |
395 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Load, N2: Lo); |
396 | } |
397 | |
398 | // This method creates the following nodes, which are necessary for |
399 | // computing a global symbol's address: |
400 | // |
401 | // (load (wrapper $gp, %got(sym))) |
402 | template <class NodeTy> |
403 | SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, |
404 | unsigned Flag, SDValue Chain, |
405 | const MachinePointerInfo &PtrInfo) const { |
406 | SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), |
407 | getTargetNode(N, Ty, DAG, Flag)); |
408 | return DAG.getLoad(VT: Ty, dl: DL, Chain, Ptr: Tgt, PtrInfo); |
409 | } |
410 | |
411 | // This method creates the following nodes, which are necessary for |
412 | // computing a global symbol's address in large-GOT mode: |
413 | // |
414 | // (load (wrapper (add %hi(sym), $gp), %lo(sym))) |
415 | template <class NodeTy> |
416 | SDValue getAddrGlobalLargeGOT(NodeTy *N, const SDLoc &DL, EVT Ty, |
417 | SelectionDAG &DAG, unsigned HiFlag, |
418 | unsigned LoFlag, SDValue Chain, |
419 | const MachinePointerInfo &PtrInfo) const { |
420 | SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty, |
421 | getTargetNode(N, Ty, DAG, HiFlag)); |
422 | Hi = DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Hi, N2: getGlobalReg(DAG, Ty)); |
423 | SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, |
424 | getTargetNode(N, Ty, DAG, LoFlag)); |
425 | return DAG.getLoad(VT: Ty, dl: DL, Chain, Ptr: Wrapper, PtrInfo); |
426 | } |
427 | |
428 | // This method creates the following nodes, which are necessary for |
429 | // computing a symbol's address in non-PIC mode: |
430 | // |
431 | // (add %hi(sym), %lo(sym)) |
432 | // |
433 | // This method covers O32, N32 and N64 in sym32 mode. |
434 | template <class NodeTy> |
435 | SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty, |
436 | SelectionDAG &DAG) const { |
437 | SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); |
438 | SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); |
439 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, |
440 | N1: DAG.getNode(Opcode: MipsISD::Hi, DL, VT: Ty, Operand: Hi), |
441 | N2: DAG.getNode(Opcode: MipsISD::Lo, DL, VT: Ty, Operand: Lo)); |
442 | } |
443 | |
444 | // This method creates the following nodes, which are necessary for |
445 | // computing a symbol's address in non-PIC mode for N64. |
446 | // |
447 | // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)), |
448 | // 16), %lo(%sym)) |
449 | // |
450 | // FIXME: This method is not efficent for (micro)MIPS64R6. |
451 | template <class NodeTy> |
452 | SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty, |
453 | SelectionDAG &DAG) const { |
454 | SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); |
455 | SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); |
456 | |
457 | SDValue Highest = |
458 | DAG.getNode(MipsISD::Highest, DL, Ty, |
459 | getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST)); |
460 | SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER); |
461 | SDValue HigherPart = |
462 | DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Highest, |
463 | N2: DAG.getNode(Opcode: MipsISD::Higher, DL, VT: Ty, Operand: Higher)); |
464 | SDValue Cst = DAG.getConstant(Val: 16, DL, VT: MVT::i32); |
465 | SDValue Shift = DAG.getNode(Opcode: ISD::SHL, DL, VT: Ty, N1: HigherPart, N2: Cst); |
466 | SDValue Add = DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Shift, |
467 | N2: DAG.getNode(Opcode: MipsISD::Hi, DL, VT: Ty, Operand: Hi)); |
468 | SDValue Shift2 = DAG.getNode(Opcode: ISD::SHL, DL, VT: Ty, N1: Add, N2: Cst); |
469 | |
470 | return DAG.getNode(Opcode: ISD::ADD, DL, VT: Ty, N1: Shift2, |
471 | N2: DAG.getNode(Opcode: MipsISD::Lo, DL, VT: Ty, Operand: Lo)); |
472 | } |
473 | |
474 | // This method creates the following nodes, which are necessary for |
475 | // computing a symbol's address using gp-relative addressing: |
476 | // |
477 | // (add $gp, %gp_rel(sym)) |
478 | template <class NodeTy> |
479 | SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty, |
480 | SelectionDAG &DAG, bool IsN64) const { |
481 | SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); |
482 | return DAG.getNode( |
483 | Opcode: ISD::ADD, DL, VT: Ty, |
484 | N1: DAG.getRegister(Reg: IsN64 ? Mips::GP_64 : Mips::GP, VT: Ty), |
485 | N2: DAG.getNode(Opcode: MipsISD::GPRel, DL, VTList: DAG.getVTList(VT: Ty), N: GPRel)); |
486 | } |
487 | |
488 | /// This function fills Ops, which is the list of operands that will later |
489 | /// be used when a function call node is created. It also generates |
490 | /// copyToReg nodes to set up argument registers. |
491 | virtual void |
492 | getOpndList(SmallVectorImpl<SDValue> &Ops, |
493 | std::deque<std::pair<unsigned, SDValue>> &RegsToPass, |
494 | bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, |
495 | bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, |
496 | SDValue Chain) const; |
497 | |
498 | protected: |
499 | SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; |
500 | SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; |
501 | |
502 | // Subtarget Info |
503 | const MipsSubtarget &Subtarget; |
504 | // Cache the ABI from the TargetMachine, we use it everywhere. |
505 | const MipsABIInfo &ABI; |
506 | |
507 | private: |
508 | // Create a TargetGlobalAddress node. |
509 | SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG, |
510 | unsigned Flag) const; |
511 | |
512 | // Create a TargetExternalSymbol node. |
513 | SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG, |
514 | unsigned Flag) const; |
515 | |
516 | // Create a TargetBlockAddress node. |
517 | SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG, |
518 | unsigned Flag) const; |
519 | |
520 | // Create a TargetJumpTable node. |
521 | SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, |
522 | unsigned Flag) const; |
523 | |
524 | // Create a TargetConstantPool node. |
525 | SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG, |
526 | unsigned Flag) const; |
527 | |
528 | // Lower Operand helpers |
529 | SDValue LowerCallResult(SDValue Chain, SDValue InGlue, |
530 | CallingConv::ID CallConv, bool isVarArg, |
531 | const SmallVectorImpl<ISD::InputArg> &Ins, |
532 | const SDLoc &dl, SelectionDAG &DAG, |
533 | SmallVectorImpl<SDValue> &InVals, |
534 | TargetLowering::CallLoweringInfo &CLI) const; |
535 | |
536 | // Lower Operand specifics |
537 | SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const; |
538 | SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; |
539 | SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; |
540 | SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; |
541 | SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; |
542 | SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; |
543 | SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; |
544 | SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const; |
545 | SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; |
546 | SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const; |
547 | SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; |
548 | SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const; |
549 | SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG, |
550 | bool ) const; |
551 | SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG, |
552 | bool ) const; |
553 | SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; |
554 | SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; |
555 | SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; |
556 | SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; |
557 | SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; |
558 | SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG, |
559 | bool IsSRA) const; |
560 | SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const; |
561 | SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; |
562 | |
563 | /// isEligibleForTailCallOptimization - Check whether the call is eligible |
564 | /// for tail call optimization. |
565 | virtual bool |
566 | isEligibleForTailCallOptimization(const CCState &CCInfo, |
567 | unsigned NextStackOffset, |
568 | const MipsFunctionInfo &FI) const = 0; |
569 | |
570 | /// copyByValArg - Copy argument registers which were used to pass a byval |
571 | /// argument to the stack. Create a stack frame object for the byval |
572 | /// argument. |
573 | void copyByValRegs(SDValue Chain, const SDLoc &DL, |
574 | std::vector<SDValue> &OutChains, SelectionDAG &DAG, |
575 | const ISD::ArgFlagsTy &Flags, |
576 | SmallVectorImpl<SDValue> &InVals, |
577 | const Argument *FuncArg, unsigned FirstReg, |
578 | unsigned LastReg, const CCValAssign &VA, |
579 | MipsCCState &State) const; |
580 | |
581 | /// passByValArg - Pass a byval argument in registers or on stack. |
582 | void passByValArg(SDValue Chain, const SDLoc &DL, |
583 | std::deque<std::pair<unsigned, SDValue>> &RegsToPass, |
584 | SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, |
585 | MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg, |
586 | unsigned FirstReg, unsigned LastReg, |
587 | const ISD::ArgFlagsTy &Flags, bool isLittle, |
588 | const CCValAssign &VA) const; |
589 | |
590 | /// writeVarArgRegs - Write variable function arguments passed in registers |
591 | /// to the stack. Also create a stack frame object for the first variable |
592 | /// argument. |
593 | void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain, |
594 | const SDLoc &DL, SelectionDAG &DAG, |
595 | CCState &State) const; |
596 | |
597 | SDValue |
598 | LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
599 | const SmallVectorImpl<ISD::InputArg> &Ins, |
600 | const SDLoc &dl, SelectionDAG &DAG, |
601 | SmallVectorImpl<SDValue> &InVals) const override; |
602 | |
603 | SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, |
604 | SDValue Arg, const SDLoc &DL, bool IsTailCall, |
605 | SelectionDAG &DAG) const; |
606 | |
607 | SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, |
608 | SmallVectorImpl<SDValue> &InVals) const override; |
609 | |
610 | bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, |
611 | bool isVarArg, |
612 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
613 | LLVMContext &Context) const override; |
614 | |
615 | SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, |
616 | const SmallVectorImpl<ISD::OutputArg> &Outs, |
617 | const SmallVectorImpl<SDValue> &OutVals, |
618 | const SDLoc &dl, SelectionDAG &DAG) const override; |
619 | |
620 | SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, |
621 | const SDLoc &DL, SelectionDAG &DAG) const; |
622 | |
623 | bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override; |
624 | |
625 | // Inline asm support |
626 | ConstraintType getConstraintType(StringRef Constraint) const override; |
627 | |
628 | /// Examine constraint string and operand type and determine a weight value. |
629 | /// The operand object must already have been set up with the operand type. |
630 | ConstraintWeight getSingleConstraintMatchWeight( |
631 | AsmOperandInfo &info, const char *constraint) const override; |
632 | |
633 | /// This function parses registers that appear in inline-asm constraints. |
634 | /// It returns pair (0, 0) on failure. |
635 | std::pair<unsigned, const TargetRegisterClass *> |
636 | parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; |
637 | |
638 | std::pair<unsigned, const TargetRegisterClass *> |
639 | getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, |
640 | StringRef Constraint, MVT VT) const override; |
641 | |
642 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops |
643 | /// vector. If it is invalid, don't add anything to Ops. If hasMemory is |
644 | /// true it means one of the asm constraint of the inline asm instruction |
645 | /// being processed is 'm'. |
646 | void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, |
647 | std::vector<SDValue> &Ops, |
648 | SelectionDAG &DAG) const override; |
649 | |
650 | InlineAsm::ConstraintCode |
651 | getInlineAsmMemConstraint(StringRef ConstraintCode) const override { |
652 | if (ConstraintCode == "o" ) |
653 | return InlineAsm::ConstraintCode::o; |
654 | if (ConstraintCode == "R" ) |
655 | return InlineAsm::ConstraintCode::R; |
656 | if (ConstraintCode == "ZC" ) |
657 | return InlineAsm::ConstraintCode::ZC; |
658 | return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); |
659 | } |
660 | |
661 | bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, |
662 | Type *Ty, unsigned AS, |
663 | Instruction *I = nullptr) const override; |
664 | |
665 | bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; |
666 | |
667 | EVT getOptimalMemOpType(const MemOp &Op, |
668 | const AttributeList &FuncAttributes) const override; |
669 | |
670 | /// isFPImmLegal - Returns true if the target can instruction select the |
671 | /// specified FP immediate natively. If false, the legalizer will |
672 | /// materialize the FP immediate as a load from a constant pool. |
673 | bool isFPImmLegal(const APFloat &Imm, EVT VT, |
674 | bool ForCodeSize) const override; |
675 | |
676 | unsigned getJumpTableEncoding() const override; |
677 | bool useSoftFloat() const override; |
678 | |
679 | bool shouldInsertFencesForAtomic(const Instruction *I) const override { |
680 | return true; |
681 | } |
682 | |
683 | /// Emit a sign-extension using sll/sra, seb, or seh appropriately. |
684 | MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, |
685 | MachineBasicBlock *BB, |
686 | unsigned Size, unsigned DstReg, |
687 | unsigned SrcRec) const; |
688 | |
689 | MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, |
690 | MachineBasicBlock *BB) const; |
691 | MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, |
692 | MachineBasicBlock *BB, |
693 | unsigned Size) const; |
694 | MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, |
695 | MachineBasicBlock *BB) const; |
696 | MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, |
697 | MachineBasicBlock *BB, |
698 | unsigned Size) const; |
699 | MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const; |
700 | MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB, |
701 | bool isFPCmp, unsigned Opc) const; |
702 | MachineBasicBlock *emitPseudoD_SELECT(MachineInstr &MI, |
703 | MachineBasicBlock *BB) const; |
704 | MachineBasicBlock *emitLDR_W(MachineInstr &MI, MachineBasicBlock *BB) const; |
705 | MachineBasicBlock *emitLDR_D(MachineInstr &MI, MachineBasicBlock *BB) const; |
706 | MachineBasicBlock *emitSTR_W(MachineInstr &MI, MachineBasicBlock *BB) const; |
707 | MachineBasicBlock *emitSTR_D(MachineInstr &MI, MachineBasicBlock *BB) const; |
708 | }; |
709 | |
710 | /// Create MipsTargetLowering objects. |
711 | const MipsTargetLowering * |
712 | createMips16TargetLowering(const MipsTargetMachine &TM, |
713 | const MipsSubtarget &STI); |
714 | const MipsTargetLowering * |
715 | createMipsSETargetLowering(const MipsTargetMachine &TM, |
716 | const MipsSubtarget &STI); |
717 | |
718 | namespace Mips { |
719 | |
720 | FastISel *createFastISel(FunctionLoweringInfo &funcInfo, |
721 | const TargetLibraryInfo *libInfo); |
722 | |
723 | } // end namespace Mips |
724 | |
725 | } // end namespace llvm |
726 | |
727 | #endif // LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H |
728 | |