1 //===-- MipsISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips --------===// 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 // This file defines an instruction selector for the MIPS target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MipsISelDAGToDAG.h" 14 #include "MCTargetDesc/MipsBaseInfo.h" 15 #include "Mips.h" 16 #include "Mips16ISelDAGToDAG.h" 17 #include "MipsMachineFunction.h" 18 #include "MipsRegisterInfo.h" 19 #include "MipsSEISelDAGToDAG.h" 20 #include "llvm/CodeGen/MachineConstantPool.h" 21 #include "llvm/CodeGen/MachineFrameInfo.h" 22 #include "llvm/CodeGen/MachineFunction.h" 23 #include "llvm/CodeGen/MachineInstrBuilder.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/CodeGen/SelectionDAG.h" 26 #include "llvm/CodeGen/SelectionDAGNodes.h" 27 #include "llvm/CodeGen/StackProtector.h" 28 #include "llvm/IR/CFG.h" 29 #include "llvm/IR/GlobalValue.h" 30 #include "llvm/IR/Instructions.h" 31 #include "llvm/IR/Intrinsics.h" 32 #include "llvm/IR/Type.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/KnownBits.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include "llvm/Target/TargetMachine.h" 38 using namespace llvm; 39 40 #define DEBUG_TYPE "mips-isel" 41 #define PASS_NAME "MIPS DAG->DAG Pattern Instruction Selection" 42 43 //===----------------------------------------------------------------------===// 44 // Instruction Selector Implementation 45 //===----------------------------------------------------------------------===// 46 47 //===----------------------------------------------------------------------===// 48 // MipsDAGToDAGISel - MIPS specific code to select MIPS machine 49 // instructions for SelectionDAG operations. 50 //===----------------------------------------------------------------------===// 51 52 void MipsDAGToDAGISelLegacy::getAnalysisUsage(AnalysisUsage &AU) const { 53 // There are multiple MipsDAGToDAGISel instances added to the pass pipeline. 54 // We need to preserve StackProtector for the next one. 55 AU.addPreserved<StackProtector>(); 56 SelectionDAGISelLegacy::getAnalysisUsage(AU); 57 } 58 59 bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 60 Subtarget = &MF.getSubtarget<MipsSubtarget>(); 61 bool Ret = SelectionDAGISel::runOnMachineFunction(MF); 62 63 processFunctionAfterISel(MF); 64 65 return Ret; 66 } 67 68 /// getGlobalBaseReg - Output the instructions required to put the 69 /// GOT address into a register. 70 SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { 71 Register GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg(*MF); 72 return CurDAG->getRegister(GlobalBaseReg, getTargetLowering()->getPointerTy( 73 CurDAG->getDataLayout())) 74 .getNode(); 75 } 76 77 /// ComplexPattern used on MipsInstrInfo 78 /// Used on Mips Load/Store instructions 79 bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, 80 SDValue &Offset) const { 81 llvm_unreachable("Unimplemented function."); 82 return false; 83 } 84 85 bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, 86 SDValue &Offset) const { 87 llvm_unreachable("Unimplemented function."); 88 return false; 89 } 90 91 bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, 92 SDValue &Offset) const { 93 llvm_unreachable("Unimplemented function."); 94 return false; 95 } 96 97 bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, 98 SDValue &Offset) const { 99 llvm_unreachable("Unimplemented function."); 100 return false; 101 } 102 103 bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, 104 SDValue &Offset) const { 105 llvm_unreachable("Unimplemented function."); 106 return false; 107 } 108 109 bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, 110 SDValue &Offset) const { 111 llvm_unreachable("Unimplemented function."); 112 return false; 113 } 114 115 bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, 116 SDValue &Offset) const { 117 llvm_unreachable("Unimplemented function."); 118 return false; 119 } 120 121 bool MipsDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base, 122 SDValue &Offset) const { 123 llvm_unreachable("Unimplemented function."); 124 return false; 125 } 126 127 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl1(SDValue Addr, SDValue &Base, 128 SDValue &Offset) const { 129 llvm_unreachable("Unimplemented function."); 130 return false; 131 } 132 133 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl2(SDValue Addr, SDValue &Base, 134 SDValue &Offset) const { 135 llvm_unreachable("Unimplemented function."); 136 return false; 137 } 138 139 bool MipsDAGToDAGISel::selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, 140 SDValue &Offset) const { 141 llvm_unreachable("Unimplemented function."); 142 return false; 143 } 144 145 bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, 146 SDValue &Offset) { 147 llvm_unreachable("Unimplemented function."); 148 return false; 149 } 150 151 bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, 152 SDValue &Offset) { 153 llvm_unreachable("Unimplemented function."); 154 return false; 155 } 156 157 bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, 158 unsigned MinSizeInBits) const { 159 llvm_unreachable("Unimplemented function."); 160 return false; 161 } 162 163 bool MipsDAGToDAGISel::selectVSplatUimm1(SDValue N, SDValue &Imm) const { 164 llvm_unreachable("Unimplemented function."); 165 return false; 166 } 167 168 bool MipsDAGToDAGISel::selectVSplatUimm2(SDValue N, SDValue &Imm) const { 169 llvm_unreachable("Unimplemented function."); 170 return false; 171 } 172 173 bool MipsDAGToDAGISel::selectVSplatUimm3(SDValue N, SDValue &Imm) const { 174 llvm_unreachable("Unimplemented function."); 175 return false; 176 } 177 178 bool MipsDAGToDAGISel::selectVSplatUimm4(SDValue N, SDValue &Imm) const { 179 llvm_unreachable("Unimplemented function."); 180 return false; 181 } 182 183 bool MipsDAGToDAGISel::selectVSplatUimm5(SDValue N, SDValue &Imm) const { 184 llvm_unreachable("Unimplemented function."); 185 return false; 186 } 187 188 bool MipsDAGToDAGISel::selectVSplatUimm6(SDValue N, SDValue &Imm) const { 189 llvm_unreachable("Unimplemented function."); 190 return false; 191 } 192 193 bool MipsDAGToDAGISel::selectVSplatUimm8(SDValue N, SDValue &Imm) const { 194 llvm_unreachable("Unimplemented function."); 195 return false; 196 } 197 198 bool MipsDAGToDAGISel::selectVSplatSimm5(SDValue N, SDValue &Imm) const { 199 llvm_unreachable("Unimplemented function."); 200 return false; 201 } 202 203 bool MipsDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const { 204 llvm_unreachable("Unimplemented function."); 205 return false; 206 } 207 208 bool MipsDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const { 209 llvm_unreachable("Unimplemented function."); 210 return false; 211 } 212 213 bool MipsDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { 214 llvm_unreachable("Unimplemented function."); 215 return false; 216 } 217 218 bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { 219 llvm_unreachable("Unimplemented function."); 220 return false; 221 } 222 223 bool MipsDAGToDAGISel::selectVSplatImmEq1(SDValue N) const { 224 llvm_unreachable("Unimplemented function."); 225 } 226 227 /// Convert vector addition with vector subtraction if that allows to encode 228 /// constant as an immediate and thus avoid extra 'ldi' instruction. 229 /// add X, <-1, -1...> --> sub X, <1, 1...> 230 bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) { 231 assert(Node->getOpcode() == ISD::ADD && "Should only get 'add' here."); 232 233 EVT VT = Node->getValueType(0); 234 assert(VT.isVector() && "Should only be called for vectors."); 235 236 SDValue X = Node->getOperand(0); 237 SDValue C = Node->getOperand(1); 238 239 auto *BVN = dyn_cast<BuildVectorSDNode>(C); 240 if (!BVN) 241 return false; 242 243 APInt SplatValue, SplatUndef; 244 unsigned SplatBitSize; 245 bool HasAnyUndefs; 246 247 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 248 8, !Subtarget->isLittle())) 249 return false; 250 251 auto IsInlineConstant = [](const APInt &Imm) { return Imm.isIntN(5); }; 252 253 if (IsInlineConstant(SplatValue)) 254 return false; // Can already be encoded as an immediate. 255 256 APInt NegSplatValue = 0 - SplatValue; 257 if (!IsInlineConstant(NegSplatValue)) 258 return false; // Even if we negate it it won't help. 259 260 SDLoc DL(Node); 261 262 SDValue NegC = CurDAG->FoldConstantArithmetic( 263 ISD::SUB, DL, VT, {CurDAG->getConstant(0, DL, VT), C}); 264 assert(NegC && "Constant-folding failed!"); 265 SDValue NewNode = CurDAG->getNode(ISD::SUB, DL, VT, X, NegC); 266 267 ReplaceNode(Node, NewNode.getNode()); 268 SelectCode(NewNode.getNode()); 269 return true; 270 } 271 272 /// Select instructions not customized! Used for 273 /// expanded, promoted and normal instructions 274 void MipsDAGToDAGISel::Select(SDNode *Node) { 275 unsigned Opcode = Node->getOpcode(); 276 277 // If we have a custom node, we already have selected! 278 if (Node->isMachineOpcode()) { 279 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 280 Node->setNodeId(-1); 281 return; 282 } 283 284 // See if subclasses can handle this node. 285 if (trySelect(Node)) 286 return; 287 288 switch(Opcode) { 289 default: break; 290 291 case ISD::ADD: 292 if (Node->getSimpleValueType(0).isVector() && 293 selectVecAddAsVecSubIfProfitable(Node)) 294 return; 295 break; 296 297 // Get target GOT address. 298 case ISD::GLOBAL_OFFSET_TABLE: 299 ReplaceNode(Node, getGlobalBaseReg()); 300 return; 301 302 #ifndef NDEBUG 303 case ISD::LOAD: 304 case ISD::STORE: 305 assert((Subtarget->systemSupportsUnalignedAccess() || 306 cast<MemSDNode>(Node)->getAlign() >= 307 cast<MemSDNode>(Node)->getMemoryVT().getStoreSize()) && 308 "Unexpected unaligned loads/stores."); 309 break; 310 #endif 311 } 312 313 // Select the default instruction 314 SelectCode(Node); 315 } 316 317 bool MipsDAGToDAGISel::SelectInlineAsmMemoryOperand( 318 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, 319 std::vector<SDValue> &OutOps) { 320 // All memory constraints can at least accept raw pointers. 321 switch(ConstraintID) { 322 default: 323 llvm_unreachable("Unexpected asm memory constraint"); 324 case InlineAsm::ConstraintCode::m: 325 case InlineAsm::ConstraintCode::R: 326 case InlineAsm::ConstraintCode::ZC: 327 OutOps.push_back(Op); 328 return false; 329 } 330 return true; 331 } 332 333 bool MipsDAGToDAGISel::isUnneededShiftMask(SDNode *N, 334 unsigned ShAmtBits) const { 335 assert(N->getOpcode() == ISD::AND && "Unexpected opcode"); 336 337 const APInt &RHS = N->getConstantOperandAPInt(1); 338 if (RHS.countr_one() >= ShAmtBits) { 339 LLVM_DEBUG( 340 dbgs() 341 << DEBUG_TYPE 342 << " Need optimize 'and & shl/srl/sra' and operand value bits is " 343 << RHS.countr_one() << "\n"); 344 return true; 345 } 346 347 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); 348 return (Known.Zero | RHS).countr_one() >= ShAmtBits; 349 } 350 351 char MipsDAGToDAGISelLegacy::ID = 0; 352 353 MipsDAGToDAGISelLegacy::MipsDAGToDAGISelLegacy( 354 std::unique_ptr<SelectionDAGISel> S) 355 : SelectionDAGISelLegacy(ID, std::move(S)) {} 356 357 INITIALIZE_PASS(MipsDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false) 358