1 //===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Subclass of MipsDAGToDAGISel specialized for mips16. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "Mips16ISelDAGToDAG.h" 14 #include "MCTargetDesc/MipsBaseInfo.h" 15 #include "Mips.h" 16 #include "MipsMachineFunction.h" 17 #include "MipsRegisterInfo.h" 18 #include "llvm/CodeGen/MachineFrameInfo.h" 19 #include "llvm/CodeGen/MachineFunction.h" 20 #include "llvm/CodeGen/MachineInstrBuilder.h" 21 #include "llvm/CodeGen/MachineRegisterInfo.h" 22 #include "llvm/CodeGen/SelectionDAGNodes.h" 23 #include "llvm/Target/TargetMachine.h" 24 using namespace llvm; 25 26 #define DEBUG_TYPE "mips-isel" 27 28 bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 29 Subtarget = &MF.getSubtarget<MipsSubtarget>(); 30 if (!Subtarget->inMips16Mode()) 31 return false; 32 return MipsDAGToDAGISel::runOnMachineFunction(MF); 33 } 34 /// Select multiply instructions. 35 std::pair<SDNode *, SDNode *> 36 Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty, 37 bool HasLo, bool HasHi) { 38 SDNode *Lo = nullptr, *Hi = nullptr; 39 SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0), 40 N->getOperand(1)); 41 SDValue InGlue = SDValue(Mul, 0); 42 43 if (HasLo) { 44 unsigned Opcode = Mips::Mflo16; 45 Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InGlue); 46 InGlue = SDValue(Lo, 1); 47 } 48 if (HasHi) { 49 unsigned Opcode = Mips::Mfhi16; 50 Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InGlue); 51 } 52 return std::make_pair(Lo, Hi); 53 } 54 55 void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { 56 MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); 57 58 if (!MipsFI->globalBaseRegSet()) 59 return; 60 61 MachineBasicBlock &MBB = MF.front(); 62 MachineBasicBlock::iterator I = MBB.begin(); 63 MachineRegisterInfo &RegInfo = MF.getRegInfo(); 64 const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); 65 DebugLoc DL; 66 Register V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(MF); 67 const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; 68 69 V0 = RegInfo.createVirtualRegister(RC); 70 V1 = RegInfo.createVirtualRegister(RC); 71 V2 = RegInfo.createVirtualRegister(RC); 72 73 74 BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0) 75 .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); 76 BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1) 77 .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); 78 79 BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16); 80 BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg) 81 .addReg(V1) 82 .addReg(V2); 83 } 84 85 void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { 86 initGlobalBaseReg(MF); 87 } 88 89 bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, 90 SDValue &Offset) { 91 SDLoc DL(Addr); 92 EVT ValTy = Addr.getValueType(); 93 94 // if Address is FI, get the TargetFrameIndex. 95 if (SPAllowed) { 96 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 97 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 98 Offset = CurDAG->getTargetConstant(0, DL, ValTy); 99 return true; 100 } 101 } 102 // on PIC code Load GA 103 if (Addr.getOpcode() == MipsISD::Wrapper) { 104 Base = Addr.getOperand(0); 105 Offset = Addr.getOperand(1); 106 return true; 107 } 108 if (!TM.isPositionIndependent()) { 109 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 110 Addr.getOpcode() == ISD::TargetGlobalAddress)) 111 return false; 112 } 113 // Addresses of the form FI+const or FI|const 114 if (CurDAG->isBaseWithConstantOffset(Addr)) { 115 auto *CN = cast<ConstantSDNode>(Addr.getOperand(1)); 116 if (isInt<16>(CN->getSExtValue())) { 117 // If the first operand is a FI, get the TargetFI Node 118 if (SPAllowed) { 119 if (FrameIndexSDNode *FIN = 120 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 121 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 122 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); 123 return true; 124 } 125 } 126 127 Base = Addr.getOperand(0); 128 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); 129 return true; 130 } 131 } 132 // Operand is a result from an ADD. 133 if (Addr.getOpcode() == ISD::ADD) { 134 // When loading from constant pools, load the lower address part in 135 // the instruction itself. Example, instead of: 136 // lui $2, %hi($CPI1_0) 137 // addiu $2, $2, %lo($CPI1_0) 138 // lwc1 $f0, 0($2) 139 // Generate: 140 // lui $2, %hi($CPI1_0) 141 // lwc1 $f0, %lo($CPI1_0)($2) 142 if (Addr.getOperand(1).getOpcode() == MipsISD::Lo || 143 Addr.getOperand(1).getOpcode() == MipsISD::GPRel) { 144 SDValue Opnd0 = Addr.getOperand(1).getOperand(0); 145 if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) || 146 isa<JumpTableSDNode>(Opnd0)) { 147 Base = Addr.getOperand(0); 148 Offset = Opnd0; 149 return true; 150 } 151 } 152 } 153 Base = Addr; 154 Offset = CurDAG->getTargetConstant(0, DL, ValTy); 155 return true; 156 } 157 158 bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, 159 SDValue &Offset) { 160 return selectAddr(false, Addr, Base, Offset); 161 } 162 163 bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, 164 SDValue &Offset) { 165 return selectAddr(true, Addr, Base, Offset); 166 } 167 168 /// Select instructions not customized! Used for 169 /// expanded, promoted and normal instructions 170 bool Mips16DAGToDAGISel::trySelect(SDNode *Node) { 171 unsigned Opcode = Node->getOpcode(); 172 SDLoc DL(Node); 173 174 /// 175 // Instruction Selection not handled by the auto-generated 176 // tablegen selection should be handled here. 177 /// 178 EVT NodeTy = Node->getValueType(0); 179 unsigned MultOpc; 180 181 switch (Opcode) { 182 default: 183 break; 184 185 /// Mul with two results 186 case ISD::SMUL_LOHI: 187 case ISD::UMUL_LOHI: { 188 MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16); 189 std::pair<SDNode *, SDNode *> LoHi = 190 selectMULT(Node, MultOpc, DL, NodeTy, true, true); 191 if (!SDValue(Node, 0).use_empty()) 192 ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0)); 193 194 if (!SDValue(Node, 1).use_empty()) 195 ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0)); 196 197 CurDAG->RemoveDeadNode(Node); 198 return true; 199 } 200 201 case ISD::MULHS: 202 case ISD::MULHU: { 203 MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16); 204 auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true); 205 ReplaceNode(Node, LoHi.second); 206 return true; 207 } 208 } 209 210 return false; 211 } 212 213 Mips16DAGToDAGISelLegacy::Mips16DAGToDAGISelLegacy(MipsTargetMachine &TM, 214 CodeGenOptLevel OL) 215 : MipsDAGToDAGISelLegacy(std::make_unique<Mips16DAGToDAGISel>(TM, OL)) {} 216 217 FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM, 218 CodeGenOptLevel OptLevel) { 219 return new Mips16DAGToDAGISelLegacy(TM, OptLevel); 220 } 221