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