10b57cec5SDimitry Andric //===-- MipsSEISelDAGToDAG.cpp - A Dag to Dag Inst Selector for MipsSE ----===// 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 MipsDAGToDAGISel specialized for mips32/64. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MipsSEISelDAGToDAG.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/MipsBaseInfo.h" 150b57cec5SDimitry Andric #include "Mips.h" 160b57cec5SDimitry Andric #include "MipsAnalyzeImmediate.h" 170b57cec5SDimitry Andric #include "MipsMachineFunction.h" 180b57cec5SDimitry Andric #include "MipsRegisterInfo.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGNodes.h" 250b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 260b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 270b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 280b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 290b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 30480093f4SDimitry Andric #include "llvm/IR/IntrinsicsMips.h" 310b57cec5SDimitry Andric #include "llvm/IR/Type.h" 320b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 350b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric #define DEBUG_TYPE "mips-isel" 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 4181ad6265SDimitry Andric Subtarget = &MF.getSubtarget<MipsSubtarget>(); 420b57cec5SDimitry Andric if (Subtarget->inMips16Mode()) 430b57cec5SDimitry Andric return false; 440b57cec5SDimitry Andric return MipsDAGToDAGISel::runOnMachineFunction(MF); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470fca6ea1SDimitry Andric void MipsSEDAGToDAGISelLegacy::getAnalysisUsage(AnalysisUsage &AU) const { 480b57cec5SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 490fca6ea1SDimitry Andric SelectionDAGISelLegacy::getAnalysisUsage(AU); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, 530b57cec5SDimitry Andric MachineFunction &MF) { 540b57cec5SDimitry Andric MachineInstrBuilder MIB(MF, &MI); 550b57cec5SDimitry Andric unsigned Mask = MI.getOperand(1).getImm(); 560b57cec5SDimitry Andric unsigned Flag = 570b57cec5SDimitry Andric IsDef ? RegState::ImplicitDefine : RegState::Implicit | RegState::Undef; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric if (Mask & 1) 600b57cec5SDimitry Andric MIB.addReg(Mips::DSPPos, Flag); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric if (Mask & 2) 630b57cec5SDimitry Andric MIB.addReg(Mips::DSPSCount, Flag); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric if (Mask & 4) 660b57cec5SDimitry Andric MIB.addReg(Mips::DSPCarry, Flag); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric if (Mask & 8) 690b57cec5SDimitry Andric MIB.addReg(Mips::DSPOutFlag, Flag); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric if (Mask & 16) 720b57cec5SDimitry Andric MIB.addReg(Mips::DSPCCond, Flag); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric if (Mask & 32) 750b57cec5SDimitry Andric MIB.addReg(Mips::DSPEFI, Flag); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric unsigned MipsSEDAGToDAGISel::getMSACtrlReg(const SDValue RegIdx) const { 791db9f3b2SDimitry Andric uint64_t RegNum = RegIdx->getAsZExtVal(); 800b57cec5SDimitry Andric return Mips::MSACtrlRegClass.getRegister(RegNum); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, 840b57cec5SDimitry Andric const MachineInstr& MI) { 850b57cec5SDimitry Andric unsigned DstReg = 0, ZeroReg = 0; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric // Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0". 880b57cec5SDimitry Andric if ((MI.getOpcode() == Mips::ADDiu) && 890b57cec5SDimitry Andric (MI.getOperand(1).getReg() == Mips::ZERO) && 900b57cec5SDimitry Andric (MI.getOperand(2).isImm()) && 910b57cec5SDimitry Andric (MI.getOperand(2).getImm() == 0)) { 920b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 930b57cec5SDimitry Andric ZeroReg = Mips::ZERO; 940b57cec5SDimitry Andric } else if ((MI.getOpcode() == Mips::DADDiu) && 950b57cec5SDimitry Andric (MI.getOperand(1).getReg() == Mips::ZERO_64) && 960b57cec5SDimitry Andric (MI.getOperand(2).isImm()) && 970b57cec5SDimitry Andric (MI.getOperand(2).getImm() == 0)) { 980b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 990b57cec5SDimitry Andric ZeroReg = Mips::ZERO_64; 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric if (!DstReg) 1030b57cec5SDimitry Andric return false; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // Replace uses with ZeroReg. 1060b57cec5SDimitry Andric for (MachineRegisterInfo::use_iterator U = MRI->use_begin(DstReg), 1070b57cec5SDimitry Andric E = MRI->use_end(); U != E;) { 1080b57cec5SDimitry Andric MachineOperand &MO = *U; 1090b57cec5SDimitry Andric unsigned OpNo = U.getOperandNo(); 1100b57cec5SDimitry Andric MachineInstr *MI = MO.getParent(); 1110b57cec5SDimitry Andric ++U; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // Do not replace if it is a phi's operand or is tied to def operand. 1140b57cec5SDimitry Andric if (MI->isPHI() || MI->isRegTiedToDefOperand(OpNo) || MI->isPseudo()) 1150b57cec5SDimitry Andric continue; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // Also, we have to check that the register class of the operand 1180b57cec5SDimitry Andric // contains the zero register. 1190b57cec5SDimitry Andric if (!MRI->getRegClass(MO.getReg())->contains(ZeroReg)) 1200b57cec5SDimitry Andric continue; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric MO.setReg(ZeroReg); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric return true; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1288bcb0991SDimitry Andric void MipsSEDAGToDAGISel::emitMCountABI(MachineInstr &MI, MachineBasicBlock &MBB, 1298bcb0991SDimitry Andric MachineFunction &MF) { 1308bcb0991SDimitry Andric MachineInstrBuilder MIB(MF, &MI); 1318bcb0991SDimitry Andric if (!Subtarget->isABI_O32()) { // N32, N64 1328bcb0991SDimitry Andric // Save current return address. 1338bcb0991SDimitry Andric BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Mips::OR64)) 1348bcb0991SDimitry Andric .addDef(Mips::AT_64) 1358bcb0991SDimitry Andric .addUse(Mips::RA_64, RegState::Undef) 1368bcb0991SDimitry Andric .addUse(Mips::ZERO_64); 1378bcb0991SDimitry Andric // Stops instruction above from being removed later on. 1388bcb0991SDimitry Andric MIB.addUse(Mips::AT_64, RegState::Implicit); 1398bcb0991SDimitry Andric } else { // O32 1408bcb0991SDimitry Andric // Save current return address. 1418bcb0991SDimitry Andric BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Mips::OR)) 1428bcb0991SDimitry Andric .addDef(Mips::AT) 1438bcb0991SDimitry Andric .addUse(Mips::RA, RegState::Undef) 1448bcb0991SDimitry Andric .addUse(Mips::ZERO); 1458bcb0991SDimitry Andric // _mcount pops 2 words from stack. 1468bcb0991SDimitry Andric BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Mips::ADDiu)) 1478bcb0991SDimitry Andric .addDef(Mips::SP) 1488bcb0991SDimitry Andric .addUse(Mips::SP) 1498bcb0991SDimitry Andric .addImm(-8); 1508bcb0991SDimitry Andric // Stops first instruction above from being removed later on. 1518bcb0991SDimitry Andric MIB.addUse(Mips::AT, RegState::Implicit); 1528bcb0991SDimitry Andric } 1538bcb0991SDimitry Andric } 1548bcb0991SDimitry Andric 1550b57cec5SDimitry Andric void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { 1565ffd83dbSDimitry Andric MF.getInfo<MipsFunctionInfo>()->initGlobalBaseReg(MF); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric MachineRegisterInfo *MRI = &MF.getRegInfo(); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric for (auto &MBB: MF) { 1610b57cec5SDimitry Andric for (auto &MI: MBB) { 1620b57cec5SDimitry Andric switch (MI.getOpcode()) { 1630b57cec5SDimitry Andric case Mips::RDDSP: 1640b57cec5SDimitry Andric addDSPCtrlRegOperands(false, MI, MF); 1650b57cec5SDimitry Andric break; 1660b57cec5SDimitry Andric case Mips::WRDSP: 1670b57cec5SDimitry Andric addDSPCtrlRegOperands(true, MI, MF); 1680b57cec5SDimitry Andric break; 1690b57cec5SDimitry Andric case Mips::BuildPairF64_64: 1700b57cec5SDimitry Andric case Mips::ExtractElementF64_64: 1710b57cec5SDimitry Andric if (!Subtarget->useOddSPReg()) { 1720b57cec5SDimitry Andric MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true)); 1730b57cec5SDimitry Andric break; 1740b57cec5SDimitry Andric } 175bdd1243dSDimitry Andric [[fallthrough]]; 1760b57cec5SDimitry Andric case Mips::BuildPairF64: 1770b57cec5SDimitry Andric case Mips::ExtractElementF64: 1780b57cec5SDimitry Andric if (Subtarget->isABI_FPXX() && !Subtarget->hasMTHC1()) 1790b57cec5SDimitry Andric MI.addOperand(MachineOperand::CreateReg(Mips::SP, false, true)); 1800b57cec5SDimitry Andric break; 1818bcb0991SDimitry Andric case Mips::JAL: 1828bcb0991SDimitry Andric case Mips::JAL_MM: 1838bcb0991SDimitry Andric if (MI.getOperand(0).isGlobal() && 1848bcb0991SDimitry Andric MI.getOperand(0).getGlobal()->getGlobalIdentifier() == "_mcount") 1858bcb0991SDimitry Andric emitMCountABI(MI, MBB, MF); 1868bcb0991SDimitry Andric break; 1878bcb0991SDimitry Andric case Mips::JALRPseudo: 1888bcb0991SDimitry Andric case Mips::JALR64Pseudo: 1898bcb0991SDimitry Andric case Mips::JALR16_MM: 1908bcb0991SDimitry Andric if (MI.getOperand(2).isMCSymbol() && 1918bcb0991SDimitry Andric MI.getOperand(2).getMCSymbol()->getName() == "_mcount") 1928bcb0991SDimitry Andric emitMCountABI(MI, MBB, MF); 1938bcb0991SDimitry Andric break; 1948bcb0991SDimitry Andric case Mips::JALR: 1958bcb0991SDimitry Andric if (MI.getOperand(3).isMCSymbol() && 1968bcb0991SDimitry Andric MI.getOperand(3).getMCSymbol()->getName() == "_mcount") 1978bcb0991SDimitry Andric emitMCountABI(MI, MBB, MF); 1988bcb0991SDimitry Andric break; 1990b57cec5SDimitry Andric default: 2000b57cec5SDimitry Andric replaceUsesWithZeroReg(MRI, MI); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { 20706c3fb27SDimitry Andric SDValue InGlue = Node->getOperand(2); 20806c3fb27SDimitry Andric unsigned Opc = InGlue.getOpcode(); 2090b57cec5SDimitry Andric SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1); 2100b57cec5SDimitry Andric EVT VT = LHS.getValueType(); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric // In the base case, we can rely on the carry bit from the addsc 2130b57cec5SDimitry Andric // instruction. 2140b57cec5SDimitry Andric if (Opc == ISD::ADDC) { 21506c3fb27SDimitry Andric SDValue Ops[3] = {LHS, RHS, InGlue}; 2160b57cec5SDimitry Andric CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Ops); 2170b57cec5SDimitry Andric return; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric assert(Opc == ISD::ADDE && "ISD::ADDE not in a chain of ADDE nodes!"); 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric // The more complex case is when there is a chain of ISD::ADDE nodes like: 2230b57cec5SDimitry Andric // (adde (adde (adde (addc a b) c) d) e). 2240b57cec5SDimitry Andric // 2250b57cec5SDimitry Andric // The addwc instruction does not write to the carry bit, instead it writes 2260b57cec5SDimitry Andric // to bit 20 of the dsp control register. To match this series of nodes, each 2270b57cec5SDimitry Andric // intermediate adde node must be expanded to write the carry bit before the 2280b57cec5SDimitry Andric // addition. 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric // Start by reading the overflow field for addsc and moving the value to the 2310b57cec5SDimitry Andric // carry field. The usage of 1 here with MipsISD::RDDSP / Mips::WRDSP 2320b57cec5SDimitry Andric // corresponds to reading/writing the entire control register to/from a GPR. 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric SDValue CstOne = CurDAG->getTargetConstant(1, DL, MVT::i32); 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric SDValue OuFlag = CurDAG->getTargetConstant(20, DL, MVT::i32); 2370b57cec5SDimitry Andric 238480093f4SDimitry Andric SDNode *DSPCtrlField = CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, 23906c3fb27SDimitry Andric MVT::Glue, CstOne, InGlue); 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric SDNode *Carry = CurDAG->getMachineNode( 2420b57cec5SDimitry Andric Mips::EXT, DL, MVT::i32, SDValue(DSPCtrlField, 0), OuFlag, CstOne); 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric SDValue Ops[4] = {SDValue(DSPCtrlField, 0), 2450b57cec5SDimitry Andric CurDAG->getTargetConstant(6, DL, MVT::i32), CstOne, 2460b57cec5SDimitry Andric SDValue(Carry, 0)}; 2470b57cec5SDimitry Andric SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, Ops); 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric // My reading of the MIPS DSP 3.01 specification isn't as clear as I 2500b57cec5SDimitry Andric // would like about whether bit 20 always gets overwritten by addwc. 2510b57cec5SDimitry Andric // Hence take an extremely conservative view and presume it's sticky. We 2520b57cec5SDimitry Andric // therefore need to clear it. 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)}; 257480093f4SDimitry Andric SDNode *DSPCtrlFinal = 258480093f4SDimitry Andric CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric SDNode *WrDSP = CurDAG->getMachineNode(Mips::WRDSP, DL, MVT::Glue, 2610b57cec5SDimitry Andric SDValue(DSPCtrlFinal, 0), CstOne); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric SDValue Operands[3] = {LHS, RHS, SDValue(WrDSP, 0)}; 2640b57cec5SDimitry Andric CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Operands); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric /// Match frameindex 2680b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrFrameIndex(SDValue Addr, SDValue &Base, 2690b57cec5SDimitry Andric SDValue &Offset) const { 2700b57cec5SDimitry Andric if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 2710b57cec5SDimitry Andric EVT ValTy = Addr.getValueType(); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 2740b57cec5SDimitry Andric Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy); 2750b57cec5SDimitry Andric return true; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric return false; 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric /// Match frameindex+offset and frameindex|offset 2810b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset( 2820b57cec5SDimitry Andric SDValue Addr, SDValue &Base, SDValue &Offset, unsigned OffsetBits, 2830b57cec5SDimitry Andric unsigned ShiftAmount = 0) const { 2840b57cec5SDimitry Andric if (CurDAG->isBaseWithConstantOffset(Addr)) { 28581ad6265SDimitry Andric auto *CN = cast<ConstantSDNode>(Addr.getOperand(1)); 2860b57cec5SDimitry Andric if (isIntN(OffsetBits + ShiftAmount, CN->getSExtValue())) { 2870b57cec5SDimitry Andric EVT ValTy = Addr.getValueType(); 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric // If the first operand is a FI, get the TargetFI Node 2900b57cec5SDimitry Andric if (FrameIndexSDNode *FIN = 2910b57cec5SDimitry Andric dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) 2920b57cec5SDimitry Andric Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 2930b57cec5SDimitry Andric else { 2940b57cec5SDimitry Andric Base = Addr.getOperand(0); 2950b57cec5SDimitry Andric // If base is a FI, additional offset calculation is done in 2960b57cec5SDimitry Andric // eliminateFrameIndex, otherwise we need to check the alignment 2978bcb0991SDimitry Andric const Align Alignment(1ULL << ShiftAmount); 2988bcb0991SDimitry Andric if (!isAligned(Alignment, CN->getZExtValue())) 2990b57cec5SDimitry Andric return false; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), 3030b57cec5SDimitry Andric ValTy); 3040b57cec5SDimitry Andric return true; 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric return false; 3080b57cec5SDimitry Andric } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric /// ComplexPattern used on MipsInstrInfo 3110b57cec5SDimitry Andric /// Used on Mips Load/Store instructions 3120b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, 3130b57cec5SDimitry Andric SDValue &Offset) const { 3140b57cec5SDimitry Andric // if Address is FI, get the TargetFrameIndex. 3150b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 3160b57cec5SDimitry Andric return true; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric // on PIC code Load GA 3190b57cec5SDimitry Andric if (Addr.getOpcode() == MipsISD::Wrapper) { 3200b57cec5SDimitry Andric Base = Addr.getOperand(0); 3210b57cec5SDimitry Andric Offset = Addr.getOperand(1); 3220b57cec5SDimitry Andric return true; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric if (!TM.isPositionIndependent()) { 3260b57cec5SDimitry Andric if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 3270b57cec5SDimitry Andric Addr.getOpcode() == ISD::TargetGlobalAddress)) 3280b57cec5SDimitry Andric return false; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric // Addresses of the form FI+const or FI|const 3320b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 16)) 3330b57cec5SDimitry Andric return true; 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric // Operand is a result from an ADD. 3360b57cec5SDimitry Andric if (Addr.getOpcode() == ISD::ADD) { 3370b57cec5SDimitry Andric // When loading from constant pools, load the lower address part in 3380b57cec5SDimitry Andric // the instruction itself. Example, instead of: 3390b57cec5SDimitry Andric // lui $2, %hi($CPI1_0) 3400b57cec5SDimitry Andric // addiu $2, $2, %lo($CPI1_0) 3410b57cec5SDimitry Andric // lwc1 $f0, 0($2) 3420b57cec5SDimitry Andric // Generate: 3430b57cec5SDimitry Andric // lui $2, %hi($CPI1_0) 3440b57cec5SDimitry Andric // lwc1 $f0, %lo($CPI1_0)($2) 3450b57cec5SDimitry Andric if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || 3460b57cec5SDimitry Andric Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { 3470b57cec5SDimitry Andric SDValue Opnd0 = Addr.getOperand(1).getOperand(0); 3480b57cec5SDimitry Andric if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || 3490b57cec5SDimitry Andric isa<JumpTableSDNode>(Opnd0)) { 3500b57cec5SDimitry Andric Base = Addr.getOperand(0); 3510b57cec5SDimitry Andric Offset = Opnd0; 3520b57cec5SDimitry Andric return true; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric return false; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric /// ComplexPattern used on MipsInstrInfo 3610b57cec5SDimitry Andric /// Used on Mips Load/Store instructions 3620b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, 3630b57cec5SDimitry Andric SDValue &Offset) const { 3640b57cec5SDimitry Andric Base = Addr; 3650b57cec5SDimitry Andric Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType()); 3660b57cec5SDimitry Andric return true; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, 3700b57cec5SDimitry Andric SDValue &Offset) const { 3710b57cec5SDimitry Andric return selectAddrRegImm(Addr, Base, Offset) || 3720b57cec5SDimitry Andric selectAddrDefault(Addr, Base, Offset); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrRegImm9(SDValue Addr, SDValue &Base, 3760b57cec5SDimitry Andric SDValue &Offset) const { 3770b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 3780b57cec5SDimitry Andric return true; 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 9)) 3810b57cec5SDimitry Andric return true; 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric return false; 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric /// Used on microMIPS LWC2, LDC2, SWC2 and SDC2 instructions (11-bit offset) 3870b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrRegImm11(SDValue Addr, SDValue &Base, 3880b57cec5SDimitry Andric SDValue &Offset) const { 3890b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 3900b57cec5SDimitry Andric return true; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 11)) 3930b57cec5SDimitry Andric return true; 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric return false; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric /// Used on microMIPS Load/Store unaligned instructions (12-bit offset) 3990b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, 4000b57cec5SDimitry Andric SDValue &Offset) const { 4010b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 4020b57cec5SDimitry Andric return true; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 12)) 4050b57cec5SDimitry Andric return true; 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric return false; 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base, 4110b57cec5SDimitry Andric SDValue &Offset) const { 4120b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 4130b57cec5SDimitry Andric return true; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 16)) 4160b57cec5SDimitry Andric return true; 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric return false; 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, 4220b57cec5SDimitry Andric SDValue &Offset) const { 4230b57cec5SDimitry Andric return selectAddrRegImm11(Addr, Base, Offset) || 4240b57cec5SDimitry Andric selectAddrDefault(Addr, Base, Offset); 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, 4280b57cec5SDimitry Andric SDValue &Offset) const { 4290b57cec5SDimitry Andric return selectAddrRegImm12(Addr, Base, Offset) || 4300b57cec5SDimitry Andric selectAddrDefault(Addr, Base, Offset); 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, 4340b57cec5SDimitry Andric SDValue &Offset) const { 4350b57cec5SDimitry Andric return selectAddrRegImm16(Addr, Base, Offset) || 4360b57cec5SDimitry Andric selectAddrDefault(Addr, Base, Offset); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, 4400b57cec5SDimitry Andric SDValue &Offset) const { 4410b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) { 4420b57cec5SDimitry Andric if (isa<FrameIndexSDNode>(Base)) 4430b57cec5SDimitry Andric return false; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Offset)) { 4460b57cec5SDimitry Andric unsigned CnstOff = CN->getZExtValue(); 4470b57cec5SDimitry Andric return (CnstOff == (CnstOff & 0x3c)); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric return false; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric // For all other cases where "lw" would be selected, don't select "lw16" 4540b57cec5SDimitry Andric // because it would result in additional instructions to prepare operands. 4550b57cec5SDimitry Andric if (selectAddrRegImm(Addr, Base, Offset)) 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric return selectAddrDefault(Addr, Base, Offset); 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, 4620b57cec5SDimitry Andric SDValue &Offset) const { 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 4650b57cec5SDimitry Andric return true; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10)) 4680b57cec5SDimitry Andric return true; 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric return selectAddrDefault(Addr, Base, Offset); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, 4740b57cec5SDimitry Andric SDValue &Offset) const { 4750b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 4760b57cec5SDimitry Andric return true; 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 1)) 4790b57cec5SDimitry Andric return true; 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric return selectAddrDefault(Addr, Base, Offset); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, 4850b57cec5SDimitry Andric SDValue &Offset) const { 4860b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 4870b57cec5SDimitry Andric return true; 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 2)) 4900b57cec5SDimitry Andric return true; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric return selectAddrDefault(Addr, Base, Offset); 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, 4960b57cec5SDimitry Andric SDValue &Offset) const { 4970b57cec5SDimitry Andric if (selectAddrFrameIndex(Addr, Base, Offset)) 4980b57cec5SDimitry Andric return true; 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric if (selectAddrFrameIndexOffset(Addr, Base, Offset, 10, 3)) 5010b57cec5SDimitry Andric return true; 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric return selectAddrDefault(Addr, Base, Offset); 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric // Select constant vector splats. 5070b57cec5SDimitry Andric // 5080b57cec5SDimitry Andric // Returns true and sets Imm if: 5090b57cec5SDimitry Andric // * MSA is enabled 5100b57cec5SDimitry Andric // * N is a ISD::BUILD_VECTOR representing a constant splat 5110b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, 5120b57cec5SDimitry Andric unsigned MinSizeInBits) const { 5130b57cec5SDimitry Andric if (!Subtarget->hasMSA()) 5140b57cec5SDimitry Andric return false; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N); 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric if (!Node) 5190b57cec5SDimitry Andric return false; 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric APInt SplatValue, SplatUndef; 5220b57cec5SDimitry Andric unsigned SplatBitSize; 5230b57cec5SDimitry Andric bool HasAnyUndefs; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 5260b57cec5SDimitry Andric MinSizeInBits, !Subtarget->isLittle())) 5270b57cec5SDimitry Andric return false; 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric Imm = SplatValue; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric return true; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric // Select constant vector splats. 5350b57cec5SDimitry Andric // 5360b57cec5SDimitry Andric // In addition to the requirements of selectVSplat(), this function returns 5370b57cec5SDimitry Andric // true and sets Imm if: 5380b57cec5SDimitry Andric // * The splat value is the same width as the elements of the vector 5390b57cec5SDimitry Andric // * The splat value fits in an integer with the specified signed-ness and 5400b57cec5SDimitry Andric // width. 5410b57cec5SDimitry Andric // 5420b57cec5SDimitry Andric // This function looks through ISD::BITCAST nodes. 5430b57cec5SDimitry Andric // TODO: This might not be appropriate for big-endian MSA since BITCAST is 5440b57cec5SDimitry Andric // sometimes a shuffle in big-endian mode. 5450b57cec5SDimitry Andric // 5460b57cec5SDimitry Andric // It's worth noting that this function is not used as part of the selection 5470b57cec5SDimitry Andric // of ldi.[bhwd] since it does not permit using the wrong-typed ldi.[bhwd] 5480b57cec5SDimitry Andric // instruction to achieve the desired bit pattern. ldi.[bhwd] is selected in 5490b57cec5SDimitry Andric // MipsSEDAGToDAGISel::selectNode. 5500b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 5510b57cec5SDimitry Andric selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, 5520b57cec5SDimitry Andric unsigned ImmBitSize) const { 5530b57cec5SDimitry Andric APInt ImmValue; 5540b57cec5SDimitry Andric EVT EltTy = N->getValueType(0).getVectorElementType(); 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric if (N->getOpcode() == ISD::BITCAST) 5570b57cec5SDimitry Andric N = N->getOperand(0); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 5600b57cec5SDimitry Andric ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric if (( Signed && ImmValue.isSignedIntN(ImmBitSize)) || 5630b57cec5SDimitry Andric (!Signed && ImmValue.isIntN(ImmBitSize))) { 5640b57cec5SDimitry Andric Imm = CurDAG->getTargetConstant(ImmValue, SDLoc(N), EltTy); 5650b57cec5SDimitry Andric return true; 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric return false; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric // Select constant vector splats. 5730b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 5740b57cec5SDimitry Andric selectVSplatUimm1(SDValue N, SDValue &Imm) const { 5750b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 1); 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 5790b57cec5SDimitry Andric selectVSplatUimm2(SDValue N, SDValue &Imm) const { 5800b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 2); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 5840b57cec5SDimitry Andric selectVSplatUimm3(SDValue N, SDValue &Imm) const { 5850b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 3); 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric // Select constant vector splats. 5890b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 5900b57cec5SDimitry Andric selectVSplatUimm4(SDValue N, SDValue &Imm) const { 5910b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 4); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric // Select constant vector splats. 5950b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 5960b57cec5SDimitry Andric selectVSplatUimm5(SDValue N, SDValue &Imm) const { 5970b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 5); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric // Select constant vector splats. 6010b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 6020b57cec5SDimitry Andric selectVSplatUimm6(SDValue N, SDValue &Imm) const { 6030b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 6); 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric // Select constant vector splats. 6070b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 6080b57cec5SDimitry Andric selectVSplatUimm8(SDValue N, SDValue &Imm) const { 6090b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, false, 8); 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric // Select constant vector splats. 6130b57cec5SDimitry Andric bool MipsSEDAGToDAGISel:: 6140b57cec5SDimitry Andric selectVSplatSimm5(SDValue N, SDValue &Imm) const { 6150b57cec5SDimitry Andric return selectVSplatCommon(N, Imm, true, 5); 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric // Select constant vector splats whose value is a power of 2. 6190b57cec5SDimitry Andric // 6200b57cec5SDimitry Andric // In addition to the requirements of selectVSplat(), this function returns 6210b57cec5SDimitry Andric // true and sets Imm if: 6220b57cec5SDimitry Andric // * The splat value is the same width as the elements of the vector 6230b57cec5SDimitry Andric // * The splat value is a power of two. 6240b57cec5SDimitry Andric // 6250b57cec5SDimitry Andric // This function looks through ISD::BITCAST nodes. 6260b57cec5SDimitry Andric // TODO: This might not be appropriate for big-endian MSA since BITCAST is 6270b57cec5SDimitry Andric // sometimes a shuffle in big-endian mode. 6280b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const { 6290b57cec5SDimitry Andric APInt ImmValue; 6300b57cec5SDimitry Andric EVT EltTy = N->getValueType(0).getVectorElementType(); 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric if (N->getOpcode() == ISD::BITCAST) 6330b57cec5SDimitry Andric N = N->getOperand(0); 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 6360b57cec5SDimitry Andric ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 6370b57cec5SDimitry Andric int32_t Log2 = ImmValue.exactLogBase2(); 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric if (Log2 != -1) { 6400b57cec5SDimitry Andric Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); 6410b57cec5SDimitry Andric return true; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric return false; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric // Select constant vector splats whose value only has a consecutive sequence 6490b57cec5SDimitry Andric // of left-most bits set (e.g. 0b11...1100...00). 6500b57cec5SDimitry Andric // 6510b57cec5SDimitry Andric // In addition to the requirements of selectVSplat(), this function returns 6520b57cec5SDimitry Andric // true and sets Imm if: 6530b57cec5SDimitry Andric // * The splat value is the same width as the elements of the vector 6540b57cec5SDimitry Andric // * The splat value is a consecutive sequence of left-most bits. 6550b57cec5SDimitry Andric // 6560b57cec5SDimitry Andric // This function looks through ISD::BITCAST nodes. 6570b57cec5SDimitry Andric // TODO: This might not be appropriate for big-endian MSA since BITCAST is 6580b57cec5SDimitry Andric // sometimes a shuffle in big-endian mode. 6590b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { 6600b57cec5SDimitry Andric APInt ImmValue; 6610b57cec5SDimitry Andric EVT EltTy = N->getValueType(0).getVectorElementType(); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric if (N->getOpcode() == ISD::BITCAST) 6640b57cec5SDimitry Andric N = N->getOperand(0); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 6670b57cec5SDimitry Andric ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 6680b57cec5SDimitry Andric // Extract the run of set bits starting with bit zero from the bitwise 6690b57cec5SDimitry Andric // inverse of ImmValue, and test that the inverse of this is the same 6700b57cec5SDimitry Andric // as the original value. 6710b57cec5SDimitry Andric if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) { 6720b57cec5SDimitry Andric 67306c3fb27SDimitry Andric Imm = CurDAG->getTargetConstant(ImmValue.popcount() - 1, SDLoc(N), EltTy); 6740b57cec5SDimitry Andric return true; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric return false; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric // Select constant vector splats whose value only has a consecutive sequence 6820b57cec5SDimitry Andric // of right-most bits set (e.g. 0b00...0011...11). 6830b57cec5SDimitry Andric // 6840b57cec5SDimitry Andric // In addition to the requirements of selectVSplat(), this function returns 6850b57cec5SDimitry Andric // true and sets Imm if: 6860b57cec5SDimitry Andric // * The splat value is the same width as the elements of the vector 6870b57cec5SDimitry Andric // * The splat value is a consecutive sequence of right-most bits. 6880b57cec5SDimitry Andric // 6890b57cec5SDimitry Andric // This function looks through ISD::BITCAST nodes. 6900b57cec5SDimitry Andric // TODO: This might not be appropriate for big-endian MSA since BITCAST is 6910b57cec5SDimitry Andric // sometimes a shuffle in big-endian mode. 6920b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { 6930b57cec5SDimitry Andric APInt ImmValue; 6940b57cec5SDimitry Andric EVT EltTy = N->getValueType(0).getVectorElementType(); 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric if (N->getOpcode() == ISD::BITCAST) 6970b57cec5SDimitry Andric N = N->getOperand(0); 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 7000b57cec5SDimitry Andric ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 7010b57cec5SDimitry Andric // Extract the run of set bits starting with bit zero, and test that the 7020b57cec5SDimitry Andric // result is the same as the original value 7030b57cec5SDimitry Andric if (ImmValue == (ImmValue & ~(ImmValue + 1))) { 70406c3fb27SDimitry Andric Imm = CurDAG->getTargetConstant(ImmValue.popcount() - 1, SDLoc(N), EltTy); 7050b57cec5SDimitry Andric return true; 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric return false; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, 7130b57cec5SDimitry Andric SDValue &Imm) const { 7140b57cec5SDimitry Andric APInt ImmValue; 7150b57cec5SDimitry Andric EVT EltTy = N->getValueType(0).getVectorElementType(); 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric if (N->getOpcode() == ISD::BITCAST) 7180b57cec5SDimitry Andric N = N->getOperand(0); 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 7210b57cec5SDimitry Andric ImmValue.getBitWidth() == EltTy.getSizeInBits()) { 7220b57cec5SDimitry Andric int32_t Log2 = (~ImmValue).exactLogBase2(); 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric if (Log2 != -1) { 7250b57cec5SDimitry Andric Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); 7260b57cec5SDimitry Andric return true; 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric return false; 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 733*71ac745dSDimitry Andric // Select const vector splat of 1. 734*71ac745dSDimitry Andric bool MipsSEDAGToDAGISel::selectVSplatImmEq1(SDValue N) const { 735*71ac745dSDimitry Andric APInt ImmValue; 736*71ac745dSDimitry Andric EVT EltTy = N->getValueType(0).getVectorElementType(); 737*71ac745dSDimitry Andric 738*71ac745dSDimitry Andric if (N->getOpcode() == ISD::BITCAST) 739*71ac745dSDimitry Andric N = N->getOperand(0); 740*71ac745dSDimitry Andric 741*71ac745dSDimitry Andric return selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && 742*71ac745dSDimitry Andric ImmValue.getBitWidth() == EltTy.getSizeInBits() && ImmValue == 1; 743*71ac745dSDimitry Andric } 744*71ac745dSDimitry Andric 7450b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { 7460b57cec5SDimitry Andric unsigned Opcode = Node->getOpcode(); 7470b57cec5SDimitry Andric SDLoc DL(Node); 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric /// 7500b57cec5SDimitry Andric // Instruction Selection not handled by the auto-generated 7510b57cec5SDimitry Andric // tablegen selection should be handled here. 7520b57cec5SDimitry Andric /// 7530b57cec5SDimitry Andric switch(Opcode) { 7540b57cec5SDimitry Andric default: break; 7550b57cec5SDimitry Andric 7560fca6ea1SDimitry Andric case MipsISD::DOUBLE_SELECT_I: 7570fca6ea1SDimitry Andric case MipsISD::DOUBLE_SELECT_I64: { 7580b57cec5SDimitry Andric MVT VT = Subtarget->isGP64bit() ? MVT::i64 : MVT::i32; 7590b57cec5SDimitry Andric SDValue cond = Node->getOperand(0); 7600b57cec5SDimitry Andric SDValue Hi1 = Node->getOperand(1); 7610b57cec5SDimitry Andric SDValue Lo1 = Node->getOperand(2); 7620b57cec5SDimitry Andric SDValue Hi2 = Node->getOperand(3); 7630b57cec5SDimitry Andric SDValue Lo2 = Node->getOperand(4); 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric SDValue ops[] = {cond, Hi1, Lo1, Hi2, Lo2}; 7660b57cec5SDimitry Andric EVT NodeTys[] = {VT, VT}; 7670b57cec5SDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Subtarget->isGP64bit() 7680b57cec5SDimitry Andric ? Mips::PseudoD_SELECT_I64 7690b57cec5SDimitry Andric : Mips::PseudoD_SELECT_I, 7700b57cec5SDimitry Andric DL, NodeTys, ops)); 7710b57cec5SDimitry Andric return true; 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric case ISD::ADDE: { 7750b57cec5SDimitry Andric selectAddE(Node, DL); 7760b57cec5SDimitry Andric return true; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric case ISD::ConstantFP: { 7808bcb0991SDimitry Andric auto *CN = cast<ConstantFPSDNode>(Node); 7810b57cec5SDimitry Andric if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { 7820b57cec5SDimitry Andric if (Subtarget->isGP64bit()) { 7830b57cec5SDimitry Andric SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, 7840b57cec5SDimitry Andric Mips::ZERO_64, MVT::i64); 7850b57cec5SDimitry Andric ReplaceNode(Node, 7860b57cec5SDimitry Andric CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero)); 7870b57cec5SDimitry Andric } else if (Subtarget->isFP64bit()) { 7880b57cec5SDimitry Andric SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, 7890b57cec5SDimitry Andric Mips::ZERO, MVT::i32); 7900b57cec5SDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64_64, DL, 7910b57cec5SDimitry Andric MVT::f64, Zero, Zero)); 7920b57cec5SDimitry Andric } else { 7930b57cec5SDimitry Andric SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, 7940b57cec5SDimitry Andric Mips::ZERO, MVT::i32); 7950b57cec5SDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64, DL, 7960b57cec5SDimitry Andric MVT::f64, Zero, Zero)); 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric return true; 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric break; 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric case ISD::Constant: { 8048bcb0991SDimitry Andric auto *CN = cast<ConstantSDNode>(Node); 8050b57cec5SDimitry Andric int64_t Imm = CN->getSExtValue(); 8060b57cec5SDimitry Andric unsigned Size = CN->getValueSizeInBits(0); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric if (isInt<32>(Imm)) 8090b57cec5SDimitry Andric break; 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric MipsAnalyzeImmediate AnalyzeImm; 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric const MipsAnalyzeImmediate::InstSeq &Seq = 8140b57cec5SDimitry Andric AnalyzeImm.Analyze(Imm, Size, false); 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); 8170b57cec5SDimitry Andric SDLoc DL(CN); 8180b57cec5SDimitry Andric SDNode *RegOpnd; 8190b57cec5SDimitry Andric SDValue ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), 8200b57cec5SDimitry Andric DL, MVT::i64); 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric // The first instruction can be a LUi which is different from other 8230b57cec5SDimitry Andric // instructions (ADDiu, ORI and SLL) in that it does not have a register 8240b57cec5SDimitry Andric // operand. 8250b57cec5SDimitry Andric if (Inst->Opc == Mips::LUi64) 8260b57cec5SDimitry Andric RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, ImmOpnd); 8270b57cec5SDimitry Andric else 8280b57cec5SDimitry Andric RegOpnd = 8290b57cec5SDimitry Andric CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, 8300b57cec5SDimitry Andric CurDAG->getRegister(Mips::ZERO_64, MVT::i64), 8310b57cec5SDimitry Andric ImmOpnd); 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric // The remaining instructions in the sequence are handled here. 8340b57cec5SDimitry Andric for (++Inst; Inst != Seq.end(); ++Inst) { 8350b57cec5SDimitry Andric ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), DL, 8360b57cec5SDimitry Andric MVT::i64); 8370b57cec5SDimitry Andric RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, 8380b57cec5SDimitry Andric SDValue(RegOpnd, 0), ImmOpnd); 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric ReplaceNode(Node, RegOpnd); 8420b57cec5SDimitry Andric return true; 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric case ISD::INTRINSIC_W_CHAIN: { 846647cbc5dSDimitry Andric const unsigned IntrinsicOpcode = Node->getConstantOperandVal(1); 8475ffd83dbSDimitry Andric switch (IntrinsicOpcode) { 8480b57cec5SDimitry Andric default: 8490b57cec5SDimitry Andric break; 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric case Intrinsic::mips_cfcmsa: { 8520b57cec5SDimitry Andric SDValue ChainIn = Node->getOperand(0); 8530b57cec5SDimitry Andric SDValue RegIdx = Node->getOperand(2); 8540b57cec5SDimitry Andric SDValue Reg = CurDAG->getCopyFromReg(ChainIn, DL, 8550b57cec5SDimitry Andric getMSACtrlReg(RegIdx), MVT::i32); 8560b57cec5SDimitry Andric ReplaceNode(Node, Reg.getNode()); 8570b57cec5SDimitry Andric return true; 8580b57cec5SDimitry Andric } 8595ffd83dbSDimitry Andric case Intrinsic::mips_ldr_d: 8605ffd83dbSDimitry Andric case Intrinsic::mips_ldr_w: { 8615ffd83dbSDimitry Andric unsigned Op = (IntrinsicOpcode == Intrinsic::mips_ldr_d) ? Mips::LDR_D 8625ffd83dbSDimitry Andric : Mips::LDR_W; 8635ffd83dbSDimitry Andric 8645ffd83dbSDimitry Andric SDLoc DL(Node); 8655ffd83dbSDimitry Andric assert(Node->getNumOperands() == 4 && "Unexpected number of operands."); 8665ffd83dbSDimitry Andric const SDValue &Chain = Node->getOperand(0); 8675ffd83dbSDimitry Andric const SDValue &Intrinsic = Node->getOperand(1); 8685ffd83dbSDimitry Andric const SDValue &Pointer = Node->getOperand(2); 8695ffd83dbSDimitry Andric const SDValue &Constant = Node->getOperand(3); 8705ffd83dbSDimitry Andric 8715ffd83dbSDimitry Andric assert(Chain.getValueType() == MVT::Other); 8725ffd83dbSDimitry Andric (void)Intrinsic; 8735ffd83dbSDimitry Andric assert(Intrinsic.getOpcode() == ISD::TargetConstant && 8745ffd83dbSDimitry Andric Constant.getOpcode() == ISD::Constant && 8755ffd83dbSDimitry Andric "Invalid instruction operand."); 8765ffd83dbSDimitry Andric 8775ffd83dbSDimitry Andric // Convert Constant to TargetConstant. 8785ffd83dbSDimitry Andric const ConstantInt *Val = 8795ffd83dbSDimitry Andric cast<ConstantSDNode>(Constant)->getConstantIntValue(); 8805ffd83dbSDimitry Andric SDValue Imm = 8815ffd83dbSDimitry Andric CurDAG->getTargetConstant(*Val, DL, Constant.getValueType()); 8825ffd83dbSDimitry Andric 8835ffd83dbSDimitry Andric SmallVector<SDValue, 3> Ops{Pointer, Imm, Chain}; 8845ffd83dbSDimitry Andric 8855ffd83dbSDimitry Andric assert(Node->getNumValues() == 2); 8865ffd83dbSDimitry Andric assert(Node->getValueType(0).is128BitVector()); 8875ffd83dbSDimitry Andric assert(Node->getValueType(1) == MVT::Other); 8885ffd83dbSDimitry Andric SmallVector<EVT, 2> ResTys{Node->getValueType(0), Node->getValueType(1)}; 8895ffd83dbSDimitry Andric 8905ffd83dbSDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Op, DL, ResTys, Ops)); 8915ffd83dbSDimitry Andric 8925ffd83dbSDimitry Andric return true; 8935ffd83dbSDimitry Andric } 8940b57cec5SDimitry Andric } 8950b57cec5SDimitry Andric break; 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric case ISD::INTRINSIC_WO_CHAIN: { 899647cbc5dSDimitry Andric switch (Node->getConstantOperandVal(0)) { 9000b57cec5SDimitry Andric default: 9010b57cec5SDimitry Andric break; 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric case Intrinsic::mips_move_v: 9040b57cec5SDimitry Andric // Like an assignment but will always produce a move.v even if 9050b57cec5SDimitry Andric // unnecessary. 9060b57cec5SDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Mips::MOVE_V, DL, 9070b57cec5SDimitry Andric Node->getValueType(0), 9080b57cec5SDimitry Andric Node->getOperand(1))); 9090b57cec5SDimitry Andric return true; 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric break; 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric case ISD::INTRINSIC_VOID: { 915647cbc5dSDimitry Andric const unsigned IntrinsicOpcode = Node->getConstantOperandVal(1); 9165ffd83dbSDimitry Andric switch (IntrinsicOpcode) { 9170b57cec5SDimitry Andric default: 9180b57cec5SDimitry Andric break; 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric case Intrinsic::mips_ctcmsa: { 9210b57cec5SDimitry Andric SDValue ChainIn = Node->getOperand(0); 9220b57cec5SDimitry Andric SDValue RegIdx = Node->getOperand(2); 9230b57cec5SDimitry Andric SDValue Value = Node->getOperand(3); 9240b57cec5SDimitry Andric SDValue ChainOut = CurDAG->getCopyToReg(ChainIn, DL, 9250b57cec5SDimitry Andric getMSACtrlReg(RegIdx), Value); 9260b57cec5SDimitry Andric ReplaceNode(Node, ChainOut.getNode()); 9270b57cec5SDimitry Andric return true; 9280b57cec5SDimitry Andric } 9295ffd83dbSDimitry Andric case Intrinsic::mips_str_d: 9305ffd83dbSDimitry Andric case Intrinsic::mips_str_w: { 9315ffd83dbSDimitry Andric unsigned Op = (IntrinsicOpcode == Intrinsic::mips_str_d) ? Mips::STR_D 9325ffd83dbSDimitry Andric : Mips::STR_W; 9335ffd83dbSDimitry Andric 9345ffd83dbSDimitry Andric SDLoc DL(Node); 9355ffd83dbSDimitry Andric assert(Node->getNumOperands() == 5 && "Unexpected number of operands."); 9365ffd83dbSDimitry Andric const SDValue &Chain = Node->getOperand(0); 9375ffd83dbSDimitry Andric const SDValue &Intrinsic = Node->getOperand(1); 9385ffd83dbSDimitry Andric const SDValue &Vec = Node->getOperand(2); 9395ffd83dbSDimitry Andric const SDValue &Pointer = Node->getOperand(3); 9405ffd83dbSDimitry Andric const SDValue &Constant = Node->getOperand(4); 9415ffd83dbSDimitry Andric 9425ffd83dbSDimitry Andric assert(Chain.getValueType() == MVT::Other); 9435ffd83dbSDimitry Andric (void)Intrinsic; 9445ffd83dbSDimitry Andric assert(Intrinsic.getOpcode() == ISD::TargetConstant && 9455ffd83dbSDimitry Andric Constant.getOpcode() == ISD::Constant && 9465ffd83dbSDimitry Andric "Invalid instruction operand."); 9475ffd83dbSDimitry Andric 9485ffd83dbSDimitry Andric // Convert Constant to TargetConstant. 9495ffd83dbSDimitry Andric const ConstantInt *Val = 9505ffd83dbSDimitry Andric cast<ConstantSDNode>(Constant)->getConstantIntValue(); 9515ffd83dbSDimitry Andric SDValue Imm = 9525ffd83dbSDimitry Andric CurDAG->getTargetConstant(*Val, DL, Constant.getValueType()); 9535ffd83dbSDimitry Andric 9545ffd83dbSDimitry Andric SmallVector<SDValue, 4> Ops{Vec, Pointer, Imm, Chain}; 9555ffd83dbSDimitry Andric 9565ffd83dbSDimitry Andric assert(Node->getNumValues() == 1); 9575ffd83dbSDimitry Andric assert(Node->getValueType(0) == MVT::Other); 9585ffd83dbSDimitry Andric SmallVector<EVT, 1> ResTys{Node->getValueType(0)}; 9595ffd83dbSDimitry Andric 9605ffd83dbSDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Op, DL, ResTys, Ops)); 9615ffd83dbSDimitry Andric return true; 9625ffd83dbSDimitry Andric } 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric break; 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric 96756f451bbSDimitry Andric case MipsISD::FAbs: { 96856f451bbSDimitry Andric MVT ResTy = Node->getSimpleValueType(0); 96956f451bbSDimitry Andric assert((ResTy == MVT::f64 || ResTy == MVT::f32) && 97056f451bbSDimitry Andric "Unsupported float type!"); 97156f451bbSDimitry Andric unsigned Opc = 0; 97256f451bbSDimitry Andric if (ResTy == MVT::f64) 97356f451bbSDimitry Andric Opc = (Subtarget->isFP64bit() ? Mips::FABS_D64 : Mips::FABS_D32); 97456f451bbSDimitry Andric else 97556f451bbSDimitry Andric Opc = Mips::FABS_S; 97656f451bbSDimitry Andric 97756f451bbSDimitry Andric if (Subtarget->inMicroMipsMode()) { 97856f451bbSDimitry Andric switch (Opc) { 97956f451bbSDimitry Andric case Mips::FABS_D64: 98056f451bbSDimitry Andric Opc = Mips::FABS_D64_MM; 98156f451bbSDimitry Andric break; 98256f451bbSDimitry Andric case Mips::FABS_D32: 98356f451bbSDimitry Andric Opc = Mips::FABS_D32_MM; 98456f451bbSDimitry Andric break; 98556f451bbSDimitry Andric case Mips::FABS_S: 98656f451bbSDimitry Andric Opc = Mips::FABS_S_MM; 98756f451bbSDimitry Andric break; 98856f451bbSDimitry Andric default: 98956f451bbSDimitry Andric llvm_unreachable("Unknown opcode for MIPS floating point abs!"); 99056f451bbSDimitry Andric } 99156f451bbSDimitry Andric } 99256f451bbSDimitry Andric 99356f451bbSDimitry Andric ReplaceNode(Node, 99456f451bbSDimitry Andric CurDAG->getMachineNode(Opc, DL, ResTy, Node->getOperand(0))); 99556f451bbSDimitry Andric 99656f451bbSDimitry Andric return true; 99756f451bbSDimitry Andric } 99856f451bbSDimitry Andric 9990b57cec5SDimitry Andric // Manually match MipsISD::Ins nodes to get the correct instruction. It has 10000b57cec5SDimitry Andric // to be done in this fashion so that we respect the differences between 10010b57cec5SDimitry Andric // dins and dinsm, as the difference is that the size operand has the range 10020b57cec5SDimitry Andric // 0 < size <= 32 for dins while dinsm has the range 2 <= size <= 64 which 10030b57cec5SDimitry Andric // means SelectionDAGISel would have to test all the operands at once to 10040b57cec5SDimitry Andric // match the instruction. 10050b57cec5SDimitry Andric case MipsISD::Ins: { 10060b57cec5SDimitry Andric 1007349cc55cSDimitry Andric // Validating the node operands. 10080b57cec5SDimitry Andric if (Node->getValueType(0) != MVT::i32 && Node->getValueType(0) != MVT::i64) 10090b57cec5SDimitry Andric return false; 10100b57cec5SDimitry Andric 10110b57cec5SDimitry Andric if (Node->getNumOperands() != 4) 10120b57cec5SDimitry Andric return false; 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric if (Node->getOperand(1)->getOpcode() != ISD::Constant || 10150b57cec5SDimitry Andric Node->getOperand(2)->getOpcode() != ISD::Constant) 10160b57cec5SDimitry Andric return false; 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric MVT ResTy = Node->getSimpleValueType(0); 10190b57cec5SDimitry Andric uint64_t Pos = Node->getConstantOperandVal(1); 10200b57cec5SDimitry Andric uint64_t Size = Node->getConstantOperandVal(2); 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric // Size has to be >0 for 'ins', 'dins' and 'dinsu'. 10230b57cec5SDimitry Andric if (!Size) 10240b57cec5SDimitry Andric return false; 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric if (Pos + Size > 64) 10270b57cec5SDimitry Andric return false; 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric if (ResTy != MVT::i32 && ResTy != MVT::i64) 10300b57cec5SDimitry Andric return false; 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric unsigned Opcode = 0; 10330b57cec5SDimitry Andric if (ResTy == MVT::i32) { 10340b57cec5SDimitry Andric if (Pos + Size <= 32) 10350b57cec5SDimitry Andric Opcode = Mips::INS; 10360b57cec5SDimitry Andric } else { 10370b57cec5SDimitry Andric if (Pos + Size <= 32) 10380b57cec5SDimitry Andric Opcode = Mips::DINS; 10390b57cec5SDimitry Andric else if (Pos < 32 && 1 < Size) 10400b57cec5SDimitry Andric Opcode = Mips::DINSM; 10410b57cec5SDimitry Andric else 10420b57cec5SDimitry Andric Opcode = Mips::DINSU; 10430b57cec5SDimitry Andric } 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric if (Opcode) { 10460b57cec5SDimitry Andric SDValue Ops[4] = { 10470b57cec5SDimitry Andric Node->getOperand(0), CurDAG->getTargetConstant(Pos, DL, MVT::i32), 10480b57cec5SDimitry Andric CurDAG->getTargetConstant(Size, DL, MVT::i32), Node->getOperand(3)}; 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, ResTy, Ops)); 10510b57cec5SDimitry Andric return true; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric return false; 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric case MipsISD::ThreadPointer: { 10580b57cec5SDimitry Andric EVT PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); 10590b57cec5SDimitry Andric unsigned RdhwrOpc, DestReg; 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric if (PtrVT == MVT::i32) { 10620b57cec5SDimitry Andric RdhwrOpc = Mips::RDHWR; 10630b57cec5SDimitry Andric DestReg = Mips::V1; 10640b57cec5SDimitry Andric } else { 10650b57cec5SDimitry Andric RdhwrOpc = Mips::RDHWR64; 10660b57cec5SDimitry Andric DestReg = Mips::V1_64; 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric SDNode *Rdhwr = 10704e117af1SDimitry Andric CurDAG->getMachineNode(RdhwrOpc, DL, Node->getValueType(0), MVT::Glue, 10710b57cec5SDimitry Andric CurDAG->getRegister(Mips::HWR29, MVT::i32), 10720b57cec5SDimitry Andric CurDAG->getTargetConstant(0, DL, MVT::i32)); 10730b57cec5SDimitry Andric SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg, 10744e117af1SDimitry Andric SDValue(Rdhwr, 0), SDValue(Rdhwr, 1)); 10754e117af1SDimitry Andric SDValue ResNode = CurDAG->getCopyFromReg(Chain, DL, DestReg, PtrVT, 10764e117af1SDimitry Andric Chain.getValue(1)); 10770b57cec5SDimitry Andric ReplaceNode(Node, ResNode.getNode()); 10780b57cec5SDimitry Andric return true; 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric case ISD::BUILD_VECTOR: { 10820b57cec5SDimitry Andric // Select appropriate ldi.[bhwd] instructions for constant splats of 10830b57cec5SDimitry Andric // 128-bit when MSA is enabled. Fixup any register class mismatches that 10840b57cec5SDimitry Andric // occur as a result. 10850b57cec5SDimitry Andric // 10860b57cec5SDimitry Andric // This allows the compiler to use a wider range of immediates than would 10870b57cec5SDimitry Andric // otherwise be allowed. If, for example, v4i32 could only use ldi.h then 10880b57cec5SDimitry Andric // it would not be possible to load { 0x01010101, 0x01010101, 0x01010101, 10890b57cec5SDimitry Andric // 0x01010101 } without using a constant pool. This would be sub-optimal 10900b57cec5SDimitry Andric // when // 'ldi.b wd, 1' is capable of producing that bit-pattern in the 10910b57cec5SDimitry Andric // same set/ of registers. Similarly, ldi.h isn't capable of producing { 10920b57cec5SDimitry Andric // 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can. 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric const MipsABIInfo &ABI = 10950b57cec5SDimitry Andric static_cast<const MipsTargetMachine &>(TM).getABI(); 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node); 10980b57cec5SDimitry Andric APInt SplatValue, SplatUndef; 10990b57cec5SDimitry Andric unsigned SplatBitSize; 11000b57cec5SDimitry Andric bool HasAnyUndefs; 11010b57cec5SDimitry Andric unsigned LdiOp; 11020b57cec5SDimitry Andric EVT ResVecTy = BVN->getValueType(0); 11030b57cec5SDimitry Andric EVT ViaVecTy; 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric if (!Subtarget->hasMSA() || !BVN->getValueType(0).is128BitVector()) 11060b57cec5SDimitry Andric return false; 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, 11090b57cec5SDimitry Andric HasAnyUndefs, 8, 11100b57cec5SDimitry Andric !Subtarget->isLittle())) 11110b57cec5SDimitry Andric return false; 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric switch (SplatBitSize) { 11140b57cec5SDimitry Andric default: 11150b57cec5SDimitry Andric return false; 11160b57cec5SDimitry Andric case 8: 11170b57cec5SDimitry Andric LdiOp = Mips::LDI_B; 11180b57cec5SDimitry Andric ViaVecTy = MVT::v16i8; 11190b57cec5SDimitry Andric break; 11200b57cec5SDimitry Andric case 16: 11210b57cec5SDimitry Andric LdiOp = Mips::LDI_H; 11220b57cec5SDimitry Andric ViaVecTy = MVT::v8i16; 11230b57cec5SDimitry Andric break; 11240b57cec5SDimitry Andric case 32: 11250b57cec5SDimitry Andric LdiOp = Mips::LDI_W; 11260b57cec5SDimitry Andric ViaVecTy = MVT::v4i32; 11270b57cec5SDimitry Andric break; 11280b57cec5SDimitry Andric case 64: 11290b57cec5SDimitry Andric LdiOp = Mips::LDI_D; 11300b57cec5SDimitry Andric ViaVecTy = MVT::v2i64; 11310b57cec5SDimitry Andric break; 11320b57cec5SDimitry Andric } 11330b57cec5SDimitry Andric 11348bcb0991SDimitry Andric SDNode *Res = nullptr; 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric // If we have a signed 10 bit integer, we can splat it directly. 11370b57cec5SDimitry Andric // 11380b57cec5SDimitry Andric // If we have something bigger we can synthesize the value into a GPR and 11390b57cec5SDimitry Andric // splat from there. 11400b57cec5SDimitry Andric if (SplatValue.isSignedIntN(10)) { 11410b57cec5SDimitry Andric SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, 11420b57cec5SDimitry Andric ViaVecTy.getVectorElementType()); 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); 11450b57cec5SDimitry Andric } else if (SplatValue.isSignedIntN(16) && 11460b57cec5SDimitry Andric ((ABI.IsO32() && SplatBitSize < 64) || 11470b57cec5SDimitry Andric (ABI.IsN32() || ABI.IsN64()))) { 11480b57cec5SDimitry Andric // Only handle signed 16 bit values when the element size is GPR width. 11490b57cec5SDimitry Andric // MIPS64 can handle all the cases but MIPS32 would need to handle 11500b57cec5SDimitry Andric // negative cases specifically here. Instead, handle those cases as 11510b57cec5SDimitry Andric // 64bit values. 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric bool Is32BitSplat = ABI.IsO32() || SplatBitSize < 64; 11540b57cec5SDimitry Andric const unsigned ADDiuOp = Is32BitSplat ? Mips::ADDiu : Mips::DADDiu; 11550b57cec5SDimitry Andric const MVT SplatMVT = Is32BitSplat ? MVT::i32 : MVT::i64; 11560b57cec5SDimitry Andric SDValue ZeroVal = CurDAG->getRegister( 11570b57cec5SDimitry Andric Is32BitSplat ? Mips::ZERO : Mips::ZERO_64, SplatMVT); 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric const unsigned FILLOp = 11600b57cec5SDimitry Andric SplatBitSize == 16 11610b57cec5SDimitry Andric ? Mips::FILL_H 11620b57cec5SDimitry Andric : (SplatBitSize == 32 ? Mips::FILL_W 11630b57cec5SDimitry Andric : (SplatBitSize == 64 ? Mips::FILL_D : 0)); 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric assert(FILLOp != 0 && "Unknown FILL Op for splat synthesis!"); 11660b57cec5SDimitry Andric assert((!ABI.IsO32() || (FILLOp != Mips::FILL_D)) && 11670b57cec5SDimitry Andric "Attempting to use fill.d on MIPS32!"); 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); 11700b57cec5SDimitry Andric SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, SplatMVT); 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric Res = CurDAG->getMachineNode(ADDiuOp, DL, SplatMVT, ZeroVal, LoVal); 11730b57cec5SDimitry Andric Res = CurDAG->getMachineNode(FILLOp, DL, ViaVecTy, SDValue(Res, 0)); 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 32) { 11760b57cec5SDimitry Andric // Only handle the cases where the splat size agrees with the size 11770b57cec5SDimitry Andric // of the SplatValue here. 11780b57cec5SDimitry Andric const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); 11790b57cec5SDimitry Andric const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); 11800b57cec5SDimitry Andric SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); 11810b57cec5SDimitry Andric 11820b57cec5SDimitry Andric SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); 11830b57cec5SDimitry Andric SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric if (Hi) 11860b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); 11870b57cec5SDimitry Andric 11880b57cec5SDimitry Andric if (Lo) 11890b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, 11900b57cec5SDimitry Andric Hi ? SDValue(Res, 0) : ZeroVal, LoVal); 11910b57cec5SDimitry Andric 11920b57cec5SDimitry Andric assert((Hi || Lo) && "Zero case reached 32 bit case splat synthesis!"); 1193480093f4SDimitry Andric Res = 1194480093f4SDimitry Andric CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, SDValue(Res, 0)); 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric } else if (SplatValue.isSignedIntN(32) && SplatBitSize == 64 && 11970b57cec5SDimitry Andric (ABI.IsN32() || ABI.IsN64())) { 11980b57cec5SDimitry Andric // N32 and N64 can perform some tricks that O32 can't for signed 32 bit 11990b57cec5SDimitry Andric // integers due to having 64bit registers. lui will cause the necessary 12000b57cec5SDimitry Andric // zero/sign extension. 12010b57cec5SDimitry Andric const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); 12020b57cec5SDimitry Andric const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); 12030b57cec5SDimitry Andric SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); 12060b57cec5SDimitry Andric SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); 12070b57cec5SDimitry Andric 12080b57cec5SDimitry Andric if (Hi) 12090b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric if (Lo) 12120b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, 12130b57cec5SDimitry Andric Hi ? SDValue(Res, 0) : ZeroVal, LoVal); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric Res = CurDAG->getMachineNode( 12160b57cec5SDimitry Andric Mips::SUBREG_TO_REG, DL, MVT::i64, 12170b57cec5SDimitry Andric CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64), 12180b57cec5SDimitry Andric SDValue(Res, 0), 12190b57cec5SDimitry Andric CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); 12200b57cec5SDimitry Andric 12210b57cec5SDimitry Andric Res = 12220b57cec5SDimitry Andric CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, SDValue(Res, 0)); 12230b57cec5SDimitry Andric 12240b57cec5SDimitry Andric } else if (SplatValue.isSignedIntN(64)) { 12250b57cec5SDimitry Andric // If we have a 64 bit Splat value, we perform a similar sequence to the 12260b57cec5SDimitry Andric // above: 12270b57cec5SDimitry Andric // 12280b57cec5SDimitry Andric // MIPS32: MIPS64: 12290b57cec5SDimitry Andric // lui $res, %highest(val) lui $res, %highest(val) 12300b57cec5SDimitry Andric // ori $res, $res, %higher(val) ori $res, $res, %higher(val) 12310b57cec5SDimitry Andric // lui $res2, %hi(val) lui $res2, %hi(val) 12320b57cec5SDimitry Andric // ori $res2, %res2, %lo(val) ori $res2, %res2, %lo(val) 12330b57cec5SDimitry Andric // $res3 = fill $res2 dinsu $res, $res2, 0, 32 12340b57cec5SDimitry Andric // $res4 = insert.w $res3[1], $res fill.d $res 12350b57cec5SDimitry Andric // splat.d $res4, 0 12360b57cec5SDimitry Andric // 1237480093f4SDimitry Andric // The ability to use dinsu is guaranteed as MSA requires MIPSR5. 1238480093f4SDimitry Andric // This saves having to materialize the value by shifts and ors. 12390b57cec5SDimitry Andric // 12400b57cec5SDimitry Andric // FIXME: Implement the preferred sequence for MIPS64R6: 12410b57cec5SDimitry Andric // 12420b57cec5SDimitry Andric // MIPS64R6: 12430b57cec5SDimitry Andric // ori $res, $zero, %lo(val) 12440b57cec5SDimitry Andric // daui $res, $res, %hi(val) 12450b57cec5SDimitry Andric // dahi $res, $res, %higher(val) 12460b57cec5SDimitry Andric // dati $res, $res, %highest(cal) 12470b57cec5SDimitry Andric // fill.d $res 12480b57cec5SDimitry Andric // 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric const unsigned Lo = SplatValue.getLoBits(16).getZExtValue(); 12510b57cec5SDimitry Andric const unsigned Hi = SplatValue.lshr(16).getLoBits(16).getZExtValue(); 12520b57cec5SDimitry Andric const unsigned Higher = SplatValue.lshr(32).getLoBits(16).getZExtValue(); 12530b57cec5SDimitry Andric const unsigned Highest = SplatValue.lshr(48).getLoBits(16).getZExtValue(); 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric SDValue LoVal = CurDAG->getTargetConstant(Lo, DL, MVT::i32); 12560b57cec5SDimitry Andric SDValue HiVal = CurDAG->getTargetConstant(Hi, DL, MVT::i32); 12570b57cec5SDimitry Andric SDValue HigherVal = CurDAG->getTargetConstant(Higher, DL, MVT::i32); 12580b57cec5SDimitry Andric SDValue HighestVal = CurDAG->getTargetConstant(Highest, DL, MVT::i32); 12590b57cec5SDimitry Andric SDValue ZeroVal = CurDAG->getRegister(Mips::ZERO, MVT::i32); 12600b57cec5SDimitry Andric 12610b57cec5SDimitry Andric // Independent of whether we're targeting MIPS64 or not, the basic 12620b57cec5SDimitry Andric // operations are the same. Also, directly use the $zero register if 12630b57cec5SDimitry Andric // the 16 bit chunk is zero. 12640b57cec5SDimitry Andric // 12650b57cec5SDimitry Andric // For optimization purposes we always synthesize the splat value as 12660b57cec5SDimitry Andric // an i32 value, then if we're targetting MIPS64, use SUBREG_TO_REG 12670b57cec5SDimitry Andric // just before combining the values with dinsu to produce an i64. This 12680b57cec5SDimitry Andric // enables SelectionDAG to aggressively share components of splat values 12690b57cec5SDimitry Andric // where possible. 12700b57cec5SDimitry Andric // 12710b57cec5SDimitry Andric // FIXME: This is the general constant synthesis problem. This code 12720b57cec5SDimitry Andric // should be factored out into a class shared between all the 12730b57cec5SDimitry Andric // classes that need it. Specifically, for a splat size of 64 12740b57cec5SDimitry Andric // bits that's a negative number we can do better than LUi/ORi 12750b57cec5SDimitry Andric // for the upper 32bits. 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric if (Hi) 12780b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HiVal); 12790b57cec5SDimitry Andric 12800b57cec5SDimitry Andric if (Lo) 12810b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, 12820b57cec5SDimitry Andric Hi ? SDValue(Res, 0) : ZeroVal, LoVal); 12830b57cec5SDimitry Andric 12840b57cec5SDimitry Andric SDNode *HiRes; 12850b57cec5SDimitry Andric if (Highest) 12860b57cec5SDimitry Andric HiRes = CurDAG->getMachineNode(Mips::LUi, DL, MVT::i32, HighestVal); 12870b57cec5SDimitry Andric 12880b57cec5SDimitry Andric if (Higher) 12890b57cec5SDimitry Andric HiRes = CurDAG->getMachineNode(Mips::ORi, DL, MVT::i32, 12900b57cec5SDimitry Andric Highest ? SDValue(HiRes, 0) : ZeroVal, 12910b57cec5SDimitry Andric HigherVal); 12920b57cec5SDimitry Andric 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric if (ABI.IsO32()) { 12950b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::FILL_W, DL, MVT::v4i32, 12960b57cec5SDimitry Andric (Hi || Lo) ? SDValue(Res, 0) : ZeroVal); 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric Res = CurDAG->getMachineNode( 12990b57cec5SDimitry Andric Mips::INSERT_W, DL, MVT::v4i32, SDValue(Res, 0), 13000b57cec5SDimitry Andric (Highest || Higher) ? SDValue(HiRes, 0) : ZeroVal, 13010b57cec5SDimitry Andric CurDAG->getTargetConstant(1, DL, MVT::i32)); 13020b57cec5SDimitry Andric 13030b57cec5SDimitry Andric const TargetLowering *TLI = getTargetLowering(); 13040b57cec5SDimitry Andric const TargetRegisterClass *RC = 13050b57cec5SDimitry Andric TLI->getRegClassFor(ViaVecTy.getSimpleVT()); 13060b57cec5SDimitry Andric 13070b57cec5SDimitry Andric Res = CurDAG->getMachineNode( 13080b57cec5SDimitry Andric Mips::COPY_TO_REGCLASS, DL, ViaVecTy, SDValue(Res, 0), 13090b57cec5SDimitry Andric CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32)); 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric Res = CurDAG->getMachineNode( 13120b57cec5SDimitry Andric Mips::SPLATI_D, DL, MVT::v2i64, SDValue(Res, 0), 13130b57cec5SDimitry Andric CurDAG->getTargetConstant(0, DL, MVT::i32)); 13140b57cec5SDimitry Andric } else if (ABI.IsN64() || ABI.IsN32()) { 13150b57cec5SDimitry Andric 13160b57cec5SDimitry Andric SDValue Zero64Val = CurDAG->getRegister(Mips::ZERO_64, MVT::i64); 13170b57cec5SDimitry Andric const bool HiResNonZero = Highest || Higher; 13180b57cec5SDimitry Andric const bool ResNonZero = Hi || Lo; 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric if (HiResNonZero) 13210b57cec5SDimitry Andric HiRes = CurDAG->getMachineNode( 13220b57cec5SDimitry Andric Mips::SUBREG_TO_REG, DL, MVT::i64, 13230b57cec5SDimitry Andric CurDAG->getTargetConstant(((Highest >> 15) & 0x1), DL, MVT::i64), 13240b57cec5SDimitry Andric SDValue(HiRes, 0), 13250b57cec5SDimitry Andric CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); 13260b57cec5SDimitry Andric 13270b57cec5SDimitry Andric if (ResNonZero) 13280b57cec5SDimitry Andric Res = CurDAG->getMachineNode( 13290b57cec5SDimitry Andric Mips::SUBREG_TO_REG, DL, MVT::i64, 13300b57cec5SDimitry Andric CurDAG->getTargetConstant(((Hi >> 15) & 0x1), DL, MVT::i64), 13310b57cec5SDimitry Andric SDValue(Res, 0), 13320b57cec5SDimitry Andric CurDAG->getTargetConstant(Mips::sub_32, DL, MVT::i64)); 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric // We have 3 cases: 13350b57cec5SDimitry Andric // The HiRes is nonzero but Res is $zero => dsll32 HiRes, 0 13360b57cec5SDimitry Andric // The Res is nonzero but HiRes is $zero => dinsu Res, $zero, 32, 32 13370b57cec5SDimitry Andric // Both are non zero => dinsu Res, HiRes, 32, 32 13380b57cec5SDimitry Andric // 13390b57cec5SDimitry Andric // The obvious "missing" case is when both are zero, but that case is 13400b57cec5SDimitry Andric // handled by the ldi case. 13410b57cec5SDimitry Andric if (ResNonZero) { 13420b57cec5SDimitry Andric IntegerType *Int32Ty = 13430b57cec5SDimitry Andric IntegerType::get(MF->getFunction().getContext(), 32); 13440b57cec5SDimitry Andric const ConstantInt *Const32 = ConstantInt::get(Int32Ty, 32); 13450b57cec5SDimitry Andric SDValue Ops[4] = {HiResNonZero ? SDValue(HiRes, 0) : Zero64Val, 13460b57cec5SDimitry Andric CurDAG->getConstant(*Const32, DL, MVT::i32), 13470b57cec5SDimitry Andric CurDAG->getConstant(*Const32, DL, MVT::i32), 13480b57cec5SDimitry Andric SDValue(Res, 0)}; 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::DINSU, DL, MVT::i64, Ops); 13510b57cec5SDimitry Andric } else if (HiResNonZero) { 13520b57cec5SDimitry Andric Res = CurDAG->getMachineNode( 13530b57cec5SDimitry Andric Mips::DSLL32, DL, MVT::i64, SDValue(HiRes, 0), 13540b57cec5SDimitry Andric CurDAG->getTargetConstant(0, DL, MVT::i32)); 13550b57cec5SDimitry Andric } else 13560b57cec5SDimitry Andric llvm_unreachable( 13570b57cec5SDimitry Andric "Zero splat value handled by non-zero 64bit splat synthesis!"); 13580b57cec5SDimitry Andric 1359480093f4SDimitry Andric Res = CurDAG->getMachineNode(Mips::FILL_D, DL, MVT::v2i64, 1360480093f4SDimitry Andric SDValue(Res, 0)); 13610b57cec5SDimitry Andric } else 13620b57cec5SDimitry Andric llvm_unreachable("Unknown ABI in MipsISelDAGToDAG!"); 13630b57cec5SDimitry Andric 13640b57cec5SDimitry Andric } else 13650b57cec5SDimitry Andric return false; 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric if (ResVecTy != ViaVecTy) { 13680b57cec5SDimitry Andric // If LdiOp is writing to a different register class to ResVecTy, then 13690b57cec5SDimitry Andric // fix it up here. This COPY_TO_REGCLASS should never cause a move.v 13700b57cec5SDimitry Andric // since the source and destination register sets contain the same 13710b57cec5SDimitry Andric // registers. 13720b57cec5SDimitry Andric const TargetLowering *TLI = getTargetLowering(); 13730b57cec5SDimitry Andric MVT ResVecTySimple = ResVecTy.getSimpleVT(); 13740b57cec5SDimitry Andric const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple); 13750b57cec5SDimitry Andric Res = CurDAG->getMachineNode(Mips::COPY_TO_REGCLASS, DL, 13760b57cec5SDimitry Andric ResVecTy, SDValue(Res, 0), 13770b57cec5SDimitry Andric CurDAG->getTargetConstant(RC->getID(), DL, 13780b57cec5SDimitry Andric MVT::i32)); 13790b57cec5SDimitry Andric } 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric ReplaceNode(Node, Res); 13820b57cec5SDimitry Andric return true; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric } 13860b57cec5SDimitry Andric 13870b57cec5SDimitry Andric return false; 13880b57cec5SDimitry Andric } 13890b57cec5SDimitry Andric 13905f757f3fSDimitry Andric bool MipsSEDAGToDAGISel::SelectInlineAsmMemoryOperand( 13915f757f3fSDimitry Andric const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, 13920b57cec5SDimitry Andric std::vector<SDValue> &OutOps) { 13930b57cec5SDimitry Andric SDValue Base, Offset; 13940b57cec5SDimitry Andric 13950b57cec5SDimitry Andric switch(ConstraintID) { 13960b57cec5SDimitry Andric default: 13970b57cec5SDimitry Andric llvm_unreachable("Unexpected asm memory constraint"); 13980b57cec5SDimitry Andric // All memory constraints can at least accept raw pointers. 13995f757f3fSDimitry Andric case InlineAsm::ConstraintCode::m: 14005f757f3fSDimitry Andric case InlineAsm::ConstraintCode::o: 14010b57cec5SDimitry Andric if (selectAddrRegImm16(Op, Base, Offset)) { 14020b57cec5SDimitry Andric OutOps.push_back(Base); 14030b57cec5SDimitry Andric OutOps.push_back(Offset); 14040b57cec5SDimitry Andric return false; 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric OutOps.push_back(Op); 14070b57cec5SDimitry Andric OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); 14080b57cec5SDimitry Andric return false; 14095f757f3fSDimitry Andric case InlineAsm::ConstraintCode::R: 14100b57cec5SDimitry Andric // The 'R' constraint is supposed to be much more complicated than this. 14110b57cec5SDimitry Andric // However, it's becoming less useful due to architectural changes and 14120b57cec5SDimitry Andric // ought to be replaced by other constraints such as 'ZC'. 14130b57cec5SDimitry Andric // For now, support 9-bit signed offsets which is supportable by all 14140b57cec5SDimitry Andric // subtargets for all instructions. 14150b57cec5SDimitry Andric if (selectAddrRegImm9(Op, Base, Offset)) { 14160b57cec5SDimitry Andric OutOps.push_back(Base); 14170b57cec5SDimitry Andric OutOps.push_back(Offset); 14180b57cec5SDimitry Andric return false; 14190b57cec5SDimitry Andric } 14200b57cec5SDimitry Andric OutOps.push_back(Op); 14210b57cec5SDimitry Andric OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); 14220b57cec5SDimitry Andric return false; 14235f757f3fSDimitry Andric case InlineAsm::ConstraintCode::ZC: 14240b57cec5SDimitry Andric // ZC matches whatever the pref, ll, and sc instructions can handle for the 14250b57cec5SDimitry Andric // given subtarget. 14260b57cec5SDimitry Andric if (Subtarget->inMicroMipsMode()) { 14270b57cec5SDimitry Andric // On microMIPS, they can handle 12-bit offsets. 14280b57cec5SDimitry Andric if (selectAddrRegImm12(Op, Base, Offset)) { 14290b57cec5SDimitry Andric OutOps.push_back(Base); 14300b57cec5SDimitry Andric OutOps.push_back(Offset); 14310b57cec5SDimitry Andric return false; 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric } else if (Subtarget->hasMips32r6()) { 14340b57cec5SDimitry Andric // On MIPS32r6/MIPS64r6, they can only handle 9-bit offsets. 14350b57cec5SDimitry Andric if (selectAddrRegImm9(Op, Base, Offset)) { 14360b57cec5SDimitry Andric OutOps.push_back(Base); 14370b57cec5SDimitry Andric OutOps.push_back(Offset); 14380b57cec5SDimitry Andric return false; 14390b57cec5SDimitry Andric } 14400b57cec5SDimitry Andric } else if (selectAddrRegImm16(Op, Base, Offset)) { 14410b57cec5SDimitry Andric // Prior to MIPS32r6/MIPS64r6, they can handle 16-bit offsets. 14420b57cec5SDimitry Andric OutOps.push_back(Base); 14430b57cec5SDimitry Andric OutOps.push_back(Offset); 14440b57cec5SDimitry Andric return false; 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric // In all cases, 0-bit offsets are acceptable. 14470b57cec5SDimitry Andric OutOps.push_back(Op); 14480b57cec5SDimitry Andric OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); 14490b57cec5SDimitry Andric return false; 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric return true; 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric 14540fca6ea1SDimitry Andric MipsSEDAGToDAGISelLegacy::MipsSEDAGToDAGISelLegacy(MipsTargetMachine &TM, 14550fca6ea1SDimitry Andric CodeGenOptLevel OL) 14560fca6ea1SDimitry Andric : MipsDAGToDAGISelLegacy(std::make_unique<MipsSEDAGToDAGISel>(TM, OL)) {} 14570fca6ea1SDimitry Andric 14580b57cec5SDimitry Andric FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM, 14595f757f3fSDimitry Andric CodeGenOptLevel OptLevel) { 14600fca6ea1SDimitry Andric return new MipsSEDAGToDAGISelLegacy(TM, OptLevel); 14610b57cec5SDimitry Andric } 1462