xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp (revision 71ac745d76c3ba442e753daff1870893f272b29d)
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 
runOnMachineFunction(MachineFunction & MF)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 
getAnalysisUsage(AnalysisUsage & AU) const470fca6ea1SDimitry Andric void MipsSEDAGToDAGISelLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
480b57cec5SDimitry Andric   AU.addRequired<DominatorTreeWrapperPass>();
490fca6ea1SDimitry Andric   SelectionDAGISelLegacy::getAnalysisUsage(AU);
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
addDSPCtrlRegOperands(bool IsDef,MachineInstr & MI,MachineFunction & MF)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 
getMSACtrlReg(const SDValue RegIdx) const780b57cec5SDimitry 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 
replaceUsesWithZeroReg(MachineRegisterInfo * MRI,const MachineInstr & MI)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 
emitMCountABI(MachineInstr & MI,MachineBasicBlock & MBB,MachineFunction & MF)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 
processFunctionAfterISel(MachineFunction & MF)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 
selectAddE(SDNode * Node,const SDLoc & DL) const2060b57cec5SDimitry 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
selectAddrFrameIndex(SDValue Addr,SDValue & Base,SDValue & Offset) const2680b57cec5SDimitry 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
selectAddrFrameIndexOffset(SDValue Addr,SDValue & Base,SDValue & Offset,unsigned OffsetBits,unsigned ShiftAmount=0) const2810b57cec5SDimitry 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
selectAddrRegImm(SDValue Addr,SDValue & Base,SDValue & Offset) const3120b57cec5SDimitry 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
selectAddrDefault(SDValue Addr,SDValue & Base,SDValue & Offset) const3620b57cec5SDimitry 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 
selectIntAddr(SDValue Addr,SDValue & Base,SDValue & Offset) const3690b57cec5SDimitry 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 
selectAddrRegImm9(SDValue Addr,SDValue & Base,SDValue & Offset) const3750b57cec5SDimitry 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)
selectAddrRegImm11(SDValue Addr,SDValue & Base,SDValue & Offset) const3870b57cec5SDimitry 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)
selectAddrRegImm12(SDValue Addr,SDValue & Base,SDValue & Offset) const3990b57cec5SDimitry 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 
selectAddrRegImm16(SDValue Addr,SDValue & Base,SDValue & Offset) const4100b57cec5SDimitry 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 
selectIntAddr11MM(SDValue Addr,SDValue & Base,SDValue & Offset) const4210b57cec5SDimitry 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 
selectIntAddr12MM(SDValue Addr,SDValue & Base,SDValue & Offset) const4270b57cec5SDimitry 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 
selectIntAddr16MM(SDValue Addr,SDValue & Base,SDValue & Offset) const4330b57cec5SDimitry 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 
selectIntAddrLSL2MM(SDValue Addr,SDValue & Base,SDValue & Offset) const4390b57cec5SDimitry 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 
selectIntAddrSImm10(SDValue Addr,SDValue & Base,SDValue & Offset) const4610b57cec5SDimitry 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 
selectIntAddrSImm10Lsl1(SDValue Addr,SDValue & Base,SDValue & Offset) const4730b57cec5SDimitry 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 
selectIntAddrSImm10Lsl2(SDValue Addr,SDValue & Base,SDValue & Offset) const4840b57cec5SDimitry 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 
selectIntAddrSImm10Lsl3(SDValue Addr,SDValue & Base,SDValue & Offset) const4950b57cec5SDimitry 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
selectVSplat(SDNode * N,APInt & Imm,unsigned MinSizeInBits) const5110b57cec5SDimitry 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::
selectVSplatCommon(SDValue N,SDValue & Imm,bool Signed,unsigned ImmBitSize) const5510b57cec5SDimitry 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::
selectVSplatUimm1(SDValue N,SDValue & Imm) const5740b57cec5SDimitry Andric selectVSplatUimm1(SDValue N, SDValue &Imm) const {
5750b57cec5SDimitry Andric   return selectVSplatCommon(N, Imm, false, 1);
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::
selectVSplatUimm2(SDValue N,SDValue & Imm) const5790b57cec5SDimitry Andric selectVSplatUimm2(SDValue N, SDValue &Imm) const {
5800b57cec5SDimitry Andric   return selectVSplatCommon(N, Imm, false, 2);
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric bool MipsSEDAGToDAGISel::
selectVSplatUimm3(SDValue N,SDValue & Imm) const5840b57cec5SDimitry 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::
selectVSplatUimm4(SDValue N,SDValue & Imm) const5900b57cec5SDimitry 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::
selectVSplatUimm5(SDValue N,SDValue & Imm) const5960b57cec5SDimitry 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::
selectVSplatUimm6(SDValue N,SDValue & Imm) const6020b57cec5SDimitry 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::
selectVSplatUimm8(SDValue N,SDValue & Imm) const6080b57cec5SDimitry 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::
selectVSplatSimm5(SDValue N,SDValue & Imm) const6140b57cec5SDimitry 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.
selectVSplatUimmPow2(SDValue N,SDValue & Imm) const6280b57cec5SDimitry 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.
selectVSplatMaskL(SDValue N,SDValue & Imm) const6590b57cec5SDimitry 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.
selectVSplatMaskR(SDValue N,SDValue & Imm) const6920b57cec5SDimitry 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 
selectVSplatUimmInvPow2(SDValue N,SDValue & Imm) const7120b57cec5SDimitry 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.
selectVSplatImmEq1(SDValue N) const734*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 
trySelect(SDNode * Node)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 
SelectInlineAsmMemoryOperand(const SDValue & Op,InlineAsm::ConstraintCode ConstraintID,std::vector<SDValue> & OutOps)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 
MipsSEDAGToDAGISelLegacy(MipsTargetMachine & TM,CodeGenOptLevel OL)14540fca6ea1SDimitry Andric MipsSEDAGToDAGISelLegacy::MipsSEDAGToDAGISelLegacy(MipsTargetMachine &TM,
14550fca6ea1SDimitry Andric                                                    CodeGenOptLevel OL)
14560fca6ea1SDimitry Andric     : MipsDAGToDAGISelLegacy(std::make_unique<MipsSEDAGToDAGISel>(TM, OL)) {}
14570fca6ea1SDimitry Andric 
createMipsSEISelDag(MipsTargetMachine & TM,CodeGenOptLevel OptLevel)14580b57cec5SDimitry Andric FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM,
14595f757f3fSDimitry Andric                                         CodeGenOptLevel OptLevel) {
14600fca6ea1SDimitry Andric   return new MipsSEDAGToDAGISelLegacy(TM, OptLevel);
14610b57cec5SDimitry Andric }
1462