731 lines · cpp
1//===-- Mips16ISelLowering.h - Mips16 DAG Lowering Interface ----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Subclass of MipsTargetLowering specialized for mips16.10//11//===----------------------------------------------------------------------===//12#include "Mips16ISelLowering.h"13#include "MCTargetDesc/MipsBaseInfo.h"14#include "Mips16HardFloatInfo.h"15#include "MipsMachineFunction.h"16#include "MipsRegisterInfo.h"17#include "MipsTargetMachine.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/TargetInstrInfo.h"20#include "llvm/Support/CommandLine.h"21 22using namespace llvm;23 24#define DEBUG_TYPE "mips-lower"25 26static cl::opt<bool> DontExpandCondPseudos16(27 "mips16-dont-expand-cond-pseudo",28 cl::init(false),29 cl::desc("Don't expand conditional move related "30 "pseudos for Mips 16"),31 cl::Hidden);32 33namespace {34struct Mips16IntrinsicHelperType{35 const char* Name;36 const char* Helper;37 38 bool operator<(const Mips16IntrinsicHelperType &RHS) const {39 return std::strcmp(Name, RHS.Name) < 0;40 }41 bool operator==(const Mips16IntrinsicHelperType &RHS) const {42 return std::strcmp(Name, RHS.Name) == 0;43 }44};45} // namespace46 47static const Mips16IntrinsicHelperType Mips16IntrinsicHelper[] = {48 {"__fixunsdfsi", "__mips16_call_stub_2" },49 {"ceil", "__mips16_call_stub_df_2"},50 {"ceilf", "__mips16_call_stub_sf_1"},51 {"copysign", "__mips16_call_stub_df_10"},52 {"copysignf", "__mips16_call_stub_sf_5"},53 {"cos", "__mips16_call_stub_df_2"},54 {"cosf", "__mips16_call_stub_sf_1"},55 {"exp2", "__mips16_call_stub_df_2"},56 {"exp2f", "__mips16_call_stub_sf_1"},57 {"floor", "__mips16_call_stub_df_2"},58 {"floorf", "__mips16_call_stub_sf_1"},59 {"log2", "__mips16_call_stub_df_2"},60 {"log2f", "__mips16_call_stub_sf_1"},61 {"nearbyint", "__mips16_call_stub_df_2"},62 {"nearbyintf", "__mips16_call_stub_sf_1"},63 {"rint", "__mips16_call_stub_df_2"},64 {"rintf", "__mips16_call_stub_sf_1"},65 {"sin", "__mips16_call_stub_df_2"},66 {"sinf", "__mips16_call_stub_sf_1"},67 {"sqrt", "__mips16_call_stub_df_2"},68 {"sqrtf", "__mips16_call_stub_sf_1"},69 {"trunc", "__mips16_call_stub_df_2"},70 {"truncf", "__mips16_call_stub_sf_1"},71};72 73Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM,74 const MipsSubtarget &STI)75 : MipsTargetLowering(TM, STI) {76 77 // Set up the register classes78 addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass);79 80 setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, LibCall);81 setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, LibCall);82 setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, LibCall);83 setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, LibCall);84 setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, LibCall);85 setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, LibCall);86 setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, LibCall);87 setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, LibCall);88 setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, LibCall);89 setOperationAction(ISD::ATOMIC_LOAD_MIN, MVT::i32, LibCall);90 setOperationAction(ISD::ATOMIC_LOAD_MAX, MVT::i32, LibCall);91 setOperationAction(ISD::ATOMIC_LOAD_UMIN, MVT::i32, LibCall);92 setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, LibCall);93 94 setOperationAction(ISD::ROTR, MVT::i32, Expand);95 setOperationAction(ISD::ROTR, MVT::i64, Expand);96 setOperationAction(ISD::BSWAP, MVT::i32, Expand);97 setOperationAction(ISD::BSWAP, MVT::i64, Expand);98 99 computeRegisterProperties(STI.getRegisterInfo());100}101 102const MipsTargetLowering *103llvm::createMips16TargetLowering(const MipsTargetMachine &TM,104 const MipsSubtarget &STI) {105 return new Mips16TargetLowering(TM, STI);106}107 108bool Mips16TargetLowering::allowsMisalignedMemoryAccesses(109 EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {110 return false;111}112 113MachineBasicBlock *114Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,115 MachineBasicBlock *BB) const {116 switch (MI.getOpcode()) {117 default:118 return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);119 case Mips::SelBeqZ:120 return emitSel16(Mips::BeqzRxImm16, MI, BB);121 case Mips::SelBneZ:122 return emitSel16(Mips::BnezRxImm16, MI, BB);123 case Mips::SelTBteqZCmpi:124 return emitSeliT16(Mips::Bteqz16, Mips::CmpiRxImmX16, MI, BB);125 case Mips::SelTBteqZSlti:126 return emitSeliT16(Mips::Bteqz16, Mips::SltiRxImmX16, MI, BB);127 case Mips::SelTBteqZSltiu:128 return emitSeliT16(Mips::Bteqz16, Mips::SltiuRxImmX16, MI, BB);129 case Mips::SelTBtneZCmpi:130 return emitSeliT16(Mips::Btnez16, Mips::CmpiRxImmX16, MI, BB);131 case Mips::SelTBtneZSlti:132 return emitSeliT16(Mips::Btnez16, Mips::SltiRxImmX16, MI, BB);133 case Mips::SelTBtneZSltiu:134 return emitSeliT16(Mips::Btnez16, Mips::SltiuRxImmX16, MI, BB);135 case Mips::SelTBteqZCmp:136 return emitSelT16(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);137 case Mips::SelTBteqZSlt:138 return emitSelT16(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);139 case Mips::SelTBteqZSltu:140 return emitSelT16(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);141 case Mips::SelTBtneZCmp:142 return emitSelT16(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);143 case Mips::SelTBtneZSlt:144 return emitSelT16(Mips::Btnez16, Mips::SltRxRy16, MI, BB);145 case Mips::SelTBtneZSltu:146 return emitSelT16(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);147 case Mips::BteqzT8CmpX16:148 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::CmpRxRy16, MI, BB);149 case Mips::BteqzT8SltX16:150 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltRxRy16, MI, BB);151 case Mips::BteqzT8SltuX16:152 // TBD: figure out a way to get this or remove the instruction153 // altogether.154 return emitFEXT_T8I816_ins(Mips::Bteqz16, Mips::SltuRxRy16, MI, BB);155 case Mips::BtnezT8CmpX16:156 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::CmpRxRy16, MI, BB);157 case Mips::BtnezT8SltX16:158 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltRxRy16, MI, BB);159 case Mips::BtnezT8SltuX16:160 // TBD: figure out a way to get this or remove the instruction161 // altogether.162 return emitFEXT_T8I816_ins(Mips::Btnez16, Mips::SltuRxRy16, MI, BB);163 case Mips::BteqzT8CmpiX16: return emitFEXT_T8I8I16_ins(164 Mips::Bteqz16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);165 case Mips::BteqzT8SltiX16: return emitFEXT_T8I8I16_ins(166 Mips::Bteqz16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);167 case Mips::BteqzT8SltiuX16: return emitFEXT_T8I8I16_ins(168 Mips::Bteqz16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);169 case Mips::BtnezT8CmpiX16: return emitFEXT_T8I8I16_ins(170 Mips::Btnez16, Mips::CmpiRxImm16, Mips::CmpiRxImmX16, false, MI, BB);171 case Mips::BtnezT8SltiX16: return emitFEXT_T8I8I16_ins(172 Mips::Btnez16, Mips::SltiRxImm16, Mips::SltiRxImmX16, true, MI, BB);173 case Mips::BtnezT8SltiuX16: return emitFEXT_T8I8I16_ins(174 Mips::Btnez16, Mips::SltiuRxImm16, Mips::SltiuRxImmX16, false, MI, BB);175 break;176 case Mips::SltCCRxRy16:177 return emitFEXT_CCRX16_ins(Mips::SltRxRy16, MI, BB);178 break;179 case Mips::SltiCCRxImmX16:180 return emitFEXT_CCRXI16_ins181 (Mips::SltiRxImm16, Mips::SltiRxImmX16, MI, BB);182 case Mips::SltiuCCRxImmX16:183 return emitFEXT_CCRXI16_ins184 (Mips::SltiuRxImm16, Mips::SltiuRxImmX16, MI, BB);185 case Mips::SltuCCRxRy16:186 return emitFEXT_CCRX16_ins187 (Mips::SltuRxRy16, MI, BB);188 }189}190 191bool Mips16TargetLowering::isEligibleForTailCallOptimization(192 const CCState &CCInfo, unsigned NextStackOffset,193 const MipsFunctionInfo &FI) const {194 // No tail call optimization for mips16.195 return false;196}197 198//199// The Mips16 hard float is a crazy quilt inherited from gcc. I have a much200// cleaner way to do all of this but it will have to wait until the traditional201// gcc mechanism is completed.202//203// For Pic, in order for Mips16 code to call Mips32 code which according the abi204// have either arguments or returned values placed in floating point registers,205// we use a set of helper functions. (This includes functions which return type206// complex which on Mips are returned in a pair of floating point registers).207//208// This is an encoding that we inherited from gcc.209// In Mips traditional O32, N32 ABI, floating point numbers are passed in210// floating point argument registers 1,2 only when the first and optionally211// the second arguments are float (sf) or double (df).212// For Mips16 we are only concerned with the situations where floating point213// arguments are being passed in floating point registers by the ABI, because214// Mips16 mode code cannot execute floating point instructions to load those215// values and hence helper functions are needed.216// The possibilities are (), (sf), (sf, sf), (sf, df), (df), (df, sf), (df, df)217// the helper function suffixs for these are:218// 0, 1, 5, 9, 2, 6, 10219// this suffix can then be calculated as follows:220// for a given argument Arg:221// Arg1x, Arg2x = 1 : Arg is sf222// 2 : Arg is df223// 0: Arg is neither sf or df224// So this stub is the string for number Arg1x + Arg2x*4.225// However not all numbers between 0 and 10 are possible, we check anyway and226// assert if the impossible exists.227//228 229unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber230 (ArgListTy &Args) const {231 unsigned int resultNum = 0;232 if (Args.size() >= 1) {233 Type *t = Args[0].Ty;234 if (t->isFloatTy()) {235 resultNum = 1;236 }237 else if (t->isDoubleTy()) {238 resultNum = 2;239 }240 }241 if (resultNum) {242 if (Args.size() >=2) {243 Type *t = Args[1].Ty;244 if (t->isFloatTy()) {245 resultNum += 4;246 }247 else if (t->isDoubleTy()) {248 resultNum += 8;249 }250 }251 }252 return resultNum;253}254 255//256// Prefixes are attached to stub numbers depending on the return type.257// return type: float sf_258// double df_259// single complex sc_260// double complext dc_261// others NO PREFIX262//263//264// The full name of a helper function is__mips16_call_stub +265// return type dependent prefix + stub number266//267// FIXME: This is something that probably should be in a different source file268// and perhaps done differently but my main purpose is to not waste runtime269// on something that we can enumerate in the source. Another possibility is270// to have a python script to generate these mapping tables. This will do271// for now. There are a whole series of helper function mapping arrays, one272// for each return type class as outlined above. There there are 11 possible273// entries. Ones with 0 are ones which should never be selected.274//275// All the arrays are similar except for ones which return neither276// sf, df, sc, dc, in which we only care about ones which have sf or df as a277// first parameter.278//279#define P_ "__mips16_call_stub_"280#define MAX_STUB_NUMBER 10281#define T1 P "1", P "2", 0, 0, P "5", P "6", 0, 0, P "9", P "10"282#define T P "0" , T1283#define P P_284static char const * vMips16Helper[MAX_STUB_NUMBER+1] =285 {nullptr, T1 };286#undef P287#define P P_ "sf_"288static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =289 { T };290#undef P291#define P P_ "df_"292static char const * dfMips16Helper[MAX_STUB_NUMBER+1] =293 { T };294#undef P295#define P P_ "sc_"296static char const * scMips16Helper[MAX_STUB_NUMBER+1] =297 { T };298#undef P299#define P P_ "dc_"300static char const * dcMips16Helper[MAX_STUB_NUMBER+1] =301 { T };302#undef P303#undef P_304 305 306const char* Mips16TargetLowering::307 getMips16HelperFunction308 (Type* RetTy, ArgListTy &Args, bool &needHelper) const {309 const unsigned int stubNum = getMips16HelperFunctionStubNumber(Args);310#ifndef NDEBUG311 const unsigned int maxStubNum = 10;312 assert(stubNum <= maxStubNum);313 const bool validStubNum[maxStubNum+1] =314 {true, true, true, false, false, true, true, false, false, true, true};315 assert(validStubNum[stubNum]);316#endif317 const char *result;318 if (RetTy->isFloatTy()) {319 result = sfMips16Helper[stubNum];320 }321 else if (RetTy ->isDoubleTy()) {322 result = dfMips16Helper[stubNum];323 } else if (StructType *SRetTy = dyn_cast<StructType>(RetTy)) {324 // check if it's complex325 if (SRetTy->getNumElements() == 2) {326 if ((SRetTy->getElementType(0)->isFloatTy()) &&327 (SRetTy->getElementType(1)->isFloatTy())) {328 result = scMips16Helper[stubNum];329 } else if ((SRetTy->getElementType(0)->isDoubleTy()) &&330 (SRetTy->getElementType(1)->isDoubleTy())) {331 result = dcMips16Helper[stubNum];332 } else {333 llvm_unreachable("Uncovered condition");334 }335 } else {336 llvm_unreachable("Uncovered condition");337 }338 } else {339 if (stubNum == 0) {340 needHelper = false;341 return "";342 }343 result = vMips16Helper[stubNum];344 }345 needHelper = true;346 return result;347}348 349static bool isMips16HardFloatLibcall(StringRef Name) {350 // FIXME: Use getSupportedLibcallImpl instead of blindly parsing the name.351 iota_range<RTLIB::LibcallImpl> ParsedLibcalls =352 RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(Name);353 return !ParsedLibcalls.empty() &&354 binary_search(MipsSubtarget::HardFloatLibCalls,355 *ParsedLibcalls.begin());356}357 358void Mips16TargetLowering::359getOpndList(SmallVectorImpl<SDValue> &Ops,360 std::deque< std::pair<unsigned, SDValue> > &RegsToPass,361 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,362 bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,363 SDValue Chain) const {364 SelectionDAG &DAG = CLI.DAG;365 MachineFunction &MF = DAG.getMachineFunction();366 MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();367 const char* Mips16HelperFunction = nullptr;368 bool NeedMips16Helper = false;369 370 if (Subtarget.inMips16HardFloat()) {371 //372 // currently we don't have symbols tagged with the mips16 or mips32373 // qualifier so we will assume that we don't know what kind it is.374 // and generate the helper375 //376 bool LookupHelper = true;377 if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {378 if (isMips16HardFloatLibcall(S->getSymbol()))379 LookupHelper = false;380 else {381 const char *Symbol = S->getSymbol();382 Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" };383 const Mips16HardFloatInfo::FuncSignature *Signature =384 Mips16HardFloatInfo::findFuncSignature(Symbol);385 if (!IsPICCall && Signature &&386 FuncInfo->StubsNeeded.try_emplace(Symbol, Signature).second) {387 //388 // S2 is normally saved if the stub is for a function which389 // returns a float or double value and is not otherwise. This is390 // because more work is required after the function the stub391 // is calling completes, and so the stub cannot directly return392 // and the stub has no stack space to store the return address so393 // S2 is used for that purpose.394 // In order to take advantage of not saving S2, we need to also395 // optimize the call in the stub and this requires some further396 // functionality in MipsAsmPrinter which we don't have yet.397 // So for now we always save S2. The optimization will be done398 // in a follow-on patch.399 //400 if (true || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet))401 FuncInfo->setSaveS2();402 }403 // one more look at list of intrinsics404 const Mips16IntrinsicHelperType *Helper =405 llvm::lower_bound(Mips16IntrinsicHelper, IntrinsicFind);406 if (Helper != std::end(Mips16IntrinsicHelper) &&407 *Helper == IntrinsicFind) {408 Mips16HelperFunction = Helper->Helper;409 NeedMips16Helper = true;410 LookupHelper = false;411 }412 413 }414 } else if (GlobalAddressSDNode *G =415 dyn_cast<GlobalAddressSDNode>(CLI.Callee)) {416 417 if (isMips16HardFloatLibcall(G->getGlobal()->getName()))418 LookupHelper = false;419 }420 if (LookupHelper)421 Mips16HelperFunction =422 getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);423 }424 425 SDValue JumpTarget = Callee;426 427 // T9 should contain the address of the callee function if428 // -relocation-model=pic or it is an indirect call.429 if (IsPICCall || !GlobalOrExternal) {430 unsigned V0Reg = Mips::V0;431 if (NeedMips16Helper) {432 RegsToPass.push_front(std::make_pair(V0Reg, Callee));433 JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction,434 getPointerTy(DAG.getDataLayout()));435 ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget);436 JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG,437 MipsII::MO_GOT, Chain,438 FuncInfo->callPtrInfo(MF, S->getSymbol()));439 } else440 RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee));441 }442 443 Ops.push_back(JumpTarget);444 445 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal,446 InternalLinkage, IsCallReloc, CLI, Callee,447 Chain);448}449 450MachineBasicBlock *451Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,452 MachineBasicBlock *BB) const {453 if (DontExpandCondPseudos16)454 return BB;455 const TargetInstrInfo *TII = Subtarget.getInstrInfo();456 DebugLoc DL = MI.getDebugLoc();457 // To "insert" a SELECT_CC instruction, we actually have to insert the458 // diamond control-flow pattern. The incoming instruction knows the459 // destination vreg to set, the condition code register to branch on, the460 // true/false values to select between, and a branch opcode to use.461 const BasicBlock *LLVM_BB = BB->getBasicBlock();462 MachineFunction::iterator It = ++BB->getIterator();463 464 // thisMBB:465 // ...466 // TrueVal = ...467 // setcc r1, r2, r3468 // bNE r1, r0, copy1MBB469 // fallthrough --> copy0MBB470 MachineBasicBlock *thisMBB = BB;471 MachineFunction *F = BB->getParent();472 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);473 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);474 F->insert(It, copy0MBB);475 F->insert(It, sinkMBB);476 477 // Transfer the remainder of BB and its successor edges to sinkMBB.478 sinkMBB->splice(sinkMBB->begin(), BB,479 std::next(MachineBasicBlock::iterator(MI)), BB->end());480 sinkMBB->transferSuccessorsAndUpdatePHIs(BB);481 482 // Next, add the true and fallthrough blocks as its successors.483 BB->addSuccessor(copy0MBB);484 BB->addSuccessor(sinkMBB);485 486 BuildMI(BB, DL, TII->get(Opc))487 .addReg(MI.getOperand(3).getReg())488 .addMBB(sinkMBB);489 490 // copy0MBB:491 // %FalseValue = ...492 // # fallthrough to sinkMBB493 BB = copy0MBB;494 495 // Update machine-CFG edges496 BB->addSuccessor(sinkMBB);497 498 // sinkMBB:499 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]500 // ...501 BB = sinkMBB;502 503 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())504 .addReg(MI.getOperand(1).getReg())505 .addMBB(thisMBB)506 .addReg(MI.getOperand(2).getReg())507 .addMBB(copy0MBB);508 509 MI.eraseFromParent(); // The pseudo instruction is gone now.510 return BB;511}512 513MachineBasicBlock *514Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,515 MachineBasicBlock *BB) const {516 if (DontExpandCondPseudos16)517 return BB;518 const TargetInstrInfo *TII = Subtarget.getInstrInfo();519 DebugLoc DL = MI.getDebugLoc();520 // To "insert" a SELECT_CC instruction, we actually have to insert the521 // diamond control-flow pattern. The incoming instruction knows the522 // destination vreg to set, the condition code register to branch on, the523 // true/false values to select between, and a branch opcode to use.524 const BasicBlock *LLVM_BB = BB->getBasicBlock();525 MachineFunction::iterator It = ++BB->getIterator();526 527 // thisMBB:528 // ...529 // TrueVal = ...530 // setcc r1, r2, r3531 // bNE r1, r0, copy1MBB532 // fallthrough --> copy0MBB533 MachineBasicBlock *thisMBB = BB;534 MachineFunction *F = BB->getParent();535 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);536 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);537 F->insert(It, copy0MBB);538 F->insert(It, sinkMBB);539 540 // Transfer the remainder of BB and its successor edges to sinkMBB.541 sinkMBB->splice(sinkMBB->begin(), BB,542 std::next(MachineBasicBlock::iterator(MI)), BB->end());543 sinkMBB->transferSuccessorsAndUpdatePHIs(BB);544 545 // Next, add the true and fallthrough blocks as its successors.546 BB->addSuccessor(copy0MBB);547 BB->addSuccessor(sinkMBB);548 549 BuildMI(BB, DL, TII->get(Opc2))550 .addReg(MI.getOperand(3).getReg())551 .addReg(MI.getOperand(4).getReg());552 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);553 554 // copy0MBB:555 // %FalseValue = ...556 // # fallthrough to sinkMBB557 BB = copy0MBB;558 559 // Update machine-CFG edges560 BB->addSuccessor(sinkMBB);561 562 // sinkMBB:563 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]564 // ...565 BB = sinkMBB;566 567 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())568 .addReg(MI.getOperand(1).getReg())569 .addMBB(thisMBB)570 .addReg(MI.getOperand(2).getReg())571 .addMBB(copy0MBB);572 573 MI.eraseFromParent(); // The pseudo instruction is gone now.574 return BB;575 576}577 578MachineBasicBlock *579Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,580 MachineInstr &MI,581 MachineBasicBlock *BB) const {582 if (DontExpandCondPseudos16)583 return BB;584 const TargetInstrInfo *TII = Subtarget.getInstrInfo();585 DebugLoc DL = MI.getDebugLoc();586 // To "insert" a SELECT_CC instruction, we actually have to insert the587 // diamond control-flow pattern. The incoming instruction knows the588 // destination vreg to set, the condition code register to branch on, the589 // true/false values to select between, and a branch opcode to use.590 const BasicBlock *LLVM_BB = BB->getBasicBlock();591 MachineFunction::iterator It = ++BB->getIterator();592 593 // thisMBB:594 // ...595 // TrueVal = ...596 // setcc r1, r2, r3597 // bNE r1, r0, copy1MBB598 // fallthrough --> copy0MBB599 MachineBasicBlock *thisMBB = BB;600 MachineFunction *F = BB->getParent();601 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);602 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);603 F->insert(It, copy0MBB);604 F->insert(It, sinkMBB);605 606 // Transfer the remainder of BB and its successor edges to sinkMBB.607 sinkMBB->splice(sinkMBB->begin(), BB,608 std::next(MachineBasicBlock::iterator(MI)), BB->end());609 sinkMBB->transferSuccessorsAndUpdatePHIs(BB);610 611 // Next, add the true and fallthrough blocks as its successors.612 BB->addSuccessor(copy0MBB);613 BB->addSuccessor(sinkMBB);614 615 BuildMI(BB, DL, TII->get(Opc2))616 .addReg(MI.getOperand(3).getReg())617 .addImm(MI.getOperand(4).getImm());618 BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);619 620 // copy0MBB:621 // %FalseValue = ...622 // # fallthrough to sinkMBB623 BB = copy0MBB;624 625 // Update machine-CFG edges626 BB->addSuccessor(sinkMBB);627 628 // sinkMBB:629 // %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]630 // ...631 BB = sinkMBB;632 633 BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())634 .addReg(MI.getOperand(1).getReg())635 .addMBB(thisMBB)636 .addReg(MI.getOperand(2).getReg())637 .addMBB(copy0MBB);638 639 MI.eraseFromParent(); // The pseudo instruction is gone now.640 return BB;641 642}643 644MachineBasicBlock *645Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,646 MachineInstr &MI,647 MachineBasicBlock *BB) const {648 if (DontExpandCondPseudos16)649 return BB;650 const TargetInstrInfo *TII = Subtarget.getInstrInfo();651 Register regX = MI.getOperand(0).getReg();652 Register regY = MI.getOperand(1).getReg();653 MachineBasicBlock *target = MI.getOperand(2).getMBB();654 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))655 .addReg(regX)656 .addReg(regY);657 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);658 MI.eraseFromParent(); // The pseudo instruction is gone now.659 return BB;660}661 662MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(663 unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,664 MachineInstr &MI, MachineBasicBlock *BB) const {665 if (DontExpandCondPseudos16)666 return BB;667 const TargetInstrInfo *TII = Subtarget.getInstrInfo();668 Register regX = MI.getOperand(0).getReg();669 int64_t imm = MI.getOperand(1).getImm();670 MachineBasicBlock *target = MI.getOperand(2).getMBB();671 unsigned CmpOpc;672 if (isUInt<8>(imm))673 CmpOpc = CmpiOpc;674 else if ((!ImmSigned && isUInt<16>(imm)) ||675 (ImmSigned && isInt<16>(imm)))676 CmpOpc = CmpiXOpc;677 else678 llvm_unreachable("immediate field not usable");679 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);680 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);681 MI.eraseFromParent(); // The pseudo instruction is gone now.682 return BB;683}684 685static unsigned Mips16WhichOp8uOr16simm686 (unsigned shortOp, unsigned longOp, int64_t Imm) {687 if (isUInt<8>(Imm))688 return shortOp;689 else if (isInt<16>(Imm))690 return longOp;691 else692 llvm_unreachable("immediate field not usable");693}694 695MachineBasicBlock *696Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,697 MachineBasicBlock *BB) const {698 if (DontExpandCondPseudos16)699 return BB;700 const TargetInstrInfo *TII = Subtarget.getInstrInfo();701 Register CC = MI.getOperand(0).getReg();702 Register regX = MI.getOperand(1).getReg();703 Register regY = MI.getOperand(2).getReg();704 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))705 .addReg(regX)706 .addReg(regY);707 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)708 .addReg(Mips::T8);709 MI.eraseFromParent(); // The pseudo instruction is gone now.710 return BB;711}712 713MachineBasicBlock *714Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,715 MachineInstr &MI,716 MachineBasicBlock *BB) const {717 if (DontExpandCondPseudos16)718 return BB;719 const TargetInstrInfo *TII = Subtarget.getInstrInfo();720 Register CC = MI.getOperand(0).getReg();721 Register regX = MI.getOperand(1).getReg();722 int64_t Imm = MI.getOperand(2).getImm();723 unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);724 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);725 BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)726 .addReg(Mips::T8);727 MI.eraseFromParent(); // The pseudo instruction is gone now.728 return BB;729 730}731