xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Mips/Mips16ISelLowering.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- Mips16ISelLowering.h - Mips16 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 // Subclass of MipsTargetLowering specialized for mips16.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric #include "Mips16ISelLowering.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h"
140b57cec5SDimitry Andric #include "Mips16HardFloatInfo.h"
150b57cec5SDimitry Andric #include "MipsMachineFunction.h"
160b57cec5SDimitry Andric #include "MipsRegisterInfo.h"
170b57cec5SDimitry Andric #include "MipsTargetMachine.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
200b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #define DEBUG_TYPE "mips-lower"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric static cl::opt<bool> DontExpandCondPseudos16(
270b57cec5SDimitry Andric   "mips16-dont-expand-cond-pseudo",
280b57cec5SDimitry Andric   cl::init(false),
290b57cec5SDimitry Andric   cl::desc("Don't expand conditional move related "
300b57cec5SDimitry Andric            "pseudos for Mips 16"),
310b57cec5SDimitry Andric   cl::Hidden);
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric namespace {
340b57cec5SDimitry Andric struct Mips16Libcall {
350b57cec5SDimitry Andric   RTLIB::Libcall Libcall;
360b57cec5SDimitry Andric   const char *Name;
370b57cec5SDimitry Andric 
operator <__anonddd1c6b40111::Mips16Libcall380b57cec5SDimitry Andric   bool operator<(const Mips16Libcall &RHS) const {
390b57cec5SDimitry Andric     return std::strcmp(Name, RHS.Name) < 0;
400b57cec5SDimitry Andric   }
410b57cec5SDimitry Andric };
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric struct Mips16IntrinsicHelperType{
440b57cec5SDimitry Andric   const char* Name;
450b57cec5SDimitry Andric   const char* Helper;
460b57cec5SDimitry Andric 
operator <__anonddd1c6b40111::Mips16IntrinsicHelperType470b57cec5SDimitry Andric   bool operator<(const Mips16IntrinsicHelperType &RHS) const {
480b57cec5SDimitry Andric     return std::strcmp(Name, RHS.Name) < 0;
490b57cec5SDimitry Andric   }
operator ==__anonddd1c6b40111::Mips16IntrinsicHelperType500b57cec5SDimitry Andric   bool operator==(const Mips16IntrinsicHelperType &RHS) const {
510b57cec5SDimitry Andric     return std::strcmp(Name, RHS.Name) == 0;
520b57cec5SDimitry Andric   }
530b57cec5SDimitry Andric };
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric // Libcalls for which no helper is generated. Sorted by name for binary search.
570b57cec5SDimitry Andric static const Mips16Libcall HardFloatLibCalls[] = {
580b57cec5SDimitry Andric   { RTLIB::ADD_F64, "__mips16_adddf3" },
590b57cec5SDimitry Andric   { RTLIB::ADD_F32, "__mips16_addsf3" },
600b57cec5SDimitry Andric   { RTLIB::DIV_F64, "__mips16_divdf3" },
610b57cec5SDimitry Andric   { RTLIB::DIV_F32, "__mips16_divsf3" },
620b57cec5SDimitry Andric   { RTLIB::OEQ_F64, "__mips16_eqdf2" },
630b57cec5SDimitry Andric   { RTLIB::OEQ_F32, "__mips16_eqsf2" },
640b57cec5SDimitry Andric   { RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" },
650b57cec5SDimitry Andric   { RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" },
660b57cec5SDimitry Andric   { RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" },
670b57cec5SDimitry Andric   { RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" },
680b57cec5SDimitry Andric   { RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" },
690b57cec5SDimitry Andric   { RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" },
700b57cec5SDimitry Andric   { RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" },
710b57cec5SDimitry Andric   { RTLIB::OGE_F64, "__mips16_gedf2" },
720b57cec5SDimitry Andric   { RTLIB::OGE_F32, "__mips16_gesf2" },
730b57cec5SDimitry Andric   { RTLIB::OGT_F64, "__mips16_gtdf2" },
740b57cec5SDimitry Andric   { RTLIB::OGT_F32, "__mips16_gtsf2" },
750b57cec5SDimitry Andric   { RTLIB::OLE_F64, "__mips16_ledf2" },
760b57cec5SDimitry Andric   { RTLIB::OLE_F32, "__mips16_lesf2" },
770b57cec5SDimitry Andric   { RTLIB::OLT_F64, "__mips16_ltdf2" },
780b57cec5SDimitry Andric   { RTLIB::OLT_F32, "__mips16_ltsf2" },
790b57cec5SDimitry Andric   { RTLIB::MUL_F64, "__mips16_muldf3" },
800b57cec5SDimitry Andric   { RTLIB::MUL_F32, "__mips16_mulsf3" },
810b57cec5SDimitry Andric   { RTLIB::UNE_F64, "__mips16_nedf2" },
820b57cec5SDimitry Andric   { RTLIB::UNE_F32, "__mips16_nesf2" },
830b57cec5SDimitry Andric   { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall.
840b57cec5SDimitry Andric   { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall.
850b57cec5SDimitry Andric   { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall.
860b57cec5SDimitry Andric   { RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall.
870b57cec5SDimitry Andric   { RTLIB::SUB_F64, "__mips16_subdf3" },
880b57cec5SDimitry Andric   { RTLIB::SUB_F32, "__mips16_subsf3" },
890b57cec5SDimitry Andric   { RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" },
900b57cec5SDimitry Andric   { RTLIB::UO_F64, "__mips16_unorddf2" },
910b57cec5SDimitry Andric   { RTLIB::UO_F32, "__mips16_unordsf2" }
920b57cec5SDimitry Andric };
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {
950b57cec5SDimitry Andric   {"__fixunsdfsi", "__mips16_call_stub_2" },
960b57cec5SDimitry Andric   {"ceil",  "__mips16_call_stub_df_2"},
970b57cec5SDimitry Andric   {"ceilf", "__mips16_call_stub_sf_1"},
980b57cec5SDimitry Andric   {"copysign",  "__mips16_call_stub_df_10"},
990b57cec5SDimitry Andric   {"copysignf", "__mips16_call_stub_sf_5"},
1000b57cec5SDimitry Andric   {"cos",  "__mips16_call_stub_df_2"},
1010b57cec5SDimitry Andric   {"cosf", "__mips16_call_stub_sf_1"},
1020b57cec5SDimitry Andric   {"exp2",  "__mips16_call_stub_df_2"},
1030b57cec5SDimitry Andric   {"exp2f", "__mips16_call_stub_sf_1"},
1040b57cec5SDimitry Andric   {"floor",  "__mips16_call_stub_df_2"},
1050b57cec5SDimitry Andric   {"floorf", "__mips16_call_stub_sf_1"},
1060b57cec5SDimitry Andric   {"log2",  "__mips16_call_stub_df_2"},
1070b57cec5SDimitry Andric   {"log2f", "__mips16_call_stub_sf_1"},
1080b57cec5SDimitry Andric   {"nearbyint",  "__mips16_call_stub_df_2"},
1090b57cec5SDimitry Andric   {"nearbyintf", "__mips16_call_stub_sf_1"},
1100b57cec5SDimitry Andric   {"rint",  "__mips16_call_stub_df_2"},
1110b57cec5SDimitry Andric   {"rintf", "__mips16_call_stub_sf_1"},
1120b57cec5SDimitry Andric   {"sin",  "__mips16_call_stub_df_2"},
1130b57cec5SDimitry Andric   {"sinf", "__mips16_call_stub_sf_1"},
1140b57cec5SDimitry Andric   {"sqrt",  "__mips16_call_stub_df_2"},
1150b57cec5SDimitry Andric   {"sqrtf", "__mips16_call_stub_sf_1"},
1160b57cec5SDimitry Andric   {"trunc",  "__mips16_call_stub_df_2"},
1170b57cec5SDimitry Andric   {"truncf", "__mips16_call_stub_sf_1"},
1180b57cec5SDimitry Andric };
1190b57cec5SDimitry Andric 
Mips16TargetLowering(const MipsTargetMachine & TM,const MipsSubtarget & STI)1200b57cec5SDimitry Andric Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM,
1210b57cec5SDimitry Andric                                            const MipsSubtarget &STI)
1220b57cec5SDimitry Andric     : MipsTargetLowering(TM, STI) {
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // Set up the register classes
1250b57cec5SDimitry Andric   addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   if (!Subtarget.useSoftFloat())
1280b57cec5SDimitry Andric     setMips16HardFloatLibCalls();
1290b57cec5SDimitry Andric 
130*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, LibCall);
131*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, LibCall);
132*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, LibCall);
133*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, LibCall);
134*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, LibCall);
135*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, LibCall);
136*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, LibCall);
137*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, LibCall);
138*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, LibCall);
139*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, LibCall);
140*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, LibCall);
141*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, LibCall);
142*5f757f3fSDimitry Andric   setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, LibCall);
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   setOperationAction(ISD::ROTR, MVT::i32,  Expand);
1450b57cec5SDimitry Andric   setOperationAction(ISD::ROTR, MVT::i64,  Expand);
1460b57cec5SDimitry Andric   setOperationAction(ISD::BSWAP, MVT::i32, Expand);
1470b57cec5SDimitry Andric   setOperationAction(ISD::BSWAP, MVT::i64, Expand);
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   computeRegisterProperties(STI.getRegisterInfo());
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric const MipsTargetLowering *
createMips16TargetLowering(const MipsTargetMachine & TM,const MipsSubtarget & STI)1530b57cec5SDimitry Andric llvm::createMips16TargetLowering(const MipsTargetMachine &TM,
1540b57cec5SDimitry Andric                                  const MipsSubtarget &STI) {
1550b57cec5SDimitry Andric   return new Mips16TargetLowering(TM, STI);
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
allowsMisalignedMemoryAccesses(EVT VT,unsigned,Align,MachineMemOperand::Flags,unsigned * Fast) const1580b57cec5SDimitry Andric bool Mips16TargetLowering::allowsMisalignedMemoryAccesses(
159bdd1243dSDimitry Andric     EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
1600b57cec5SDimitry Andric   return false;
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const1640b57cec5SDimitry Andric Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1650b57cec5SDimitry Andric                                                   MachineBasicBlock *BB) const {
1660b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1670b57cec5SDimitry Andric   default:
1680b57cec5SDimitry Andric     return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
1690b57cec5SDimitry Andric   case Mips::SelBeqZ:
1700b57cec5SDimitry Andric     return emitSel16(Mips::BeqzRxImm16, MI, BB);
1710b57cec5SDimitry Andric   case Mips::SelBneZ:
1720b57cec5SDimitry Andric     return emitSel16(Mips::BnezRxImm16, MI, BB);
1730b57cec5SDimitry Andric   case Mips::SelTBteqZCmpi:
1740b57cec5SDimitry Andric     return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);
1750b57cec5SDimitry Andric   case Mips::SelTBteqZSlti:
1760b57cec5SDimitry Andric     return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);
1770b57cec5SDimitry Andric   case Mips::SelTBteqZSltiu:
1780b57cec5SDimitry Andric     return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);
1790b57cec5SDimitry Andric   case Mips::SelTBtneZCmpi:
1800b57cec5SDimitry Andric     return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);
1810b57cec5SDimitry Andric   case Mips::SelTBtneZSlti:
1820b57cec5SDimitry Andric     return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);
1830b57cec5SDimitry Andric   case Mips::SelTBtneZSltiu:
1840b57cec5SDimitry Andric     return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);
1850b57cec5SDimitry Andric   case Mips::SelTBteqZCmp:
1860b57cec5SDimitry Andric     return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
1870b57cec5SDimitry Andric   case Mips::SelTBteqZSlt:
1880b57cec5SDimitry Andric     return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
1890b57cec5SDimitry Andric   case Mips::SelTBteqZSltu:
1900b57cec5SDimitry Andric     return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
1910b57cec5SDimitry Andric   case Mips::SelTBtneZCmp:
1920b57cec5SDimitry Andric     return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
1930b57cec5SDimitry Andric   case Mips::SelTBtneZSlt:
1940b57cec5SDimitry Andric     return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
1950b57cec5SDimitry Andric   case Mips::SelTBtneZSltu:
1960b57cec5SDimitry Andric     return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
1970b57cec5SDimitry Andric   case Mips::BteqzT8CmpX16:
1980b57cec5SDimitry Andric     return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);
1990b57cec5SDimitry Andric   case Mips::BteqzT8SltX16:
2000b57cec5SDimitry Andric     return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);
2010b57cec5SDimitry Andric   case Mips::BteqzT8SltuX16:
2020b57cec5SDimitry Andric     // TBD: figure out a way to get this or remove the instruction
2030b57cec5SDimitry Andric     // altogether.
2040b57cec5SDimitry Andric     return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);
2050b57cec5SDimitry Andric   case Mips::BtnezT8CmpX16:
2060b57cec5SDimitry Andric     return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);
2070b57cec5SDimitry Andric   case Mips::BtnezT8SltX16:
2080b57cec5SDimitry Andric     return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);
2090b57cec5SDimitry Andric   case Mips::BtnezT8SltuX16:
2100b57cec5SDimitry Andric     // TBD: figure out a way to get this or remove the instruction
2110b57cec5SDimitry Andric     // altogether.
2120b57cec5SDimitry Andric     return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);
2130b57cec5SDimitry Andric   case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(
2140b57cec5SDimitry Andric     Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
2150b57cec5SDimitry Andric   case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(
2160b57cec5SDimitry Andric     Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
2170b57cec5SDimitry Andric   case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(
2180b57cec5SDimitry Andric     Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
2190b57cec5SDimitry Andric   case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(
2200b57cec5SDimitry Andric     Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);
2210b57cec5SDimitry Andric   case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(
2220b57cec5SDimitry Andric     Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);
2230b57cec5SDimitry Andric   case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(
2240b57cec5SDimitry Andric     Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);
2250b57cec5SDimitry Andric     break;
2260b57cec5SDimitry Andric   case Mips::SltCCRxRy16:
2270b57cec5SDimitry Andric     return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);
2280b57cec5SDimitry Andric     break;
2290b57cec5SDimitry Andric   case Mips::SltiCCRxImmX16:
2300b57cec5SDimitry Andric     return emitFEXT_CCRXI16_ins
2310b57cec5SDimitry Andric       (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);
2320b57cec5SDimitry Andric   case Mips::SltiuCCRxImmX16:
2330b57cec5SDimitry Andric     return emitFEXT_CCRXI16_ins
2340b57cec5SDimitry Andric       (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);
2350b57cec5SDimitry Andric   case Mips::SltuCCRxRy16:
2360b57cec5SDimitry Andric     return emitFEXT_CCRX16_ins
2370b57cec5SDimitry Andric       (Mips::SltuRxRy16, MI, BB);
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
isEligibleForTailCallOptimization(const CCState & CCInfo,unsigned NextStackOffset,const MipsFunctionInfo & FI) const2410b57cec5SDimitry Andric bool Mips16TargetLowering::isEligibleForTailCallOptimization(
2420b57cec5SDimitry Andric     const CCState &CCInfo, unsigned NextStackOffset,
2430b57cec5SDimitry Andric     const MipsFunctionInfo &FI) const {
2440b57cec5SDimitry Andric   // No tail call optimization for mips16.
2450b57cec5SDimitry Andric   return false;
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
setMips16HardFloatLibCalls()2480b57cec5SDimitry Andric void Mips16TargetLowering::setMips16HardFloatLibCalls() {
249bdd1243dSDimitry Andric   for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {
2500b57cec5SDimitry Andric     assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
2510b57cec5SDimitry Andric            "Array not sorted!");
2520b57cec5SDimitry Andric     if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL)
2530b57cec5SDimitry Andric       setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name);
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric //
2580b57cec5SDimitry Andric // The Mips16 hard float is a crazy quilt inherited from gcc. I have a much
2590b57cec5SDimitry Andric // cleaner way to do all of this but it will have to wait until the traditional
2600b57cec5SDimitry Andric // gcc mechanism is completed.
2610b57cec5SDimitry Andric //
2620b57cec5SDimitry Andric // For Pic, in order for Mips16 code to call Mips32 code which according the abi
2630b57cec5SDimitry Andric // have either arguments or returned values placed in floating point registers,
2640b57cec5SDimitry Andric // we use a set of helper functions. (This includes functions which return type
2650b57cec5SDimitry Andric //  complex which on Mips are returned in a pair of floating point registers).
2660b57cec5SDimitry Andric //
2670b57cec5SDimitry Andric // This is an encoding that we inherited from gcc.
2680b57cec5SDimitry Andric // In Mips traditional O32, N32 ABI, floating point numbers are passed in
2690b57cec5SDimitry Andric // floating point argument registers 1,2 only when the first and optionally
2700b57cec5SDimitry Andric // the second arguments are float (sf) or double (df).
2710b57cec5SDimitry Andric // For Mips16 we are only concerned with the situations where floating point
2720b57cec5SDimitry Andric // arguments are being passed in floating point registers by the ABI, because
2730b57cec5SDimitry Andric // Mips16 mode code cannot execute floating point instructions to load those
2740b57cec5SDimitry Andric // values and hence helper functions are needed.
2750b57cec5SDimitry Andric // The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)
2760b57cec5SDimitry Andric // the helper function suffixs for these are:
2770b57cec5SDimitry Andric //                        0,  1,    5,        9,         2,   6,        10
2780b57cec5SDimitry Andric // this suffix can then be calculated as follows:
2790b57cec5SDimitry Andric // for a given argument Arg:
2800b57cec5SDimitry Andric //     Arg1x, Arg2x = 1 :  Arg is sf
2810b57cec5SDimitry Andric //                    2 :  Arg is df
2820b57cec5SDimitry Andric //                    0:   Arg is neither sf or df
2830b57cec5SDimitry Andric // So this stub is the string for number Arg1x + Arg2x*4.
2840b57cec5SDimitry Andric // However not all numbers between 0 and 10 are possible, we check anyway and
2850b57cec5SDimitry Andric // assert if the impossible exists.
2860b57cec5SDimitry Andric //
2870b57cec5SDimitry Andric 
getMips16HelperFunctionStubNumber(ArgListTy & Args) const2880b57cec5SDimitry Andric unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
2890b57cec5SDimitry Andric   (ArgListTy &Args) const {
2900b57cec5SDimitry Andric   unsigned int resultNum = 0;
2910b57cec5SDimitry Andric   if (Args.size() >= 1) {
2920b57cec5SDimitry Andric     Type *t = Args[0].Ty;
2930b57cec5SDimitry Andric     if (t->isFloatTy()) {
2940b57cec5SDimitry Andric       resultNum = 1;
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric     else if (t->isDoubleTy()) {
2970b57cec5SDimitry Andric       resultNum = 2;
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric   if (resultNum) {
3010b57cec5SDimitry Andric     if (Args.size() >=2) {
3020b57cec5SDimitry Andric       Type *t = Args[1].Ty;
3030b57cec5SDimitry Andric       if (t->isFloatTy()) {
3040b57cec5SDimitry Andric         resultNum += 4;
3050b57cec5SDimitry Andric       }
3060b57cec5SDimitry Andric       else if (t->isDoubleTy()) {
3070b57cec5SDimitry Andric         resultNum += 8;
3080b57cec5SDimitry Andric       }
3090b57cec5SDimitry Andric     }
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric   return resultNum;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric //
3150b57cec5SDimitry Andric // Prefixes are attached to stub numbers depending on the return type.
3160b57cec5SDimitry Andric // return type: float  sf_
3170b57cec5SDimitry Andric //              double df_
3180b57cec5SDimitry Andric //              single complex sc_
3190b57cec5SDimitry Andric //              double complext dc_
3200b57cec5SDimitry Andric //              others  NO PREFIX
3210b57cec5SDimitry Andric //
3220b57cec5SDimitry Andric //
3230b57cec5SDimitry Andric // The full name of a helper function is__mips16_call_stub +
3240b57cec5SDimitry Andric //    return type dependent prefix + stub number
3250b57cec5SDimitry Andric //
3260b57cec5SDimitry Andric // FIXME: This is something that probably should be in a different source file
3270b57cec5SDimitry Andric // and perhaps done differently but my main purpose is to not waste runtime
3280b57cec5SDimitry Andric // on something that we can enumerate in the source. Another possibility is
3290b57cec5SDimitry Andric // to have a python script to generate these mapping tables. This will do
3300b57cec5SDimitry Andric // for now. There are a whole series of helper function mapping arrays, one
3310b57cec5SDimitry Andric // for each return type class as outlined above. There there are 11 possible
3320b57cec5SDimitry Andric // entries. Ones with 0 are ones which should never be selected.
3330b57cec5SDimitry Andric //
3340b57cec5SDimitry Andric // All the arrays are similar except for ones which return neither
3350b57cec5SDimitry Andric // sf, df, sc, dc, in which we only care about ones which have sf or df as a
3360b57cec5SDimitry Andric // first parameter.
3370b57cec5SDimitry Andric //
3380b57cec5SDimitry Andric #define P_ "__mips16_call_stub_"
3390b57cec5SDimitry Andric #define MAX_STUB_NUMBER 10
3400b57cec5SDimitry Andric #define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"
3410b57cec5SDimitry Andric #define T P "0" , T1
3420b57cec5SDimitry Andric #define P P_
3430b57cec5SDimitry Andric static char const * vMips16Helper[MAX_STUB_NUMBER+1] =
3440b57cec5SDimitry Andric   {nullptr, T1 };
3450b57cec5SDimitry Andric #undef P
3460b57cec5SDimitry Andric #define P P_ "sf_"
3470b57cec5SDimitry Andric static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =
3480b57cec5SDimitry Andric   { T };
3490b57cec5SDimitry Andric #undef P
3500b57cec5SDimitry Andric #define P P_ "df_"
3510b57cec5SDimitry Andric static char const * dfMips16Helper[MAX_STUB_NUMBER+1] =
3520b57cec5SDimitry Andric   { T };
3530b57cec5SDimitry Andric #undef P
3540b57cec5SDimitry Andric #define P P_ "sc_"
3550b57cec5SDimitry Andric static char const * scMips16Helper[MAX_STUB_NUMBER+1] =
3560b57cec5SDimitry Andric   { T };
3570b57cec5SDimitry Andric #undef P
3580b57cec5SDimitry Andric #define P P_ "dc_"
3590b57cec5SDimitry Andric static char const * dcMips16Helper[MAX_STUB_NUMBER+1] =
3600b57cec5SDimitry Andric   { T };
3610b57cec5SDimitry Andric #undef P
3620b57cec5SDimitry Andric #undef P_
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric const char* Mips16TargetLowering::
getMips16HelperFunction(Type * RetTy,ArgListTy & Args,bool & needHelper) const3660b57cec5SDimitry Andric   getMips16HelperFunction
3670b57cec5SDimitry Andric     (Type* RetTy, ArgListTy &Args, bool &needHelper) const {
3680b57cec5SDimitry Andric   const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);
3690b57cec5SDimitry Andric #ifndef NDEBUG
3700b57cec5SDimitry Andric   const unsigned int maxStubNum = 10;
3710b57cec5SDimitry Andric   assert(stubNum <= maxStubNum);
3720b57cec5SDimitry Andric   const bool validStubNum[maxStubNum+1] =
3730b57cec5SDimitry Andric     {true, true, true, false, false, true, true, false, false, true, true};
3740b57cec5SDimitry Andric   assert(validStubNum[stubNum]);
3750b57cec5SDimitry Andric #endif
3760b57cec5SDimitry Andric   const char *result;
3770b57cec5SDimitry Andric   if (RetTy->isFloatTy()) {
3780b57cec5SDimitry Andric     result = sfMips16Helper[stubNum];
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric   else if (RetTy ->isDoubleTy()) {
3810b57cec5SDimitry Andric     result = dfMips16Helper[stubNum];
3820b57cec5SDimitry Andric   } else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) {
3830b57cec5SDimitry Andric     // check if it's complex
3840b57cec5SDimitry Andric     if (SRetTy->getNumElements() == 2) {
3850b57cec5SDimitry Andric       if ((SRetTy->getElementType(0)->isFloatTy()) &&
3860b57cec5SDimitry Andric           (SRetTy->getElementType(1)->isFloatTy())) {
3870b57cec5SDimitry Andric         result = scMips16Helper[stubNum];
3880b57cec5SDimitry Andric       } else if ((SRetTy->getElementType(0)->isDoubleTy()) &&
3890b57cec5SDimitry Andric                  (SRetTy->getElementType(1)->isDoubleTy())) {
3900b57cec5SDimitry Andric         result = dcMips16Helper[stubNum];
3910b57cec5SDimitry Andric       } else {
3920b57cec5SDimitry Andric         llvm_unreachable("Uncovered condition");
3930b57cec5SDimitry Andric       }
3940b57cec5SDimitry Andric     } else {
3950b57cec5SDimitry Andric       llvm_unreachable("Uncovered condition");
3960b57cec5SDimitry Andric     }
3970b57cec5SDimitry Andric   } else {
3980b57cec5SDimitry Andric     if (stubNum == 0) {
3990b57cec5SDimitry Andric       needHelper = false;
4000b57cec5SDimitry Andric       return "";
4010b57cec5SDimitry Andric     }
4020b57cec5SDimitry Andric     result = vMips16Helper[stubNum];
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   needHelper = true;
4050b57cec5SDimitry Andric   return result;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric void Mips16TargetLowering::
getOpndList(SmallVectorImpl<SDValue> & Ops,std::deque<std::pair<unsigned,SDValue>> & RegsToPass,bool IsPICCall,bool GlobalOrExternal,bool InternalLinkage,bool IsCallReloc,CallLoweringInfo & CLI,SDValue Callee,SDValue Chain) const4090b57cec5SDimitry Andric getOpndList(SmallVectorImpl<SDValue> &Ops,
4100b57cec5SDimitry Andric             std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
4110b57cec5SDimitry Andric             bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
4120b57cec5SDimitry Andric             bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
4130b57cec5SDimitry Andric             SDValue Chain) const {
4140b57cec5SDimitry Andric   SelectionDAG &DAG = CLI.DAG;
4150b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
4160b57cec5SDimitry Andric   MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
4170b57cec5SDimitry Andric   const char* Mips16HelperFunction = nullptr;
4180b57cec5SDimitry Andric   bool NeedMips16Helper = false;
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   if (Subtarget.inMips16HardFloat()) {
4210b57cec5SDimitry Andric     //
4220b57cec5SDimitry Andric     // currently we don't have symbols tagged with the mips16 or mips32
4230b57cec5SDimitry Andric     // qualifier so we will assume that we don't know what kind it is.
4240b57cec5SDimitry Andric     // and generate the helper
4250b57cec5SDimitry Andric     //
4260b57cec5SDimitry Andric     bool LookupHelper = true;
4270b57cec5SDimitry Andric     if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
4280b57cec5SDimitry Andric       Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric       if (std::binary_search(std::begin(HardFloatLibCalls),
4310b57cec5SDimitry Andric                              std::end(HardFloatLibCalls), Find))
4320b57cec5SDimitry Andric         LookupHelper = false;
4330b57cec5SDimitry Andric       else {
4340b57cec5SDimitry Andric         const char *Symbol = S->getSymbol();
4350b57cec5SDimitry Andric         Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };
4360b57cec5SDimitry Andric         const Mips16HardFloatInfo::FuncSignature *Signature =
4370b57cec5SDimitry Andric             Mips16HardFloatInfo::findFuncSignature(Symbol);
4380b57cec5SDimitry Andric         if (!IsPICCall && (Signature && (FuncInfo->StubsNeeded.find(Symbol) ==
4390b57cec5SDimitry Andric                                          FuncInfo->StubsNeeded.end()))) {
4400b57cec5SDimitry Andric           FuncInfo->StubsNeeded[Symbol] = Signature;
4410b57cec5SDimitry Andric           //
4420b57cec5SDimitry Andric           // S2 is normally saved if the stub is for a function which
4430b57cec5SDimitry Andric           // returns a float or double value and is not otherwise. This is
4440b57cec5SDimitry Andric           // because more work is required after the function the stub
4450b57cec5SDimitry Andric           // is calling completes, and so the stub cannot directly return
4460b57cec5SDimitry Andric           // and the stub has no stack space to store the return address so
4470b57cec5SDimitry Andric           // S2 is used for that purpose.
4480b57cec5SDimitry Andric           // In order to take advantage of not saving S2, we need to also
4490b57cec5SDimitry Andric           // optimize the call in the stub and this requires some further
4500b57cec5SDimitry Andric           // functionality in MipsAsmPrinter which we don't have yet.
4510b57cec5SDimitry Andric           // So for now we always save S2. The optimization will be done
4520b57cec5SDimitry Andric           // in a follow-on patch.
4530b57cec5SDimitry Andric           //
45404eeddc0SDimitry Andric           if (true || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))
4550b57cec5SDimitry Andric             FuncInfo->setSaveS2();
4560b57cec5SDimitry Andric         }
4570b57cec5SDimitry Andric         // one more look at list of intrinsics
4580b57cec5SDimitry Andric         const Mips16IntrinsicHelperType *Helper =
4590b57cec5SDimitry Andric             llvm::lower_bound(Mips16IntrinsicHelper, IntrinsicFind);
4600b57cec5SDimitry Andric         if (Helper != std::end(Mips16IntrinsicHelper) &&
4610b57cec5SDimitry Andric             *Helper == IntrinsicFind) {
4620b57cec5SDimitry Andric           Mips16HelperFunction = Helper->Helper;
4630b57cec5SDimitry Andric           NeedMips16Helper = true;
4640b57cec5SDimitry Andric           LookupHelper = false;
4650b57cec5SDimitry Andric         }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric       }
4680b57cec5SDimitry Andric     } else if (GlobalAddressSDNode *G =
4690b57cec5SDimitry Andric                    dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {
4700b57cec5SDimitry Andric       Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,
4710b57cec5SDimitry Andric                              G->getGlobal()->getName().data() };
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric       if (std::binary_search(std::begin(HardFloatLibCalls),
4740b57cec5SDimitry Andric                              std::end(HardFloatLibCalls), Find))
4750b57cec5SDimitry Andric         LookupHelper = false;
4760b57cec5SDimitry Andric     }
4770b57cec5SDimitry Andric     if (LookupHelper)
4780b57cec5SDimitry Andric       Mips16HelperFunction =
4790b57cec5SDimitry Andric         getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   SDValue JumpTarget = Callee;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   // T9 should contain the address of the callee function if
4850b57cec5SDimitry Andric   // -relocation-model=pic or it is an indirect call.
4860b57cec5SDimitry Andric   if (IsPICCall || !GlobalOrExternal) {
4870b57cec5SDimitry Andric     unsigned V0Reg = Mips::V0;
4880b57cec5SDimitry Andric     if (NeedMips16Helper) {
4890b57cec5SDimitry Andric       RegsToPass.push_front(std::make_pair(V0Reg, Callee));
4900b57cec5SDimitry Andric       JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction,
4910b57cec5SDimitry Andric                                          getPointerTy(DAG.getDataLayout()));
4920b57cec5SDimitry Andric       ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);
4930b57cec5SDimitry Andric       JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG,
4940b57cec5SDimitry Andric                                  MipsII::MO_GOT, Chain,
4955ffd83dbSDimitry Andric                                  FuncInfo->callPtrInfo(MF, S->getSymbol()));
4960b57cec5SDimitry Andric     } else
4970b57cec5SDimitry Andric       RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   Ops.push_back(JumpTarget);
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,
5030b57cec5SDimitry Andric                                   InternalLinkage, IsCallReloc, CLI, Callee,
5040b57cec5SDimitry Andric                                   Chain);
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric MachineBasicBlock *
emitSel16(unsigned Opc,MachineInstr & MI,MachineBasicBlock * BB) const5080b57cec5SDimitry Andric Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,
5090b57cec5SDimitry Andric                                 MachineBasicBlock *BB) const {
5100b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
5110b57cec5SDimitry Andric     return BB;
5120b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
5130b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
5140b57cec5SDimitry Andric   // To "insert" a SELECT_CC instruction, we actually have to insert the
5150b57cec5SDimitry Andric   // diamond control-flow pattern.  The incoming instruction knows the
5160b57cec5SDimitry Andric   // destination vreg to set, the condition code register to branch on, the
5170b57cec5SDimitry Andric   // true/false values to select between, and a branch opcode to use.
5180b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
5190b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB->getIterator();
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   //  thisMBB:
5220b57cec5SDimitry Andric   //  ...
5230b57cec5SDimitry Andric   //   TrueVal = ...
5240b57cec5SDimitry Andric   //   setcc r1, r2, r3
5250b57cec5SDimitry Andric   //   bNE   r1, r0, copy1MBB
5260b57cec5SDimitry Andric   //   fallthrough --> copy0MBB
5270b57cec5SDimitry Andric   MachineBasicBlock *thisMBB  = BB;
5280b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
5290b57cec5SDimitry Andric   MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
5300b57cec5SDimitry Andric   MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
5310b57cec5SDimitry Andric   F->insert(It, copy0MBB);
5320b57cec5SDimitry Andric   F->insert(It, sinkMBB);
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   // Transfer the remainder of BB and its successor edges to sinkMBB.
5350b57cec5SDimitry Andric   sinkMBB->splice(sinkMBB->begin(), BB,
5360b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(MI)), BB->end());
5370b57cec5SDimitry Andric   sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   // Next, add the true and fallthrough blocks as its successors.
5400b57cec5SDimitry Andric   BB->addSuccessor(copy0MBB);
5410b57cec5SDimitry Andric   BB->addSuccessor(sinkMBB);
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   BuildMI(BB, DL, TII->get(Opc))
5440b57cec5SDimitry Andric       .addReg(MI.getOperand(3).getReg())
5450b57cec5SDimitry Andric       .addMBB(sinkMBB);
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   //  copy0MBB:
5480b57cec5SDimitry Andric   //   %FalseValue = ...
5490b57cec5SDimitry Andric   //   # fallthrough to sinkMBB
5500b57cec5SDimitry Andric   BB = copy0MBB;
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   // Update machine-CFG edges
5530b57cec5SDimitry Andric   BB->addSuccessor(sinkMBB);
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   //  sinkMBB:
5560b57cec5SDimitry Andric   //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
5570b57cec5SDimitry Andric   //  ...
5580b57cec5SDimitry Andric   BB = sinkMBB;
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
5610b57cec5SDimitry Andric       .addReg(MI.getOperand(1).getReg())
5620b57cec5SDimitry Andric       .addMBB(thisMBB)
5630b57cec5SDimitry Andric       .addReg(MI.getOperand(2).getReg())
5640b57cec5SDimitry Andric       .addMBB(copy0MBB);
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
5670b57cec5SDimitry Andric   return BB;
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric MachineBasicBlock *
emitSelT16(unsigned Opc1,unsigned Opc2,MachineInstr & MI,MachineBasicBlock * BB) const5710b57cec5SDimitry Andric Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,
5720b57cec5SDimitry Andric                                  MachineBasicBlock *BB) const {
5730b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
5740b57cec5SDimitry Andric     return BB;
5750b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
5760b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
5770b57cec5SDimitry Andric   // To "insert" a SELECT_CC instruction, we actually have to insert the
5780b57cec5SDimitry Andric   // diamond control-flow pattern.  The incoming instruction knows the
5790b57cec5SDimitry Andric   // destination vreg to set, the condition code register to branch on, the
5800b57cec5SDimitry Andric   // true/false values to select between, and a branch opcode to use.
5810b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
5820b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB->getIterator();
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   //  thisMBB:
5850b57cec5SDimitry Andric   //  ...
5860b57cec5SDimitry Andric   //   TrueVal = ...
5870b57cec5SDimitry Andric   //   setcc r1, r2, r3
5880b57cec5SDimitry Andric   //   bNE   r1, r0, copy1MBB
5890b57cec5SDimitry Andric   //   fallthrough --> copy0MBB
5900b57cec5SDimitry Andric   MachineBasicBlock *thisMBB  = BB;
5910b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
5920b57cec5SDimitry Andric   MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
5930b57cec5SDimitry Andric   MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
5940b57cec5SDimitry Andric   F->insert(It, copy0MBB);
5950b57cec5SDimitry Andric   F->insert(It, sinkMBB);
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   // Transfer the remainder of BB and its successor edges to sinkMBB.
5980b57cec5SDimitry Andric   sinkMBB->splice(sinkMBB->begin(), BB,
5990b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(MI)), BB->end());
6000b57cec5SDimitry Andric   sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   // Next, add the true and fallthrough blocks as its successors.
6030b57cec5SDimitry Andric   BB->addSuccessor(copy0MBB);
6040b57cec5SDimitry Andric   BB->addSuccessor(sinkMBB);
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   BuildMI(BB, DL, TII->get(Opc2))
6070b57cec5SDimitry Andric       .addReg(MI.getOperand(3).getReg())
6080b57cec5SDimitry Andric       .addReg(MI.getOperand(4).getReg());
6090b57cec5SDimitry Andric   BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   //  copy0MBB:
6120b57cec5SDimitry Andric   //   %FalseValue = ...
6130b57cec5SDimitry Andric   //   # fallthrough to sinkMBB
6140b57cec5SDimitry Andric   BB = copy0MBB;
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   // Update machine-CFG edges
6170b57cec5SDimitry Andric   BB->addSuccessor(sinkMBB);
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric   //  sinkMBB:
6200b57cec5SDimitry Andric   //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
6210b57cec5SDimitry Andric   //  ...
6220b57cec5SDimitry Andric   BB = sinkMBB;
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric   BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
6250b57cec5SDimitry Andric       .addReg(MI.getOperand(1).getReg())
6260b57cec5SDimitry Andric       .addMBB(thisMBB)
6270b57cec5SDimitry Andric       .addReg(MI.getOperand(2).getReg())
6280b57cec5SDimitry Andric       .addMBB(copy0MBB);
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
6310b57cec5SDimitry Andric   return BB;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric MachineBasicBlock *
emitSeliT16(unsigned Opc1,unsigned Opc2,MachineInstr & MI,MachineBasicBlock * BB) const6360b57cec5SDimitry Andric Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
6370b57cec5SDimitry Andric                                   MachineInstr &MI,
6380b57cec5SDimitry Andric                                   MachineBasicBlock *BB) const {
6390b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
6400b57cec5SDimitry Andric     return BB;
6410b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
6420b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
6430b57cec5SDimitry Andric   // To "insert" a SELECT_CC instruction, we actually have to insert the
6440b57cec5SDimitry Andric   // diamond control-flow pattern.  The incoming instruction knows the
6450b57cec5SDimitry Andric   // destination vreg to set, the condition code register to branch on, the
6460b57cec5SDimitry Andric   // true/false values to select between, and a branch opcode to use.
6470b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
6480b57cec5SDimitry Andric   MachineFunction::iterator It = ++BB->getIterator();
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   //  thisMBB:
6510b57cec5SDimitry Andric   //  ...
6520b57cec5SDimitry Andric   //   TrueVal = ...
6530b57cec5SDimitry Andric   //   setcc r1, r2, r3
6540b57cec5SDimitry Andric   //   bNE   r1, r0, copy1MBB
6550b57cec5SDimitry Andric   //   fallthrough --> copy0MBB
6560b57cec5SDimitry Andric   MachineBasicBlock *thisMBB  = BB;
6570b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
6580b57cec5SDimitry Andric   MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
6590b57cec5SDimitry Andric   MachineBasicBlock *sinkMBB  = F->CreateMachineBasicBlock(LLVM_BB);
6600b57cec5SDimitry Andric   F->insert(It, copy0MBB);
6610b57cec5SDimitry Andric   F->insert(It, sinkMBB);
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   // Transfer the remainder of BB and its successor edges to sinkMBB.
6640b57cec5SDimitry Andric   sinkMBB->splice(sinkMBB->begin(), BB,
6650b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(MI)), BB->end());
6660b57cec5SDimitry Andric   sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   // Next, add the true and fallthrough blocks as its successors.
6690b57cec5SDimitry Andric   BB->addSuccessor(copy0MBB);
6700b57cec5SDimitry Andric   BB->addSuccessor(sinkMBB);
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   BuildMI(BB, DL, TII->get(Opc2))
6730b57cec5SDimitry Andric       .addReg(MI.getOperand(3).getReg())
6740b57cec5SDimitry Andric       .addImm(MI.getOperand(4).getImm());
6750b57cec5SDimitry Andric   BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   //  copy0MBB:
6780b57cec5SDimitry Andric   //   %FalseValue = ...
6790b57cec5SDimitry Andric   //   # fallthrough to sinkMBB
6800b57cec5SDimitry Andric   BB = copy0MBB;
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // Update machine-CFG edges
6830b57cec5SDimitry Andric   BB->addSuccessor(sinkMBB);
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric   //  sinkMBB:
6860b57cec5SDimitry Andric   //   %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
6870b57cec5SDimitry Andric   //  ...
6880b57cec5SDimitry Andric   BB = sinkMBB;
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
6910b57cec5SDimitry Andric       .addReg(MI.getOperand(1).getReg())
6920b57cec5SDimitry Andric       .addMBB(thisMBB)
6930b57cec5SDimitry Andric       .addReg(MI.getOperand(2).getReg())
6940b57cec5SDimitry Andric       .addMBB(copy0MBB);
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
6970b57cec5SDimitry Andric   return BB;
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric MachineBasicBlock *
emitFEXT_T8I816_ins(unsigned BtOpc,unsigned CmpOpc,MachineInstr & MI,MachineBasicBlock * BB) const7020b57cec5SDimitry Andric Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
7030b57cec5SDimitry Andric                                           MachineInstr &MI,
7040b57cec5SDimitry Andric                                           MachineBasicBlock *BB) const {
7050b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
7060b57cec5SDimitry Andric     return BB;
7070b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
7088bcb0991SDimitry Andric   Register regX = MI.getOperand(0).getReg();
7098bcb0991SDimitry Andric   Register regY = MI.getOperand(1).getReg();
7100b57cec5SDimitry Andric   MachineBasicBlock *target = MI.getOperand(2).getMBB();
7110b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))
7120b57cec5SDimitry Andric       .addReg(regX)
7130b57cec5SDimitry Andric       .addReg(regY);
7140b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
7150b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
7160b57cec5SDimitry Andric   return BB;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
emitFEXT_T8I8I16_ins(unsigned BtOpc,unsigned CmpiOpc,unsigned CmpiXOpc,bool ImmSigned,MachineInstr & MI,MachineBasicBlock * BB) const7190b57cec5SDimitry Andric MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
7200b57cec5SDimitry Andric     unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
7210b57cec5SDimitry Andric     MachineInstr &MI, MachineBasicBlock *BB) const {
7220b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
7230b57cec5SDimitry Andric     return BB;
7240b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
7258bcb0991SDimitry Andric   Register regX = MI.getOperand(0).getReg();
7260b57cec5SDimitry Andric   int64_t imm = MI.getOperand(1).getImm();
7270b57cec5SDimitry Andric   MachineBasicBlock *target = MI.getOperand(2).getMBB();
7280b57cec5SDimitry Andric   unsigned CmpOpc;
7290b57cec5SDimitry Andric   if (isUInt<8>(imm))
7300b57cec5SDimitry Andric     CmpOpc = CmpiOpc;
7310b57cec5SDimitry Andric   else if ((!ImmSigned && isUInt<16>(imm)) ||
7320b57cec5SDimitry Andric            (ImmSigned && isInt<16>(imm)))
7330b57cec5SDimitry Andric     CmpOpc = CmpiXOpc;
7340b57cec5SDimitry Andric   else
7350b57cec5SDimitry Andric     llvm_unreachable("immediate field not usable");
7360b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);
7370b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
7380b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
7390b57cec5SDimitry Andric   return BB;
7400b57cec5SDimitry Andric }
7410b57cec5SDimitry Andric 
Mips16WhichOp8uOr16simm(unsigned shortOp,unsigned longOp,int64_t Imm)7420b57cec5SDimitry Andric static unsigned Mips16WhichOp8uOr16simm
7430b57cec5SDimitry Andric   (unsigned shortOp, unsigned longOp, int64_t Imm) {
7440b57cec5SDimitry Andric   if (isUInt<8>(Imm))
7450b57cec5SDimitry Andric     return shortOp;
7460b57cec5SDimitry Andric   else if (isInt<16>(Imm))
7470b57cec5SDimitry Andric     return longOp;
7480b57cec5SDimitry Andric   else
7490b57cec5SDimitry Andric     llvm_unreachable("immediate field not usable");
7500b57cec5SDimitry Andric }
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric MachineBasicBlock *
emitFEXT_CCRX16_ins(unsigned SltOpc,MachineInstr & MI,MachineBasicBlock * BB) const7530b57cec5SDimitry Andric Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,
7540b57cec5SDimitry Andric                                           MachineBasicBlock *BB) const {
7550b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
7560b57cec5SDimitry Andric     return BB;
7570b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
7588bcb0991SDimitry Andric   Register CC = MI.getOperand(0).getReg();
7598bcb0991SDimitry Andric   Register regX = MI.getOperand(1).getReg();
7608bcb0991SDimitry Andric   Register regY = MI.getOperand(2).getReg();
7610b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))
7620b57cec5SDimitry Andric       .addReg(regX)
7630b57cec5SDimitry Andric       .addReg(regY);
7640b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
7650b57cec5SDimitry Andric       .addReg(Mips::T8);
7660b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
7670b57cec5SDimitry Andric   return BB;
7680b57cec5SDimitry Andric }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric MachineBasicBlock *
emitFEXT_CCRXI16_ins(unsigned SltiOpc,unsigned SltiXOpc,MachineInstr & MI,MachineBasicBlock * BB) const7710b57cec5SDimitry Andric Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
7720b57cec5SDimitry Andric                                            MachineInstr &MI,
7730b57cec5SDimitry Andric                                            MachineBasicBlock *BB) const {
7740b57cec5SDimitry Andric   if (DontExpandCondPseudos16)
7750b57cec5SDimitry Andric     return BB;
7760b57cec5SDimitry Andric   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
7778bcb0991SDimitry Andric   Register CC = MI.getOperand(0).getReg();
7788bcb0991SDimitry Andric   Register regX = MI.getOperand(1).getReg();
7790b57cec5SDimitry Andric   int64_t Imm = MI.getOperand(2).getImm();
7800b57cec5SDimitry Andric   unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);
7810b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);
7820b57cec5SDimitry Andric   BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
7830b57cec5SDimitry Andric       .addReg(Mips::T8);
7840b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
7850b57cec5SDimitry Andric   return BB;
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric }
788