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 MipsDAGToDAGISel::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 SelectionDAGISel::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 /// Convert vector addition with vector subtraction if that allows to encode 224 /// constant as an immediate and thus avoid extra 'ldi' instruction. 225 /// add X, <-1, -1...> --> sub X, <1, 1...> 226 bool MipsDAGToDAGISel::selectVecAddAsVecSubIfProfitable(SDNode *Node) { 227 assert(Node->getOpcode() == ISD::ADD && "Should only get 'add' here."); 228 229 EVT VT = Node->getValueType(0); 230 assert(VT.isVector() && "Should only be called for vectors."); 231 232 SDValue X = Node->getOperand(0); 233 SDValue C = Node->getOperand(1); 234 235 auto *BVN = dyn_cast<BuildVectorSDNode>(C); 236 if (!BVN) 237 return false; 238 239 APInt SplatValue, SplatUndef; 240 unsigned SplatBitSize; 241 bool HasAnyUndefs; 242 243 if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 244 8, !Subtarget->isLittle())) 245 return false; 246 247 auto IsInlineConstant = [](const APInt &Imm) { return Imm.isIntN(5); }; 248 249 if (IsInlineConstant(SplatValue)) 250 return false; // Can already be encoded as an immediate. 251 252 APInt NegSplatValue = 0 - SplatValue; 253 if (!IsInlineConstant(NegSplatValue)) 254 return false; // Even if we negate it it won't help. 255 256 SDLoc DL(Node); 257 258 SDValue NegC = CurDAG->FoldConstantArithmetic( 259 ISD::SUB, DL, VT, {CurDAG->getConstant(0, DL, VT), C}); 260 assert(NegC && "Constant-folding failed!"); 261 SDValue NewNode = CurDAG->getNode(ISD::SUB, DL, VT, X, NegC); 262 263 ReplaceNode(Node, NewNode.getNode()); 264 SelectCode(NewNode.getNode()); 265 return true; 266 } 267 268 /// Select instructions not customized! Used for 269 /// expanded, promoted and normal instructions 270 void MipsDAGToDAGISel::Select(SDNode *Node) { 271 unsigned Opcode = Node->getOpcode(); 272 273 // If we have a custom node, we already have selected! 274 if (Node->isMachineOpcode()) { 275 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 276 Node->setNodeId(-1); 277 return; 278 } 279 280 // See if subclasses can handle this node. 281 if (trySelect(Node)) 282 return; 283 284 switch(Opcode) { 285 default: break; 286 287 case ISD::ADD: 288 if (Node->getSimpleValueType(0).isVector() && 289 selectVecAddAsVecSubIfProfitable(Node)) 290 return; 291 break; 292 293 // Get target GOT address. 294 case ISD::GLOBAL_OFFSET_TABLE: 295 ReplaceNode(Node, getGlobalBaseReg()); 296 return; 297 298 #ifndef NDEBUG 299 case ISD::LOAD: 300 case ISD::STORE: 301 assert((Subtarget->systemSupportsUnalignedAccess() || 302 cast<MemSDNode>(Node)->getAlign() >= 303 cast<MemSDNode>(Node)->getMemoryVT().getStoreSize()) && 304 "Unexpected unaligned loads/stores."); 305 break; 306 #endif 307 } 308 309 // Select the default instruction 310 SelectCode(Node); 311 } 312 313 bool MipsDAGToDAGISel::SelectInlineAsmMemoryOperand( 314 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, 315 std::vector<SDValue> &OutOps) { 316 // All memory constraints can at least accept raw pointers. 317 switch(ConstraintID) { 318 default: 319 llvm_unreachable("Unexpected asm memory constraint"); 320 case InlineAsm::ConstraintCode::m: 321 case InlineAsm::ConstraintCode::R: 322 case InlineAsm::ConstraintCode::ZC: 323 OutOps.push_back(Op); 324 return false; 325 } 326 return true; 327 } 328 329 bool MipsDAGToDAGISel::isUnneededShiftMask(SDNode *N, 330 unsigned ShAmtBits) const { 331 assert(N->getOpcode() == ISD::AND && "Unexpected opcode"); 332 333 const APInt &RHS = N->getConstantOperandAPInt(1); 334 if (RHS.countr_one() >= ShAmtBits) { 335 LLVM_DEBUG( 336 dbgs() 337 << DEBUG_TYPE 338 << " Need optimize 'and & shl/srl/sra' and operand value bits is " 339 << RHS.countr_one() << "\n"); 340 return true; 341 } 342 343 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0)); 344 return (Known.Zero | RHS).countr_one() >= ShAmtBits; 345 } 346 347 char MipsDAGToDAGISel::ID = 0; 348 349 INITIALIZE_PASS(MipsDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false) 350