Path: blob/main/contrib/llvm-project/llvm/lib/Target/Mips/Mips16ISelLowering.cpp
35266 views
//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Subclass of MipsTargetLowering specialized for mips16.9//10//===----------------------------------------------------------------------===//11#include "Mips16ISelLowering.h"12#include "MCTargetDesc/MipsBaseInfo.h"13#include "Mips16HardFloatInfo.h"14#include "MipsMachineFunction.h"15#include "MipsRegisterInfo.h"16#include "MipsTargetMachine.h"17#include "llvm/CodeGen/MachineInstrBuilder.h"18#include "llvm/CodeGen/TargetInstrInfo.h"19#include "llvm/Support/CommandLine.h"2021using namespace llvm;2223#define DEBUG_TYPE "mips-lower"2425static cl::opt<bool> DontExpandCondPseudos16(26"mips16-dont-expand-cond-pseudo",27cl::init(false),28cl::desc("Don't expand conditional move related "29"pseudos for Mips 16"),30cl::Hidden);3132namespace {33struct Mips16Libcall {34RTLIB::Libcall Libcall;35const char *Name;3637bool operator<(const Mips16Libcall &RHS) const {38return std::strcmp(Name, RHS.Name) < 0;39}40};4142struct Mips16IntrinsicHelperType{43const char* Name;44const char* Helper;4546bool operator<(const Mips16IntrinsicHelperType &RHS) const {47return std::strcmp(Name, RHS.Name) < 0;48}49bool operator==(const Mips16IntrinsicHelperType &RHS) const {50return std::strcmp(Name, RHS.Name) == 0;51}52};53}5455// Libcalls for which no helper is generated. Sorted by name for binary search.56static const Mips16Libcall HardFloatLibCalls[] = {57{ RTLIB::ADD_F64, "__mips16_adddf3" },58{ RTLIB::ADD_F32, "__mips16_addsf3" },59{ RTLIB::DIV_F64, "__mips16_divdf3" },60{ RTLIB::DIV_F32, "__mips16_divsf3" },61{ RTLIB::OEQ_F64, "__mips16_eqdf2" },62{ RTLIB::OEQ_F32, "__mips16_eqsf2" },63{ RTLIB::FPEXT_F32_F64, "__mips16_extendsfdf2" },64{ RTLIB::FPTOSINT_F64_I32, "__mips16_fix_truncdfsi" },65{ RTLIB::FPTOSINT_F32_I32, "__mips16_fix_truncsfsi" },66{ RTLIB::SINTTOFP_I32_F64, "__mips16_floatsidf" },67{ RTLIB::SINTTOFP_I32_F32, "__mips16_floatsisf" },68{ RTLIB::UINTTOFP_I32_F64, "__mips16_floatunsidf" },69{ RTLIB::UINTTOFP_I32_F32, "__mips16_floatunsisf" },70{ RTLIB::OGE_F64, "__mips16_gedf2" },71{ RTLIB::OGE_F32, "__mips16_gesf2" },72{ RTLIB::OGT_F64, "__mips16_gtdf2" },73{ RTLIB::OGT_F32, "__mips16_gtsf2" },74{ RTLIB::OLE_F64, "__mips16_ledf2" },75{ RTLIB::OLE_F32, "__mips16_lesf2" },76{ RTLIB::OLT_F64, "__mips16_ltdf2" },77{ RTLIB::OLT_F32, "__mips16_ltsf2" },78{ RTLIB::MUL_F64, "__mips16_muldf3" },79{ RTLIB::MUL_F32, "__mips16_mulsf3" },80{ RTLIB::UNE_F64, "__mips16_nedf2" },81{ RTLIB::UNE_F32, "__mips16_nesf2" },82{ RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_dc" }, // No associated libcall.83{ RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_df" }, // No associated libcall.84{ RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sc" }, // No associated libcall.85{ RTLIB::UNKNOWN_LIBCALL, "__mips16_ret_sf" }, // No associated libcall.86{ RTLIB::SUB_F64, "__mips16_subdf3" },87{ RTLIB::SUB_F32, "__mips16_subsf3" },88{ RTLIB::FPROUND_F64_F32, "__mips16_truncdfsf2" },89{ RTLIB::UO_F64, "__mips16_unorddf2" },90{ RTLIB::UO_F32, "__mips16_unordsf2" }91};9293static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {94{"__fixunsdfsi", "__mips16_call_stub_2" },95{"ceil", "__mips16_call_stub_df_2"},96{"ceilf", "__mips16_call_stub_sf_1"},97{"copysign", "__mips16_call_stub_df_10"},98{"copysignf", "__mips16_call_stub_sf_5"},99{"cos", "__mips16_call_stub_df_2"},100{"cosf", "__mips16_call_stub_sf_1"},101{"exp2", "__mips16_call_stub_df_2"},102{"exp2f", "__mips16_call_stub_sf_1"},103{"floor", "__mips16_call_stub_df_2"},104{"floorf", "__mips16_call_stub_sf_1"},105{"log2", "__mips16_call_stub_df_2"},106{"log2f", "__mips16_call_stub_sf_1"},107{"nearbyint", "__mips16_call_stub_df_2"},108{"nearbyintf", "__mips16_call_stub_sf_1"},109{"rint", "__mips16_call_stub_df_2"},110{"rintf", "__mips16_call_stub_sf_1"},111{"sin", "__mips16_call_stub_df_2"},112{"sinf", "__mips16_call_stub_sf_1"},113{"sqrt", "__mips16_call_stub_df_2"},114{"sqrtf", "__mips16_call_stub_sf_1"},115{"trunc", "__mips16_call_stub_df_2"},116{"truncf", "__mips16_call_stub_sf_1"},117};118119Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM,120const MipsSubtarget &STI)121: MipsTargetLowering(TM, STI) {122123// Set up the register classes124addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);125126if (!Subtarget.useSoftFloat())127setMips16HardFloatLibCalls();128129setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, LibCall);130setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, LibCall);131setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, LibCall);132setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, LibCall);133setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, LibCall);134setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, LibCall);135setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, LibCall);136setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, LibCall);137setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, LibCall);138setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, LibCall);139setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, LibCall);140setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, LibCall);141setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, LibCall);142143setOperationAction(ISD::ROTR, MVT::i32, Expand);144setOperationAction(ISD::ROTR, MVT::i64, Expand);145setOperationAction(ISD::BSWAP, MVT::i32, Expand);146setOperationAction(ISD::BSWAP, MVT::i64, Expand);147148computeRegisterProperties(STI.getRegisterInfo());149}150151const MipsTargetLowering *152llvm::createMips16TargetLowering(const MipsTargetMachine &TM,153const MipsSubtarget &STI) {154return new Mips16TargetLowering(TM, STI);155}156157bool Mips16TargetLowering::allowsMisalignedMemoryAccesses(158EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {159return false;160}161162MachineBasicBlock *163Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,164MachineBasicBlock *BB) const {165switch (MI.getOpcode()) {166default:167return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);168case Mips::SelBeqZ:169return emitSel16(Mips::BeqzRxImm16, MI, BB);170case Mips::SelBneZ:171return emitSel16(Mips::BnezRxImm16, MI, BB);172case Mips::SelTBteqZCmpi:173return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);174case Mips::SelTBteqZSlti:175return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);176case Mips::SelTBteqZSltiu:177return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);178case Mips::SelTBtneZCmpi:179return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);180case Mips::SelTBtneZSlti:181return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);182case Mips::SelTBtneZSltiu:183return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);184case Mips::SelTBteqZCmp:185return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);186case Mips::SelTBteqZSlt:187return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);188case Mips::SelTBteqZSltu:189return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);190case Mips::SelTBtneZCmp:191return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);192case Mips::SelTBtneZSlt:193return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);194case Mips::SelTBtneZSltu:195return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);196case Mips::BteqzT8CmpX16:197return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);198case Mips::BteqzT8SltX16:199return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);200case Mips::BteqzT8SltuX16:201// TBD: figure out a way to get this or remove the instruction202// altogether.203return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);204case Mips::BtnezT8CmpX16:205return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);206case Mips::BtnezT8SltX16:207return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);208case Mips::BtnezT8SltuX16:209// TBD: figure out a way to get this or remove the instruction210// altogether.211return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);212case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(213Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);214case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(215Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);216case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(217Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);218case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(219Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);220case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(221Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);222case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(223Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);224break;225case Mips::SltCCRxRy16:226return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);227break;228case Mips::SltiCCRxImmX16:229return emitFEXT_CCRXI16_ins230(Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);231case Mips::SltiuCCRxImmX16:232return emitFEXT_CCRXI16_ins233(Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);234case Mips::SltuCCRxRy16:235return emitFEXT_CCRX16_ins236(Mips::SltuRxRy16, MI, BB);237}238}239240bool Mips16TargetLowering::isEligibleForTailCallOptimization(241const CCState &CCInfo, unsigned NextStackOffset,242const MipsFunctionInfo &FI) const {243// No tail call optimization for mips16.244return false;245}246247void Mips16TargetLowering::setMips16HardFloatLibCalls() {248for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {249assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&250"Array not sorted!");251if (HardFloatLibCalls[I].Libcall != RTLIB::UNKNOWN_LIBCALL)252setLibcallName(HardFloatLibCalls[I].Libcall, HardFloatLibCalls[I].Name);253}254}255256//257// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much258// cleaner way to do all of this but it will have to wait until the traditional259// gcc mechanism is completed.260//261// For Pic, in order for Mips16 code to call Mips32 code which according the abi262// have either arguments or returned values placed in floating point registers,263// we use a set of helper functions. (This includes functions which return type264// complex which on Mips are returned in a pair of floating point registers).265//266// This is an encoding that we inherited from gcc.267// In Mips traditional O32, N32 ABI, floating point numbers are passed in268// floating point argument registers 1,2 only when the first and optionally269// the second arguments are float (sf) or double (df).270// For Mips16 we are only concerned with the situations where floating point271// arguments are being passed in floating point registers by the ABI, because272// Mips16 mode code cannot execute floating point instructions to load those273// values and hence helper functions are needed.274// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)275// the helper function suffixs for these are:276// 0, 1, 5, 9, 2, 6, 10277// this suffix can then be calculated as follows:278// for a given argument Arg:279// Arg1x, Arg2x = 1 : Arg is sf280// 2 : Arg is df281// 0: Arg is neither sf or df282// So this stub is the string for number Arg1x + Arg2x*4.283// However not all numbers between 0 and 10 are possible, we check anyway and284// assert if the impossible exists.285//286287unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber288(ArgListTy &Args) const {289unsigned int resultNum = 0;290if (Args.size() >= 1) {291Type *t = Args[0].Ty;292if (t->isFloatTy()) {293resultNum = 1;294}295else if (t->isDoubleTy()) {296resultNum = 2;297}298}299if (resultNum) {300if (Args.size() >=2) {301Type *t = Args[1].Ty;302if (t->isFloatTy()) {303resultNum += 4;304}305else if (t->isDoubleTy()) {306resultNum += 8;307}308}309}310return resultNum;311}312313//314// Prefixes are attached to stub numbers depending on the return type.315// return type: float sf_316// double df_317// single complex sc_318// double complext dc_319// others NO PREFIX320//321//322// The full name of a helper function is__mips16_call_stub +323// return type dependent prefix + stub number324//325// FIXME: This is something that probably should be in a different source file326// and perhaps done differently but my main purpose is to not waste runtime327// on something that we can enumerate in the source. Another possibility is328// to have a python script to generate these mapping tables. This will do329// for now. There are a whole series of helper function mapping arrays, one330// for each return type class as outlined above. There there are 11 possible331// entries. Ones with 0 are ones which should never be selected.332//333// All the arrays are similar except for ones which return neither334// sf, df, sc, dc, in which we only care about ones which have sf or df as a335// first parameter.336//337#define P_ "__mips16_call_stub_"338#define MAX_STUB_NUMBER 10339#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"340#define T P "0" , T1341#define P P_342static char const * vMips16Helper[MAX_STUB_NUMBER+1] =343{nullptr, T1 };344#undef P345#define P P_ "sf_"346static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =347{ T };348#undef P349#define P P_ "df_"350static char const * dfMips16Helper[MAX_STUB_NUMBER+1] =351{ T };352#undef P353#define P P_ "sc_"354static char const * scMips16Helper[MAX_STUB_NUMBER+1] =355{ T };356#undef P357#define P P_ "dc_"358static char const * dcMips16Helper[MAX_STUB_NUMBER+1] =359{ T };360#undef P361#undef P_362363364const char* Mips16TargetLowering::365getMips16HelperFunction366(Type* RetTy, ArgListTy &Args, bool &needHelper) const {367const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);368#ifndef NDEBUG369const unsigned int maxStubNum = 10;370assert(stubNum <= maxStubNum);371const bool validStubNum[maxStubNum+1] =372{true, true, true, false, false, true, true, false, false, true, true};373assert(validStubNum[stubNum]);374#endif375const char *result;376if (RetTy->isFloatTy()) {377result = sfMips16Helper[stubNum];378}379else if (RetTy ->isDoubleTy()) {380result = dfMips16Helper[stubNum];381} else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) {382// check if it's complex383if (SRetTy->getNumElements() == 2) {384if ((SRetTy->getElementType(0)->isFloatTy()) &&385(SRetTy->getElementType(1)->isFloatTy())) {386result = scMips16Helper[stubNum];387} else if ((SRetTy->getElementType(0)->isDoubleTy()) &&388(SRetTy->getElementType(1)->isDoubleTy())) {389result = dcMips16Helper[stubNum];390} else {391llvm_unreachable("Uncovered condition");392}393} else {394llvm_unreachable("Uncovered condition");395}396} else {397if (stubNum == 0) {398needHelper = false;399return "";400}401result = vMips16Helper[stubNum];402}403needHelper = true;404return result;405}406407void Mips16TargetLowering::408getOpndList(SmallVectorImpl<SDValue> &Ops,409std::deque< std::pair<unsigned, SDValue> > &RegsToPass,410bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,411bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,412SDValue Chain) const {413SelectionDAG &DAG = CLI.DAG;414MachineFunction &MF = DAG.getMachineFunction();415MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();416const char* Mips16HelperFunction = nullptr;417bool NeedMips16Helper = false;418419if (Subtarget.inMips16HardFloat()) {420//421// currently we don't have symbols tagged with the mips16 or mips32422// qualifier so we will assume that we don't know what kind it is.423// and generate the helper424//425bool LookupHelper = true;426if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {427Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };428429if (std::binary_search(std::begin(HardFloatLibCalls),430std::end(HardFloatLibCalls), Find))431LookupHelper = false;432else {433const char *Symbol = S->getSymbol();434Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };435const Mips16HardFloatInfo::FuncSignature *Signature =436Mips16HardFloatInfo::findFuncSignature(Symbol);437if (!IsPICCall && (Signature && (FuncInfo->StubsNeeded.find(Symbol) ==438FuncInfo->StubsNeeded.end()))) {439FuncInfo->StubsNeeded[Symbol] = Signature;440//441// S2 is normally saved if the stub is for a function which442// returns a float or double value and is not otherwise. This is443// because more work is required after the function the stub444// is calling completes, and so the stub cannot directly return445// and the stub has no stack space to store the return address so446// S2 is used for that purpose.447// In order to take advantage of not saving S2, we need to also448// optimize the call in the stub and this requires some further449// functionality in MipsAsmPrinter which we don't have yet.450// So for now we always save S2. The optimization will be done451// in a follow-on patch.452//453if (true || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))454FuncInfo->setSaveS2();455}456// one more look at list of intrinsics457const Mips16IntrinsicHelperType *Helper =458llvm::lower_bound(Mips16IntrinsicHelper, IntrinsicFind);459if (Helper != std::end(Mips16IntrinsicHelper) &&460*Helper == IntrinsicFind) {461Mips16HelperFunction = Helper->Helper;462NeedMips16Helper = true;463LookupHelper = false;464}465466}467} else if (GlobalAddressSDNode *G =468dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {469Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,470G->getGlobal()->getName().data() };471472if (std::binary_search(std::begin(HardFloatLibCalls),473std::end(HardFloatLibCalls), Find))474LookupHelper = false;475}476if (LookupHelper)477Mips16HelperFunction =478getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);479}480481SDValue JumpTarget = Callee;482483// T9 should contain the address of the callee function if484// -relocation-model=pic or it is an indirect call.485if (IsPICCall || !GlobalOrExternal) {486unsigned V0Reg = Mips::V0;487if (NeedMips16Helper) {488RegsToPass.push_front(std::make_pair(V0Reg, Callee));489JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction,490getPointerTy(DAG.getDataLayout()));491ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);492JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG,493MipsII::MO_GOT, Chain,494FuncInfo->callPtrInfo(MF, S->getSymbol()));495} else496RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));497}498499Ops.push_back(JumpTarget);500501MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,502InternalLinkage, IsCallReloc, CLI, Callee,503Chain);504}505506MachineBasicBlock *507Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,508MachineBasicBlock *BB) const {509if (DontExpandCondPseudos16)510return BB;511const TargetInstrInfo *TII = Subtarget.getInstrInfo();512DebugLoc DL = MI.getDebugLoc();513// To "insert" a SELECT_CC instruction, we actually have to insert the514// diamond control-flow pattern. The incoming instruction knows the515// destination vreg to set, the condition code register to branch on, the516// true/false values to select between, and a branch opcode to use.517const BasicBlock *LLVM_BB = BB->getBasicBlock();518MachineFunction::iterator It = ++BB->getIterator();519520// thisMBB:521// ...522// TrueVal = ...523// setcc r1, r2, r3524// bNE r1, r0, copy1MBB525// fallthrough --> copy0MBB526MachineBasicBlock *thisMBB = BB;527MachineFunction *F = BB->getParent();528MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);529MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);530F->insert(It, copy0MBB);531F->insert(It, sinkMBB);532533// Transfer the remainder of BB and its successor edges to sinkMBB.534sinkMBB->splice(sinkMBB->begin(), BB,535std::next(MachineBasicBlock::iterator(MI)), BB->end());536sinkMBB->transferSuccessorsAndUpdatePHIs(BB);537538// Next, add the true and fallthrough blocks as its successors.539BB->addSuccessor(copy0MBB);540BB->addSuccessor(sinkMBB);541542BuildMI(BB, DL, TII->get(Opc))543.addReg(MI.getOperand(3).getReg())544.addMBB(sinkMBB);545546// copy0MBB:547// %FalseValue = ...548// # fallthrough to sinkMBB549BB = copy0MBB;550551// Update machine-CFG edges552BB->addSuccessor(sinkMBB);553554// sinkMBB:555// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]556// ...557BB = sinkMBB;558559BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())560.addReg(MI.getOperand(1).getReg())561.addMBB(thisMBB)562.addReg(MI.getOperand(2).getReg())563.addMBB(copy0MBB);564565MI.eraseFromParent(); // The pseudo instruction is gone now.566return BB;567}568569MachineBasicBlock *570Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,571MachineBasicBlock *BB) const {572if (DontExpandCondPseudos16)573return BB;574const TargetInstrInfo *TII = Subtarget.getInstrInfo();575DebugLoc DL = MI.getDebugLoc();576// To "insert" a SELECT_CC instruction, we actually have to insert the577// diamond control-flow pattern. The incoming instruction knows the578// destination vreg to set, the condition code register to branch on, the579// true/false values to select between, and a branch opcode to use.580const BasicBlock *LLVM_BB = BB->getBasicBlock();581MachineFunction::iterator It = ++BB->getIterator();582583// thisMBB:584// ...585// TrueVal = ...586// setcc r1, r2, r3587// bNE r1, r0, copy1MBB588// fallthrough --> copy0MBB589MachineBasicBlock *thisMBB = BB;590MachineFunction *F = BB->getParent();591MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);592MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);593F->insert(It, copy0MBB);594F->insert(It, sinkMBB);595596// Transfer the remainder of BB and its successor edges to sinkMBB.597sinkMBB->splice(sinkMBB->begin(), BB,598std::next(MachineBasicBlock::iterator(MI)), BB->end());599sinkMBB->transferSuccessorsAndUpdatePHIs(BB);600601// Next, add the true and fallthrough blocks as its successors.602BB->addSuccessor(copy0MBB);603BB->addSuccessor(sinkMBB);604605BuildMI(BB, DL, TII->get(Opc2))606.addReg(MI.getOperand(3).getReg())607.addReg(MI.getOperand(4).getReg());608BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);609610// copy0MBB:611// %FalseValue = ...612// # fallthrough to sinkMBB613BB = copy0MBB;614615// Update machine-CFG edges616BB->addSuccessor(sinkMBB);617618// sinkMBB:619// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]620// ...621BB = sinkMBB;622623BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())624.addReg(MI.getOperand(1).getReg())625.addMBB(thisMBB)626.addReg(MI.getOperand(2).getReg())627.addMBB(copy0MBB);628629MI.eraseFromParent(); // The pseudo instruction is gone now.630return BB;631632}633634MachineBasicBlock *635Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,636MachineInstr &MI,637MachineBasicBlock *BB) const {638if (DontExpandCondPseudos16)639return BB;640const TargetInstrInfo *TII = Subtarget.getInstrInfo();641DebugLoc DL = MI.getDebugLoc();642// To "insert" a SELECT_CC instruction, we actually have to insert the643// diamond control-flow pattern. The incoming instruction knows the644// destination vreg to set, the condition code register to branch on, the645// true/false values to select between, and a branch opcode to use.646const BasicBlock *LLVM_BB = BB->getBasicBlock();647MachineFunction::iterator It = ++BB->getIterator();648649// thisMBB:650// ...651// TrueVal = ...652// setcc r1, r2, r3653// bNE r1, r0, copy1MBB654// fallthrough --> copy0MBB655MachineBasicBlock *thisMBB = BB;656MachineFunction *F = BB->getParent();657MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);658MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);659F->insert(It, copy0MBB);660F->insert(It, sinkMBB);661662// Transfer the remainder of BB and its successor edges to sinkMBB.663sinkMBB->splice(sinkMBB->begin(), BB,664std::next(MachineBasicBlock::iterator(MI)), BB->end());665sinkMBB->transferSuccessorsAndUpdatePHIs(BB);666667// Next, add the true and fallthrough blocks as its successors.668BB->addSuccessor(copy0MBB);669BB->addSuccessor(sinkMBB);670671BuildMI(BB, DL, TII->get(Opc2))672.addReg(MI.getOperand(3).getReg())673.addImm(MI.getOperand(4).getImm());674BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);675676// copy0MBB:677// %FalseValue = ...678// # fallthrough to sinkMBB679BB = copy0MBB;680681// Update machine-CFG edges682BB->addSuccessor(sinkMBB);683684// sinkMBB:685// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]686// ...687BB = sinkMBB;688689BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())690.addReg(MI.getOperand(1).getReg())691.addMBB(thisMBB)692.addReg(MI.getOperand(2).getReg())693.addMBB(copy0MBB);694695MI.eraseFromParent(); // The pseudo instruction is gone now.696return BB;697698}699700MachineBasicBlock *701Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,702MachineInstr &MI,703MachineBasicBlock *BB) const {704if (DontExpandCondPseudos16)705return BB;706const TargetInstrInfo *TII = Subtarget.getInstrInfo();707Register regX = MI.getOperand(0).getReg();708Register regY = MI.getOperand(1).getReg();709MachineBasicBlock *target = MI.getOperand(2).getMBB();710BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))711.addReg(regX)712.addReg(regY);713BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);714MI.eraseFromParent(); // The pseudo instruction is gone now.715return BB;716}717718MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(719unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,720MachineInstr &MI, MachineBasicBlock *BB) const {721if (DontExpandCondPseudos16)722return BB;723const TargetInstrInfo *TII = Subtarget.getInstrInfo();724Register regX = MI.getOperand(0).getReg();725int64_t imm = MI.getOperand(1).getImm();726MachineBasicBlock *target = MI.getOperand(2).getMBB();727unsigned CmpOpc;728if (isUInt<8>(imm))729CmpOpc = CmpiOpc;730else if ((!ImmSigned && isUInt<16>(imm)) ||731(ImmSigned && isInt<16>(imm)))732CmpOpc = CmpiXOpc;733else734llvm_unreachable("immediate field not usable");735BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);736BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);737MI.eraseFromParent(); // The pseudo instruction is gone now.738return BB;739}740741static unsigned Mips16WhichOp8uOr16simm742(unsigned shortOp, unsigned longOp, int64_t Imm) {743if (isUInt<8>(Imm))744return shortOp;745else if (isInt<16>(Imm))746return longOp;747else748llvm_unreachable("immediate field not usable");749}750751MachineBasicBlock *752Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,753MachineBasicBlock *BB) const {754if (DontExpandCondPseudos16)755return BB;756const TargetInstrInfo *TII = Subtarget.getInstrInfo();757Register CC = MI.getOperand(0).getReg();758Register regX = MI.getOperand(1).getReg();759Register regY = MI.getOperand(2).getReg();760BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))761.addReg(regX)762.addReg(regY);763BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)764.addReg(Mips::T8);765MI.eraseFromParent(); // The pseudo instruction is gone now.766return BB;767}768769MachineBasicBlock *770Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,771MachineInstr &MI,772MachineBasicBlock *BB) const {773if (DontExpandCondPseudos16)774return BB;775const TargetInstrInfo *TII = Subtarget.getInstrInfo();776Register CC = MI.getOperand(0).getReg();777Register regX = MI.getOperand(1).getReg();778int64_t Imm = MI.getOperand(2).getImm();779unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);780BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);781BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)782.addReg(Mips::T8);783MI.eraseFromParent(); // The pseudo instruction is gone now.784return BB;785786}787788789