xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsISelLowering.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MipsISelLowering.h - Mips DAG Lowering Interface ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the interfaces that Mips uses to lower LLVM code into a
100b57cec5SDimitry Andric // selection DAG.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H
150b57cec5SDimitry Andric #define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
190b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h"
200b57cec5SDimitry Andric #include "Mips.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
28*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
290b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
300b57cec5SDimitry Andric #include "llvm/IR/InlineAsm.h"
310b57cec5SDimitry Andric #include "llvm/IR/Type.h"
320b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
330b57cec5SDimitry Andric #include <algorithm>
340b57cec5SDimitry Andric #include <deque>
350b57cec5SDimitry Andric #include <utility>
360b57cec5SDimitry Andric #include <vector>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace llvm {
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric class Argument;
410b57cec5SDimitry Andric class FastISel;
420b57cec5SDimitry Andric class FunctionLoweringInfo;
430b57cec5SDimitry Andric class MachineBasicBlock;
440b57cec5SDimitry Andric class MachineFrameInfo;
450b57cec5SDimitry Andric class MachineInstr;
460b57cec5SDimitry Andric class MipsCCState;
470b57cec5SDimitry Andric class MipsFunctionInfo;
480b57cec5SDimitry Andric class MipsSubtarget;
490b57cec5SDimitry Andric class MipsTargetMachine;
500b57cec5SDimitry Andric class TargetLibraryInfo;
510b57cec5SDimitry Andric class TargetRegisterClass;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   namespace MipsISD {
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric     enum NodeType : unsigned {
560b57cec5SDimitry Andric       // Start the numbering from where ISD NodeType finishes.
570b57cec5SDimitry Andric       FIRST_NUMBER = ISD::BUILTIN_OP_END,
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric       // Jump and link (call)
600b57cec5SDimitry Andric       JmpLink,
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric       // Tail call
630b57cec5SDimitry Andric       TailCall,
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric       // Get the Highest (63-48) 16 bits from a 64-bit immediate
660b57cec5SDimitry Andric       Highest,
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric       // Get the Higher (47-32) 16 bits from a 64-bit immediate
690b57cec5SDimitry Andric       Higher,
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric       // Get the High 16 bits from a 32/64-bit immediate
720b57cec5SDimitry Andric       // No relation with Mips Hi register
730b57cec5SDimitry Andric       Hi,
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric       // Get the Lower 16 bits from a 32/64-bit immediate
760b57cec5SDimitry Andric       // No relation with Mips Lo register
770b57cec5SDimitry Andric       Lo,
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric       // Get the High 16 bits from a 32 bit immediate for accessing the GOT.
800b57cec5SDimitry Andric       GotHi,
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric       // Get the High 16 bits from a 32-bit immediate for accessing TLS.
830b57cec5SDimitry Andric       TlsHi,
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric       // Handle gp_rel (small data/bss sections) relocation.
860b57cec5SDimitry Andric       GPRel,
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric       // Thread Pointer
890b57cec5SDimitry Andric       ThreadPointer,
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric       // Vector Floating Point Multiply and Subtract
920b57cec5SDimitry Andric       FMS,
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric       // Floating Point Branch Conditional
950b57cec5SDimitry Andric       FPBrcond,
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric       // Floating Point Compare
980b57cec5SDimitry Andric       FPCmp,
990b57cec5SDimitry Andric 
10056f451bbSDimitry Andric       // Floating point Abs
10156f451bbSDimitry Andric       FAbs,
10256f451bbSDimitry Andric 
1030b57cec5SDimitry Andric       // Floating point select
1040b57cec5SDimitry Andric       FSELECT,
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric       // Node used to generate an MTC1 i32 to f64 instruction
1070b57cec5SDimitry Andric       MTC1_D64,
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric       // Floating Point Conditional Moves
1100b57cec5SDimitry Andric       CMovFP_T,
1110b57cec5SDimitry Andric       CMovFP_F,
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric       // FP-to-int truncation node.
1140b57cec5SDimitry Andric       TruncIntFP,
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric       // Return
1170b57cec5SDimitry Andric       Ret,
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric       // Interrupt, exception, error trap Return
1200b57cec5SDimitry Andric       ERet,
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric       // Software Exception Return.
1230b57cec5SDimitry Andric       EH_RETURN,
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric       // Node used to extract integer from accumulator.
1260b57cec5SDimitry Andric       MFHI,
1270b57cec5SDimitry Andric       MFLO,
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric       // Node used to insert integers to accumulator.
1300b57cec5SDimitry Andric       MTLOHI,
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric       // Mult nodes.
1330b57cec5SDimitry Andric       Mult,
1340b57cec5SDimitry Andric       Multu,
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric       // MAdd/Sub nodes
1370b57cec5SDimitry Andric       MAdd,
1380b57cec5SDimitry Andric       MAddu,
1390b57cec5SDimitry Andric       MSub,
1400b57cec5SDimitry Andric       MSubu,
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric       // DivRem(u)
1430b57cec5SDimitry Andric       DivRem,
1440b57cec5SDimitry Andric       DivRemU,
1450b57cec5SDimitry Andric       DivRem16,
1460b57cec5SDimitry Andric       DivRemU16,
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric       BuildPairF64,
1490b57cec5SDimitry Andric       ExtractElementF64,
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric       Wrapper,
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric       DynAlloc,
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric       Sync,
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric       Ext,
1580b57cec5SDimitry Andric       Ins,
1590b57cec5SDimitry Andric       CIns,
1600b57cec5SDimitry Andric 
16181ad6265SDimitry Andric       // EXTR.W intrinsic nodes.
1620b57cec5SDimitry Andric       EXTP,
1630b57cec5SDimitry Andric       EXTPDP,
1640b57cec5SDimitry Andric       EXTR_S_H,
1650b57cec5SDimitry Andric       EXTR_W,
1660b57cec5SDimitry Andric       EXTR_R_W,
1670b57cec5SDimitry Andric       EXTR_RS_W,
1680b57cec5SDimitry Andric       SHILO,
1690b57cec5SDimitry Andric       MTHLIP,
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric       // DPA.W intrinsic nodes.
1720b57cec5SDimitry Andric       MULSAQ_S_W_PH,
1730b57cec5SDimitry Andric       MAQ_S_W_PHL,
1740b57cec5SDimitry Andric       MAQ_S_W_PHR,
1750b57cec5SDimitry Andric       MAQ_SA_W_PHL,
1760b57cec5SDimitry Andric       MAQ_SA_W_PHR,
1770b57cec5SDimitry Andric       DPAU_H_QBL,
1780b57cec5SDimitry Andric       DPAU_H_QBR,
1790b57cec5SDimitry Andric       DPSU_H_QBL,
1800b57cec5SDimitry Andric       DPSU_H_QBR,
1810b57cec5SDimitry Andric       DPAQ_S_W_PH,
1820b57cec5SDimitry Andric       DPSQ_S_W_PH,
1830b57cec5SDimitry Andric       DPAQ_SA_L_W,
1840b57cec5SDimitry Andric       DPSQ_SA_L_W,
1850b57cec5SDimitry Andric       DPA_W_PH,
1860b57cec5SDimitry Andric       DPS_W_PH,
1870b57cec5SDimitry Andric       DPAQX_S_W_PH,
1880b57cec5SDimitry Andric       DPAQX_SA_W_PH,
1890b57cec5SDimitry Andric       DPAX_W_PH,
1900b57cec5SDimitry Andric       DPSX_W_PH,
1910b57cec5SDimitry Andric       DPSQX_S_W_PH,
1920b57cec5SDimitry Andric       DPSQX_SA_W_PH,
1930b57cec5SDimitry Andric       MULSA_W_PH,
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric       MULT,
1960b57cec5SDimitry Andric       MULTU,
1970b57cec5SDimitry Andric       MADD_DSP,
1980b57cec5SDimitry Andric       MADDU_DSP,
1990b57cec5SDimitry Andric       MSUB_DSP,
2000b57cec5SDimitry Andric       MSUBU_DSP,
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric       // DSP shift nodes.
2030b57cec5SDimitry Andric       SHLL_DSP,
2040b57cec5SDimitry Andric       SHRA_DSP,
2050b57cec5SDimitry Andric       SHRL_DSP,
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric       // DSP setcc and select_cc nodes.
2080b57cec5SDimitry Andric       SETCC_DSP,
2090b57cec5SDimitry Andric       SELECT_CC_DSP,
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric       // Vector comparisons.
2120b57cec5SDimitry Andric       // These take a vector and return a boolean.
2130b57cec5SDimitry Andric       VALL_ZERO,
2140b57cec5SDimitry Andric       VANY_ZERO,
2150b57cec5SDimitry Andric       VALL_NONZERO,
2160b57cec5SDimitry Andric       VANY_NONZERO,
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric       // These take a vector and return a vector bitmask.
2190b57cec5SDimitry Andric       VCEQ,
2200b57cec5SDimitry Andric       VCLE_S,
2210b57cec5SDimitry Andric       VCLE_U,
2220b57cec5SDimitry Andric       VCLT_S,
2230b57cec5SDimitry Andric       VCLT_U,
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric       // Vector Shuffle with mask as an operand
2260b57cec5SDimitry Andric       VSHF,  // Generic shuffle
2270b57cec5SDimitry Andric       SHF,   // 4-element set shuffle.
2280b57cec5SDimitry Andric       ILVEV, // Interleave even elements
2290b57cec5SDimitry Andric       ILVOD, // Interleave odd elements
2300b57cec5SDimitry Andric       ILVL,  // Interleave left elements
2310b57cec5SDimitry Andric       ILVR,  // Interleave right elements
2320b57cec5SDimitry Andric       PCKEV, // Pack even elements
2330b57cec5SDimitry Andric       PCKOD, // Pack odd elements
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric       // Vector Lane Copy
2360b57cec5SDimitry Andric       INSVE, // Copy element from one vector to another
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric       // Combined (XOR (OR $a, $b), -1)
2390b57cec5SDimitry Andric       VNOR,
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric       // Extended vector element extraction
2420b57cec5SDimitry Andric       VEXTRACT_SEXT_ELT,
2430b57cec5SDimitry Andric       VEXTRACT_ZEXT_ELT,
2440b57cec5SDimitry Andric 
245*0fca6ea1SDimitry Andric       // Double select nodes for machines without conditional-move.
246*0fca6ea1SDimitry Andric       DOUBLE_SELECT_I,
247*0fca6ea1SDimitry Andric       DOUBLE_SELECT_I64,
248*0fca6ea1SDimitry Andric 
2490b57cec5SDimitry Andric       // Load/Store Left/Right nodes.
2500b57cec5SDimitry Andric       LWL = ISD::FIRST_TARGET_MEMORY_OPCODE,
2510b57cec5SDimitry Andric       LWR,
2520b57cec5SDimitry Andric       SWL,
2530b57cec5SDimitry Andric       SWR,
2540b57cec5SDimitry Andric       LDL,
2550b57cec5SDimitry Andric       LDR,
2560b57cec5SDimitry Andric       SDL,
2570b57cec5SDimitry Andric       SDR
2580b57cec5SDimitry Andric     };
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   } // ene namespace MipsISD
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
2630b57cec5SDimitry Andric   // TargetLowering Implementation
2640b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   class MipsTargetLowering : public TargetLowering  {
2670b57cec5SDimitry Andric     bool isMicroMips;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   public:
2700b57cec5SDimitry Andric     explicit MipsTargetLowering(const MipsTargetMachine &TM,
2710b57cec5SDimitry Andric                                 const MipsSubtarget &STI);
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric     static const MipsTargetLowering *create(const MipsTargetMachine &TM,
2740b57cec5SDimitry Andric                                             const MipsSubtarget &STI);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     /// createFastISel - This method returns a target specific FastISel object,
2770b57cec5SDimitry Andric     /// or null if the target does not support "fast" ISel.
2780b57cec5SDimitry Andric     FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
2790b57cec5SDimitry Andric                              const TargetLibraryInfo *libInfo) const override;
2800b57cec5SDimitry Andric 
getScalarShiftAmountTy(const DataLayout &,EVT)2810b57cec5SDimitry Andric     MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override {
2820b57cec5SDimitry Andric       return MVT::i32;
2830b57cec5SDimitry Andric     }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     EVT getTypeForExtReturn(LLVMContext &Context, EVT VT,
2860b57cec5SDimitry Andric                             ISD::NodeType) const override;
2870b57cec5SDimitry Andric 
288bdd1243dSDimitry Andric     bool isCheapToSpeculateCttz(Type *Ty) const override;
289bdd1243dSDimitry Andric     bool isCheapToSpeculateCtlz(Type *Ty) const override;
29081ad6265SDimitry Andric     bool hasBitTest(SDValue X, SDValue Y) const override;
2910b57cec5SDimitry Andric     bool shouldFoldConstantShiftPairToMask(const SDNode *N,
2920b57cec5SDimitry Andric                                            CombineLevel Level) const override;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric     /// Return the register type for a given MVT, ensuring vectors are treated
2950b57cec5SDimitry Andric     /// as a series of gpr sized integers.
2960b57cec5SDimitry Andric     MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
2970b57cec5SDimitry Andric                                       EVT VT) const override;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric     /// Return the number of registers for a given MVT, ensuring vectors are
3000b57cec5SDimitry Andric     /// treated as a series of gpr sized integers.
3010b57cec5SDimitry Andric     unsigned getNumRegistersForCallingConv(LLVMContext &Context,
3020b57cec5SDimitry Andric                                            CallingConv::ID CC,
3030b57cec5SDimitry Andric                                            EVT VT) const override;
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric     /// Break down vectors to the correct number of gpr sized integers.
3060b57cec5SDimitry Andric     unsigned getVectorTypeBreakdownForCallingConv(
3070b57cec5SDimitry Andric         LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
3080b57cec5SDimitry Andric         unsigned &NumIntermediates, MVT &RegisterVT) const override;
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric     /// Return the correct alignment for the current calling convention.
getABIAlignmentForCallingConv(Type * ArgTy,const DataLayout & DL)3118bcb0991SDimitry Andric     Align getABIAlignmentForCallingConv(Type *ArgTy,
312fe6060f1SDimitry Andric                                         const DataLayout &DL) const override {
3135ffd83dbSDimitry Andric       const Align ABIAlign = DL.getABITypeAlign(ArgTy);
3140b57cec5SDimitry Andric       if (ArgTy->isVectorTy())
3158bcb0991SDimitry Andric         return std::min(ABIAlign, Align(8));
3168bcb0991SDimitry Andric       return ABIAlign;
3170b57cec5SDimitry Andric     }
3180b57cec5SDimitry Andric 
getExtendForAtomicOps()3190b57cec5SDimitry Andric     ISD::NodeType getExtendForAtomicOps() const override {
3200b57cec5SDimitry Andric       return ISD::SIGN_EXTEND;
3210b57cec5SDimitry Andric     }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric     /// LowerOperation - Provide custom lowering hooks for some operations.
3240b57cec5SDimitry Andric     SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric     /// ReplaceNodeResults - Replace the results of node with an illegal result
3270b57cec5SDimitry Andric     /// type with new values built out of custom code.
3280b57cec5SDimitry Andric     ///
3290b57cec5SDimitry Andric     void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
3300b57cec5SDimitry Andric                             SelectionDAG &DAG) const override;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric     /// getTargetNodeName - This method returns the name of a target specific
3330b57cec5SDimitry Andric     //  DAG node.
3340b57cec5SDimitry Andric     const char *getTargetNodeName(unsigned Opcode) const override;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     /// getSetCCResultType - get the ISD::SETCC result ValueType
3370b57cec5SDimitry Andric     EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
3380b57cec5SDimitry Andric                            EVT VT) const override;
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric     SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric     MachineBasicBlock *
3430b57cec5SDimitry Andric     EmitInstrWithCustomInserter(MachineInstr &MI,
3440b57cec5SDimitry Andric                                 MachineBasicBlock *MBB) const override;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric     void AdjustInstrPostInstrSelection(MachineInstr &MI,
3470b57cec5SDimitry Andric                                        SDNode *Node) const override;
3480b57cec5SDimitry Andric 
3495ffd83dbSDimitry Andric     void HandleByVal(CCState *, unsigned &, Align) const override;
3500b57cec5SDimitry Andric 
351480093f4SDimitry Andric     Register getRegisterByName(const char* RegName, LLT VT,
3528bcb0991SDimitry Andric                                const MachineFunction &MF) const override;
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric     /// If a physical register, this returns the register that receives the
3550b57cec5SDimitry Andric     /// exception address on entry to an EH pad.
3565ffd83dbSDimitry Andric     Register
getExceptionPointerRegister(const Constant * PersonalityFn)3570b57cec5SDimitry Andric     getExceptionPointerRegister(const Constant *PersonalityFn) const override {
3580b57cec5SDimitry Andric       return ABI.IsN64() ? Mips::A0_64 : Mips::A0;
3590b57cec5SDimitry Andric     }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric     /// If a physical register, this returns the register that receives the
3620b57cec5SDimitry Andric     /// exception typeid on entry to a landing pad.
3635ffd83dbSDimitry Andric     Register
getExceptionSelectorRegister(const Constant * PersonalityFn)3640b57cec5SDimitry Andric     getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
3650b57cec5SDimitry Andric       return ABI.IsN64() ? Mips::A1_64 : Mips::A1;
3660b57cec5SDimitry Andric     }
3670b57cec5SDimitry Andric 
isJumpTableRelative()3680b57cec5SDimitry Andric     bool isJumpTableRelative() const override {
3690b57cec5SDimitry Andric       return getTargetMachine().isPositionIndependent();
3700b57cec5SDimitry Andric     }
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric    CCAssignFn *CCAssignFnForCall() const;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric    CCAssignFn *CCAssignFnForReturn() const;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   protected:
3770b57cec5SDimitry Andric     SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric     // This method creates the following nodes, which are necessary for
3800b57cec5SDimitry Andric     // computing a local symbol's address:
3810b57cec5SDimitry Andric     //
3820b57cec5SDimitry Andric     // (add (load (wrapper $gp, %got(sym)), %lo(sym))
3830b57cec5SDimitry Andric     template <class NodeTy>
getAddrLocal(NodeTy * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG,bool IsN32OrN64)3840b57cec5SDimitry Andric     SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG,
3850b57cec5SDimitry Andric                          bool IsN32OrN64) const {
3860b57cec5SDimitry Andric       unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
3870b57cec5SDimitry Andric       SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty),
3880b57cec5SDimitry Andric                                 getTargetNode(N, Ty, DAG, GOTFlag));
3890b57cec5SDimitry Andric       SDValue Load =
3900b57cec5SDimitry Andric           DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT,
3910b57cec5SDimitry Andric                       MachinePointerInfo::getGOT(DAG.getMachineFunction()));
3920b57cec5SDimitry Andric       unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
3930b57cec5SDimitry Andric       SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty,
3940b57cec5SDimitry Andric                                getTargetNode(N, Ty, DAG, LoFlag));
3950b57cec5SDimitry Andric       return DAG.getNode(ISD::ADD, DL, Ty, Load, Lo);
3960b57cec5SDimitry Andric     }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     // This method creates the following nodes, which are necessary for
3990b57cec5SDimitry Andric     // computing a global symbol's address:
4000b57cec5SDimitry Andric     //
4010b57cec5SDimitry Andric     // (load (wrapper $gp, %got(sym)))
4020b57cec5SDimitry Andric     template <class NodeTy>
getAddrGlobal(NodeTy * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG,unsigned Flag,SDValue Chain,const MachinePointerInfo & PtrInfo)4030b57cec5SDimitry Andric     SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG,
4040b57cec5SDimitry Andric                           unsigned Flag, SDValue Chain,
4050b57cec5SDimitry Andric                           const MachinePointerInfo &PtrInfo) const {
4060b57cec5SDimitry Andric       SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty),
4070b57cec5SDimitry Andric                                 getTargetNode(N, Ty, DAG, Flag));
4080b57cec5SDimitry Andric       return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo);
4090b57cec5SDimitry Andric     }
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     // This method creates the following nodes, which are necessary for
4120b57cec5SDimitry Andric     // computing a global symbol's address in large-GOT mode:
4130b57cec5SDimitry Andric     //
4140b57cec5SDimitry Andric     // (load (wrapper (add %hi(sym), $gp), %lo(sym)))
4150b57cec5SDimitry Andric     template <class NodeTy>
getAddrGlobalLargeGOT(NodeTy * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG,unsigned HiFlag,unsigned LoFlag,SDValue Chain,const MachinePointerInfo & PtrInfo)4160b57cec5SDimitry Andric     SDValue getAddrGlobalLargeGOT(NodeTy *N, const SDLoc &DL, EVT Ty,
4170b57cec5SDimitry Andric                                   SelectionDAG &DAG, unsigned HiFlag,
4180b57cec5SDimitry Andric                                   unsigned LoFlag, SDValue Chain,
4190b57cec5SDimitry Andric                                   const MachinePointerInfo &PtrInfo) const {
4200b57cec5SDimitry Andric       SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty,
4210b57cec5SDimitry Andric                                getTargetNode(N, Ty, DAG, HiFlag));
4220b57cec5SDimitry Andric       Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty));
4230b57cec5SDimitry Andric       SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi,
4240b57cec5SDimitry Andric                                     getTargetNode(N, Ty, DAG, LoFlag));
4250b57cec5SDimitry Andric       return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo);
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     // This method creates the following nodes, which are necessary for
4290b57cec5SDimitry Andric     // computing a symbol's address in non-PIC mode:
4300b57cec5SDimitry Andric     //
4310b57cec5SDimitry Andric     // (add %hi(sym), %lo(sym))
4320b57cec5SDimitry Andric     //
4330b57cec5SDimitry Andric     // This method covers O32, N32 and N64 in sym32 mode.
4340b57cec5SDimitry Andric     template <class NodeTy>
getAddrNonPIC(NodeTy * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG)4350b57cec5SDimitry Andric     SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty,
4360b57cec5SDimitry Andric                           SelectionDAG &DAG) const {
4370b57cec5SDimitry Andric       SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI);
4380b57cec5SDimitry Andric       SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO);
4390b57cec5SDimitry Andric       return DAG.getNode(ISD::ADD, DL, Ty,
4400b57cec5SDimitry Andric                          DAG.getNode(MipsISD::Hi, DL, Ty, Hi),
4410b57cec5SDimitry Andric                          DAG.getNode(MipsISD::Lo, DL, Ty, Lo));
4420b57cec5SDimitry Andric    }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric    // This method creates the following nodes, which are necessary for
4450b57cec5SDimitry Andric    // computing a symbol's address in non-PIC mode for N64.
4460b57cec5SDimitry Andric    //
4470b57cec5SDimitry Andric    // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)),
4480b57cec5SDimitry Andric    //            16), %lo(%sym))
4490b57cec5SDimitry Andric    //
4500b57cec5SDimitry Andric    // FIXME: This method is not efficent for (micro)MIPS64R6.
4510b57cec5SDimitry Andric    template <class NodeTy>
getAddrNonPICSym64(NodeTy * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG)4520b57cec5SDimitry Andric    SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty,
4530b57cec5SDimitry Andric                           SelectionDAG &DAG) const {
4540b57cec5SDimitry Andric       SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI);
4550b57cec5SDimitry Andric       SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO);
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric       SDValue Highest =
4580b57cec5SDimitry Andric           DAG.getNode(MipsISD::Highest, DL, Ty,
4590b57cec5SDimitry Andric                       getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST));
4600b57cec5SDimitry Andric       SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER);
4610b57cec5SDimitry Andric       SDValue HigherPart =
4620b57cec5SDimitry Andric           DAG.getNode(ISD::ADD, DL, Ty, Highest,
4630b57cec5SDimitry Andric                       DAG.getNode(MipsISD::Higher, DL, Ty, Higher));
4640b57cec5SDimitry Andric       SDValue Cst = DAG.getConstant(16, DL, MVT::i32);
4650b57cec5SDimitry Andric       SDValue Shift = DAG.getNode(ISD::SHL, DL, Ty, HigherPart, Cst);
4660b57cec5SDimitry Andric       SDValue Add = DAG.getNode(ISD::ADD, DL, Ty, Shift,
4670b57cec5SDimitry Andric                                 DAG.getNode(MipsISD::Hi, DL, Ty, Hi));
4680b57cec5SDimitry Andric       SDValue Shift2 = DAG.getNode(ISD::SHL, DL, Ty, Add, Cst);
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric       return DAG.getNode(ISD::ADD, DL, Ty, Shift2,
4710b57cec5SDimitry Andric                          DAG.getNode(MipsISD::Lo, DL, Ty, Lo));
4720b57cec5SDimitry Andric    }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric     // This method creates the following nodes, which are necessary for
4750b57cec5SDimitry Andric     // computing a symbol's address using gp-relative addressing:
4760b57cec5SDimitry Andric     //
4770b57cec5SDimitry Andric     // (add $gp, %gp_rel(sym))
4780b57cec5SDimitry Andric     template <class NodeTy>
getAddrGPRel(NodeTy * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG,bool IsN64)4790b57cec5SDimitry Andric     SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty,
4800b57cec5SDimitry Andric                          SelectionDAG &DAG, bool IsN64) const {
4810b57cec5SDimitry Andric       SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL);
4820b57cec5SDimitry Andric       return DAG.getNode(
4830b57cec5SDimitry Andric           ISD::ADD, DL, Ty,
4840b57cec5SDimitry Andric           DAG.getRegister(IsN64 ? Mips::GP_64 : Mips::GP, Ty),
4850b57cec5SDimitry Andric           DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), GPRel));
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric     /// This function fills Ops, which is the list of operands that will later
4890b57cec5SDimitry Andric     /// be used when a function call node is created. It also generates
4900b57cec5SDimitry Andric     /// copyToReg nodes to set up argument registers.
4910b57cec5SDimitry Andric     virtual void
4920b57cec5SDimitry Andric     getOpndList(SmallVectorImpl<SDValue> &Ops,
4930b57cec5SDimitry Andric                 std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
4940b57cec5SDimitry Andric                 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
4950b57cec5SDimitry Andric                 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
4960b57cec5SDimitry Andric                 SDValue Chain) const;
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   protected:
4990b57cec5SDimitry Andric     SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
5000b57cec5SDimitry Andric     SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric     // Subtarget Info
5030b57cec5SDimitry Andric     const MipsSubtarget &Subtarget;
5040b57cec5SDimitry Andric     // Cache the ABI from the TargetMachine, we use it everywhere.
5050b57cec5SDimitry Andric     const MipsABIInfo &ABI;
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   private:
5080b57cec5SDimitry Andric     // Create a TargetGlobalAddress node.
5090b57cec5SDimitry Andric     SDValue getTargetNode(GlobalAddressSDNode *N, EVT Ty, SelectionDAG &DAG,
5100b57cec5SDimitry Andric                           unsigned Flag) const;
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric     // Create a TargetExternalSymbol node.
5130b57cec5SDimitry Andric     SDValue getTargetNode(ExternalSymbolSDNode *N, EVT Ty, SelectionDAG &DAG,
5140b57cec5SDimitry Andric                           unsigned Flag) const;
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric     // Create a TargetBlockAddress node.
5170b57cec5SDimitry Andric     SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG,
5180b57cec5SDimitry Andric                           unsigned Flag) const;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric     // Create a TargetJumpTable node.
5210b57cec5SDimitry Andric     SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG,
5220b57cec5SDimitry Andric                           unsigned Flag) const;
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     // Create a TargetConstantPool node.
5250b57cec5SDimitry Andric     SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG,
5260b57cec5SDimitry Andric                           unsigned Flag) const;
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric     // Lower Operand helpers
52906c3fb27SDimitry Andric     SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
5300b57cec5SDimitry Andric                             CallingConv::ID CallConv, bool isVarArg,
5310b57cec5SDimitry Andric                             const SmallVectorImpl<ISD::InputArg> &Ins,
5320b57cec5SDimitry Andric                             const SDLoc &dl, SelectionDAG &DAG,
5330b57cec5SDimitry Andric                             SmallVectorImpl<SDValue> &InVals,
5340b57cec5SDimitry Andric                             TargetLowering::CallLoweringInfo &CLI) const;
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric     // Lower Operand specifics
5370b57cec5SDimitry Andric     SDValue lowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
5380b57cec5SDimitry Andric     SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
5390b57cec5SDimitry Andric     SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
5400b57cec5SDimitry Andric     SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
5410b57cec5SDimitry Andric     SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
5420b57cec5SDimitry Andric     SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
5430b57cec5SDimitry Andric     SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;
5440b57cec5SDimitry Andric     SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const;
5450b57cec5SDimitry Andric     SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
5460b57cec5SDimitry Andric     SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const;
5470b57cec5SDimitry Andric     SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
5480b57cec5SDimitry Andric     SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const;
54956f451bbSDimitry Andric     SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG,
55056f451bbSDimitry Andric                         bool HasExtractInsert) const;
55156f451bbSDimitry Andric     SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG,
55256f451bbSDimitry Andric                         bool HasExtractInsert) const;
5530b57cec5SDimitry Andric     SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
5540b57cec5SDimitry Andric     SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
5550b57cec5SDimitry Andric     SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
5560b57cec5SDimitry Andric     SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
5570b57cec5SDimitry Andric     SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const;
5580b57cec5SDimitry Andric     SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG,
5590b57cec5SDimitry Andric                                  bool IsSRA) const;
5600b57cec5SDimitry Andric     SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
5610b57cec5SDimitry Andric     SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric     /// isEligibleForTailCallOptimization - Check whether the call is eligible
5640b57cec5SDimitry Andric     /// for tail call optimization.
5650b57cec5SDimitry Andric     virtual bool
5660b57cec5SDimitry Andric     isEligibleForTailCallOptimization(const CCState &CCInfo,
5670b57cec5SDimitry Andric                                       unsigned NextStackOffset,
5680b57cec5SDimitry Andric                                       const MipsFunctionInfo &FI) const = 0;
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric     /// copyByValArg - Copy argument registers which were used to pass a byval
5710b57cec5SDimitry Andric     /// argument to the stack. Create a stack frame object for the byval
5720b57cec5SDimitry Andric     /// argument.
5730b57cec5SDimitry Andric     void copyByValRegs(SDValue Chain, const SDLoc &DL,
5740b57cec5SDimitry Andric                        std::vector<SDValue> &OutChains, SelectionDAG &DAG,
5750b57cec5SDimitry Andric                        const ISD::ArgFlagsTy &Flags,
5760b57cec5SDimitry Andric                        SmallVectorImpl<SDValue> &InVals,
5770b57cec5SDimitry Andric                        const Argument *FuncArg, unsigned FirstReg,
5780b57cec5SDimitry Andric                        unsigned LastReg, const CCValAssign &VA,
5790b57cec5SDimitry Andric                        MipsCCState &State) const;
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric     /// passByValArg - Pass a byval argument in registers or on stack.
5820b57cec5SDimitry Andric     void passByValArg(SDValue Chain, const SDLoc &DL,
5830b57cec5SDimitry Andric                       std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
5840b57cec5SDimitry Andric                       SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr,
5850b57cec5SDimitry Andric                       MachineFrameInfo &MFI, SelectionDAG &DAG, SDValue Arg,
5860b57cec5SDimitry Andric                       unsigned FirstReg, unsigned LastReg,
5870b57cec5SDimitry Andric                       const ISD::ArgFlagsTy &Flags, bool isLittle,
5880b57cec5SDimitry Andric                       const CCValAssign &VA) const;
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric     /// writeVarArgRegs - Write variable function arguments passed in registers
5910b57cec5SDimitry Andric     /// to the stack. Also create a stack frame object for the first variable
5920b57cec5SDimitry Andric     /// argument.
5930b57cec5SDimitry Andric     void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain,
5940b57cec5SDimitry Andric                          const SDLoc &DL, SelectionDAG &DAG,
5950b57cec5SDimitry Andric                          CCState &State) const;
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric     SDValue
5980b57cec5SDimitry Andric     LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
5990b57cec5SDimitry Andric                          const SmallVectorImpl<ISD::InputArg> &Ins,
6000b57cec5SDimitry Andric                          const SDLoc &dl, SelectionDAG &DAG,
6010b57cec5SDimitry Andric                          SmallVectorImpl<SDValue> &InVals) const override;
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric     SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain,
6040b57cec5SDimitry Andric                            SDValue Arg, const SDLoc &DL, bool IsTailCall,
6050b57cec5SDimitry Andric                            SelectionDAG &DAG) const;
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric     SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
6080b57cec5SDimitry Andric                       SmallVectorImpl<SDValue> &InVals) const override;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric     bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
6110b57cec5SDimitry Andric                         bool isVarArg,
6120b57cec5SDimitry Andric                         const SmallVectorImpl<ISD::OutputArg> &Outs,
6130b57cec5SDimitry Andric                         LLVMContext &Context) const override;
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric     SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
6160b57cec5SDimitry Andric                         const SmallVectorImpl<ISD::OutputArg> &Outs,
6170b57cec5SDimitry Andric                         const SmallVectorImpl<SDValue> &OutVals,
6180b57cec5SDimitry Andric                         const SDLoc &dl, SelectionDAG &DAG) const override;
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric     SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps,
6210b57cec5SDimitry Andric                                  const SDLoc &DL, SelectionDAG &DAG) const;
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric     bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override;
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric     // Inline asm support
6260b57cec5SDimitry Andric     ConstraintType getConstraintType(StringRef Constraint) const override;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric     /// Examine constraint string and operand type and determine a weight value.
6290b57cec5SDimitry Andric     /// The operand object must already have been set up with the operand type.
6300b57cec5SDimitry Andric     ConstraintWeight getSingleConstraintMatchWeight(
6310b57cec5SDimitry Andric       AsmOperandInfo &info, const char *constraint) const override;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric     /// This function parses registers that appear in inline-asm constraints.
6340b57cec5SDimitry Andric     /// It returns pair (0, 0) on failure.
6350b57cec5SDimitry Andric     std::pair<unsigned, const TargetRegisterClass *>
6360b57cec5SDimitry Andric     parseRegForInlineAsmConstraint(StringRef C, MVT VT) const;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric     std::pair<unsigned, const TargetRegisterClass *>
6390b57cec5SDimitry Andric     getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
6400b57cec5SDimitry Andric                                  StringRef Constraint, MVT VT) const override;
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric     /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
6430b57cec5SDimitry Andric     /// vector.  If it is invalid, don't add anything to Ops. If hasMemory is
6440b57cec5SDimitry Andric     /// true it means one of the asm constraint of the inline asm instruction
6450b57cec5SDimitry Andric     /// being processed is 'm'.
6465f757f3fSDimitry Andric     void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
6470b57cec5SDimitry Andric                                       std::vector<SDValue> &Ops,
6480b57cec5SDimitry Andric                                       SelectionDAG &DAG) const override;
6490b57cec5SDimitry Andric 
6505f757f3fSDimitry Andric     InlineAsm::ConstraintCode
getInlineAsmMemConstraint(StringRef ConstraintCode)6510b57cec5SDimitry Andric     getInlineAsmMemConstraint(StringRef ConstraintCode) const override {
6520b57cec5SDimitry Andric       if (ConstraintCode == "o")
6535f757f3fSDimitry Andric         return InlineAsm::ConstraintCode::o;
6540b57cec5SDimitry Andric       if (ConstraintCode == "R")
6555f757f3fSDimitry Andric         return InlineAsm::ConstraintCode::R;
6560b57cec5SDimitry Andric       if (ConstraintCode == "ZC")
6575f757f3fSDimitry Andric         return InlineAsm::ConstraintCode::ZC;
6580b57cec5SDimitry Andric       return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
6590b57cec5SDimitry Andric     }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric     bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM,
6620b57cec5SDimitry Andric                                Type *Ty, unsigned AS,
6630b57cec5SDimitry Andric                                Instruction *I = nullptr) const override;
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric     bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
6660b57cec5SDimitry Andric 
6675ffd83dbSDimitry Andric     EVT getOptimalMemOpType(const MemOp &Op,
6680b57cec5SDimitry Andric                             const AttributeList &FuncAttributes) const override;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric     /// isFPImmLegal - Returns true if the target can instruction select the
6710b57cec5SDimitry Andric     /// specified FP immediate natively. If false, the legalizer will
6720b57cec5SDimitry Andric     /// materialize the FP immediate as a load from a constant pool.
6730b57cec5SDimitry Andric     bool isFPImmLegal(const APFloat &Imm, EVT VT,
6740b57cec5SDimitry Andric                       bool ForCodeSize) const override;
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     unsigned getJumpTableEncoding() const override;
6770b57cec5SDimitry Andric     bool useSoftFloat() const override;
6780b57cec5SDimitry Andric 
shouldInsertFencesForAtomic(const Instruction * I)6790b57cec5SDimitry Andric     bool shouldInsertFencesForAtomic(const Instruction *I) const override {
6800b57cec5SDimitry Andric       return true;
6810b57cec5SDimitry Andric     }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric     /// Emit a sign-extension using sll/sra, seb, or seh appropriately.
6840b57cec5SDimitry Andric     MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI,
6850b57cec5SDimitry Andric                                                 MachineBasicBlock *BB,
6860b57cec5SDimitry Andric                                                 unsigned Size, unsigned DstReg,
6870b57cec5SDimitry Andric                                                 unsigned SrcRec) const;
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric     MachineBasicBlock *emitAtomicBinary(MachineInstr &MI,
6900b57cec5SDimitry Andric                                         MachineBasicBlock *BB) const;
6910b57cec5SDimitry Andric     MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI,
6920b57cec5SDimitry Andric                                                 MachineBasicBlock *BB,
6930b57cec5SDimitry Andric                                                 unsigned Size) const;
6940b57cec5SDimitry Andric     MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI,
6950b57cec5SDimitry Andric                                          MachineBasicBlock *BB) const;
6960b57cec5SDimitry Andric     MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI,
6970b57cec5SDimitry Andric                                                  MachineBasicBlock *BB,
6980b57cec5SDimitry Andric                                                  unsigned Size) const;
6990b57cec5SDimitry Andric     MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const;
7000b57cec5SDimitry Andric     MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB,
7010b57cec5SDimitry Andric                                         bool isFPCmp, unsigned Opc) const;
7020b57cec5SDimitry Andric     MachineBasicBlock *emitPseudoD_SELECT(MachineInstr &MI,
7030b57cec5SDimitry Andric                                           MachineBasicBlock *BB) const;
7045ffd83dbSDimitry Andric     MachineBasicBlock *emitLDR_W(MachineInstr &MI, MachineBasicBlock *BB) const;
7055ffd83dbSDimitry Andric     MachineBasicBlock *emitLDR_D(MachineInstr &MI, MachineBasicBlock *BB) const;
7065ffd83dbSDimitry Andric     MachineBasicBlock *emitSTR_W(MachineInstr &MI, MachineBasicBlock *BB) const;
7075ffd83dbSDimitry Andric     MachineBasicBlock *emitSTR_D(MachineInstr &MI, MachineBasicBlock *BB) const;
7080b57cec5SDimitry Andric   };
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric   /// Create MipsTargetLowering objects.
7110b57cec5SDimitry Andric   const MipsTargetLowering *
7120b57cec5SDimitry Andric   createMips16TargetLowering(const MipsTargetMachine &TM,
7130b57cec5SDimitry Andric                              const MipsSubtarget &STI);
7140b57cec5SDimitry Andric   const MipsTargetLowering *
7150b57cec5SDimitry Andric   createMipsSETargetLowering(const MipsTargetMachine &TM,
7160b57cec5SDimitry Andric                              const MipsSubtarget &STI);
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric namespace Mips {
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
7210b57cec5SDimitry Andric                          const TargetLibraryInfo *libInfo);
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric } // end namespace Mips
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric } // end namespace llvm
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H
728