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