1 //===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an instruction selector for the MIPS target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "mips-isel" 15 #include "Mips.h" 16 #include "MipsMachineFunction.h" 17 #include "MipsRegisterInfo.h" 18 #include "MipsSubtarget.h" 19 #include "MipsTargetMachine.h" 20 #include "llvm/GlobalValue.h" 21 #include "llvm/Instructions.h" 22 #include "llvm/Intrinsics.h" 23 #include "llvm/Support/CFG.h" 24 #include "llvm/Type.h" 25 #include "llvm/CodeGen/MachineConstantPool.h" 26 #include "llvm/CodeGen/MachineFunction.h" 27 #include "llvm/CodeGen/MachineFrameInfo.h" 28 #include "llvm/CodeGen/MachineInstrBuilder.h" 29 #include "llvm/CodeGen/MachineRegisterInfo.h" 30 #include "llvm/CodeGen/SelectionDAGISel.h" 31 #include "llvm/Target/TargetMachine.h" 32 #include "llvm/Support/Debug.h" 33 #include "llvm/Support/ErrorHandling.h" 34 #include "llvm/Support/raw_ostream.h" 35 using namespace llvm; 36 37 //===----------------------------------------------------------------------===// 38 // Instruction Selector Implementation 39 //===----------------------------------------------------------------------===// 40 41 //===----------------------------------------------------------------------===// 42 // MipsDAGToDAGISel - MIPS specific code to select MIPS machine 43 // instructions for SelectionDAG operations. 44 //===----------------------------------------------------------------------===// 45 namespace { 46 47 class MipsDAGToDAGISel : public SelectionDAGISel { 48 49 /// TM - Keep a reference to MipsTargetMachine. 50 MipsTargetMachine &TM; 51 52 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can 53 /// make the right decision when generating code for different targets. 54 const MipsSubtarget &Subtarget; 55 56 public: 57 explicit MipsDAGToDAGISel(MipsTargetMachine &tm) : 58 SelectionDAGISel(tm), 59 TM(tm), Subtarget(tm.getSubtarget<MipsSubtarget>()) {} 60 61 // Pass Name 62 virtual const char *getPassName() const { 63 return "MIPS DAG->DAG Pattern Instruction Selection"; 64 } 65 66 67 private: 68 // Include the pieces autogenerated from the target description. 69 #include "MipsGenDAGISel.inc" 70 71 /// getTargetMachine - Return a reference to the TargetMachine, casted 72 /// to the target-specific type. 73 const MipsTargetMachine &getTargetMachine() { 74 return static_cast<const MipsTargetMachine &>(TM); 75 } 76 77 /// getInstrInfo - Return a reference to the TargetInstrInfo, casted 78 /// to the target-specific type. 79 const MipsInstrInfo *getInstrInfo() { 80 return getTargetMachine().getInstrInfo(); 81 } 82 83 SDNode *getGlobalBaseReg(); 84 SDNode *Select(SDNode *N); 85 86 // Complex Pattern. 87 bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset); 88 89 SDNode *SelectLoadFp64(SDNode *N); 90 SDNode *SelectStoreFp64(SDNode *N); 91 92 // getI32Imm - Return a target constant with the specified 93 // value, of type i32. 94 inline SDValue getI32Imm(unsigned Imm) { 95 return CurDAG->getTargetConstant(Imm, MVT::i32); 96 } 97 98 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 99 char ConstraintCode, 100 std::vector<SDValue> &OutOps); 101 }; 102 103 } 104 105 106 /// getGlobalBaseReg - Output the instructions required to put the 107 /// GOT address into a register. 108 SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { 109 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); 110 return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); 111 } 112 113 /// ComplexPattern used on MipsInstrInfo 114 /// Used on Mips Load/Store instructions 115 bool MipsDAGToDAGISel:: 116 SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { 117 // if Address is FI, get the TargetFrameIndex. 118 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 119 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 120 Offset = CurDAG->getTargetConstant(0, MVT::i32); 121 return true; 122 } 123 124 // on PIC code Load GA 125 if (TM.getRelocationModel() == Reloc::PIC_) { 126 if (Addr.getOpcode() == MipsISD::WrapperPIC) { 127 Base = CurDAG->getRegister(Mips::GP, MVT::i32); 128 Offset = Addr.getOperand(0); 129 return true; 130 } 131 } else { 132 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 133 Addr.getOpcode() == ISD::TargetGlobalAddress)) 134 return false; 135 else if (Addr.getOpcode() == ISD::TargetGlobalTLSAddress) { 136 Base = CurDAG->getRegister(Mips::GP, MVT::i32); 137 Offset = Addr; 138 return true; 139 } 140 } 141 142 // Addresses of the form FI+const or FI|const 143 if (CurDAG->isBaseWithConstantOffset(Addr)) { 144 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); 145 if (isInt<16>(CN->getSExtValue())) { 146 147 // If the first operand is a FI, get the TargetFI Node 148 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> 149 (Addr.getOperand(0))) 150 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 151 else 152 Base = Addr.getOperand(0); 153 154 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); 155 return true; 156 } 157 } 158 159 // Operand is a result from an ADD. 160 if (Addr.getOpcode() == ISD::ADD) { 161 // When loading from constant pools, load the lower address part in 162 // the instruction itself. Example, instead of: 163 // lui $2, %hi($CPI1_0) 164 // addiu $2, $2, %lo($CPI1_0) 165 // lwc1 $f0, 0($2) 166 // Generate: 167 // lui $2, %hi($CPI1_0) 168 // lwc1 $f0, %lo($CPI1_0)($2) 169 if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi || 170 Addr.getOperand(0).getOpcode() == ISD::LOAD) && 171 Addr.getOperand(1).getOpcode() == MipsISD::Lo) { 172 SDValue LoVal = Addr.getOperand(1); 173 if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || 174 isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { 175 Base = Addr.getOperand(0); 176 Offset = LoVal.getOperand(0); 177 return true; 178 } 179 } 180 } 181 182 Base = Addr; 183 Offset = CurDAG->getTargetConstant(0, MVT::i32); 184 return true; 185 } 186 187 SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { 188 MVT::SimpleValueType NVT = 189 N->getValueType(0).getSimpleVT().SimpleTy; 190 191 if (!Subtarget.isMips1() || NVT != MVT::f64) 192 return NULL; 193 194 LoadSDNode *LN = cast<LoadSDNode>(N); 195 if (LN->getExtensionType() != ISD::NON_EXTLOAD || 196 LN->getAddressingMode() != ISD::UNINDEXED) 197 return NULL; 198 199 SDValue Chain = N->getOperand(0); 200 SDValue N1 = N->getOperand(1); 201 SDValue Offset0, Offset1, Base; 202 203 if (!SelectAddr(N1, Base, Offset0) || 204 N1.getValueType() != MVT::i32) 205 return NULL; 206 207 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); 208 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand(); 209 DebugLoc dl = N->getDebugLoc(); 210 211 // The second load should start after for 4 bytes. 212 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0)) 213 Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); 214 else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Offset0)) 215 Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(), 216 MVT::i32, 217 CP->getAlignment(), 218 CP->getOffset()+4, 219 CP->getTargetFlags()); 220 else 221 return NULL; 222 223 // Choose the offsets depending on the endianess 224 if (TM.getTargetData()->isBigEndian()) 225 std::swap(Offset0, Offset1); 226 227 // Instead of: 228 // ldc $f0, X($3) 229 // Generate: 230 // lwc $f0, X($3) 231 // lwc $f1, X+4($3) 232 SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, 233 MVT::Other, Base, Offset0, Chain); 234 SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, 235 dl, NVT), 0); 236 SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, 237 MVT::f64, Undef, SDValue(LD0, 0)); 238 239 SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, 240 MVT::Other, Base, Offset1, SDValue(LD0, 1)); 241 SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, 242 MVT::f64, I0, SDValue(LD1, 0)); 243 244 ReplaceUses(SDValue(N, 0), I1); 245 ReplaceUses(SDValue(N, 1), Chain); 246 cast<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1); 247 cast<MachineSDNode>(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1); 248 return I1.getNode(); 249 } 250 251 SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) { 252 253 if (!Subtarget.isMips1() || 254 N->getOperand(1).getValueType() != MVT::f64) 255 return NULL; 256 257 SDValue Chain = N->getOperand(0); 258 259 StoreSDNode *SN = cast<StoreSDNode>(N); 260 if (SN->isTruncatingStore() || SN->getAddressingMode() != ISD::UNINDEXED) 261 return NULL; 262 263 SDValue N1 = N->getOperand(1); 264 SDValue N2 = N->getOperand(2); 265 SDValue Offset0, Offset1, Base; 266 267 if (!SelectAddr(N2, Base, Offset0) || 268 N1.getValueType() != MVT::f64 || 269 N2.getValueType() != MVT::i32) 270 return NULL; 271 272 MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); 273 MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand(); 274 DebugLoc dl = N->getDebugLoc(); 275 276 // Get the even and odd part from the f64 register 277 SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::sub_fpodd, 278 dl, MVT::f32, N1); 279 SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::sub_fpeven, 280 dl, MVT::f32, N1); 281 282 // The second store should start after for 4 bytes. 283 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0)) 284 Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); 285 else 286 return NULL; 287 288 // Choose the offsets depending on the endianess 289 if (TM.getTargetData()->isBigEndian()) 290 std::swap(Offset0, Offset1); 291 292 // Instead of: 293 // sdc $f0, X($3) 294 // Generate: 295 // swc $f0, X($3) 296 // swc $f1, X+4($3) 297 SDValue Ops0[] = { FPEven, Base, Offset0, Chain }; 298 Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, 299 MVT::Other, Ops0, 4), 0); 300 cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); 301 302 SDValue Ops1[] = { FPOdd, Base, Offset1, Chain }; 303 Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl, 304 MVT::Other, Ops1, 4), 0); 305 cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1); 306 307 ReplaceUses(SDValue(N, 0), Chain); 308 return Chain.getNode(); 309 } 310 311 /// Select instructions not customized! Used for 312 /// expanded, promoted and normal instructions 313 SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { 314 unsigned Opcode = Node->getOpcode(); 315 DebugLoc dl = Node->getDebugLoc(); 316 317 // Dump information about the Node being selected 318 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); 319 320 // If we have a custom node, we already have selected! 321 if (Node->isMachineOpcode()) { 322 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 323 return NULL; 324 } 325 326 /// 327 // Instruction Selection not handled by the auto-generated 328 // tablegen selection should be handled here. 329 /// 330 switch(Opcode) { 331 default: break; 332 333 case ISD::SUBE: 334 case ISD::ADDE: { 335 SDValue InFlag = Node->getOperand(2), CmpLHS; 336 unsigned Opc = InFlag.getOpcode(); (void)Opc; 337 assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || 338 (Opc == ISD::SUBC || Opc == ISD::SUBE)) && 339 "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); 340 341 unsigned MOp; 342 if (Opcode == ISD::ADDE) { 343 CmpLHS = InFlag.getValue(0); 344 MOp = Mips::ADDu; 345 } else { 346 CmpLHS = InFlag.getOperand(0); 347 MOp = Mips::SUBu; 348 } 349 350 SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; 351 352 SDValue LHS = Node->getOperand(0); 353 SDValue RHS = Node->getOperand(1); 354 355 EVT VT = LHS.getValueType(); 356 SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, dl, VT, Ops, 2); 357 SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, 358 SDValue(Carry,0), RHS); 359 360 return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, 361 LHS, SDValue(AddCarry,0)); 362 } 363 364 /// Mul with two results 365 case ISD::SMUL_LOHI: 366 case ISD::UMUL_LOHI: { 367 SDValue Op1 = Node->getOperand(0); 368 SDValue Op2 = Node->getOperand(1); 369 370 unsigned Op; 371 Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); 372 373 SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); 374 375 SDValue InFlag = SDValue(Mul, 0); 376 SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, 377 MVT::Glue, InFlag); 378 InFlag = SDValue(Lo,1); 379 SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); 380 381 if (!SDValue(Node, 0).use_empty()) 382 ReplaceUses(SDValue(Node, 0), SDValue(Lo,0)); 383 384 if (!SDValue(Node, 1).use_empty()) 385 ReplaceUses(SDValue(Node, 1), SDValue(Hi,0)); 386 387 return NULL; 388 } 389 390 /// Special Muls 391 case ISD::MUL: 392 if (Subtarget.isMips32()) 393 break; 394 case ISD::MULHS: 395 case ISD::MULHU: { 396 SDValue MulOp1 = Node->getOperand(0); 397 SDValue MulOp2 = Node->getOperand(1); 398 399 unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); 400 SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, 401 MVT::Glue, MulOp1, MulOp2); 402 403 SDValue InFlag = SDValue(MulNode, 0); 404 405 if (Opcode == ISD::MUL) 406 return CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, InFlag); 407 else 408 return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); 409 } 410 411 // Get target GOT address. 412 case ISD::GLOBAL_OFFSET_TABLE: 413 return getGlobalBaseReg(); 414 415 case ISD::ConstantFP: { 416 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); 417 if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { 418 SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, 419 Mips::ZERO, MVT::i32); 420 SDValue Undef = SDValue( 421 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0); 422 SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero); 423 SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, 424 MVT::f64, Undef, SDValue(MTC, 0)); 425 SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, 426 MVT::f64, I0, SDValue(MTC, 0)); 427 ReplaceUses(SDValue(Node, 0), I1); 428 return I1.getNode(); 429 } 430 break; 431 } 432 433 case ISD::LOAD: 434 if (SDNode *ResNode = SelectLoadFp64(Node)) 435 return ResNode; 436 // Other cases are autogenerated. 437 break; 438 439 case ISD::STORE: 440 if (SDNode *ResNode = SelectStoreFp64(Node)) 441 return ResNode; 442 // Other cases are autogenerated. 443 break; 444 445 case MipsISD::ThreadPointer: { 446 unsigned SrcReg = Mips::HWR29; 447 unsigned DestReg = Mips::V1; 448 SDNode *Rdhwr = CurDAG->getMachineNode(Mips::RDHWR, Node->getDebugLoc(), 449 Node->getValueType(0), CurDAG->getRegister(SrcReg, MVT::i32)); 450 SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg, 451 SDValue(Rdhwr, 0)); 452 SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, MVT::i32); 453 ReplaceUses(SDValue(Node, 0), ResNode); 454 return ResNode.getNode(); 455 } 456 } 457 458 // Select the default instruction 459 SDNode *ResNode = SelectCode(Node); 460 461 DEBUG(errs() << "=> "); 462 if (ResNode == NULL || ResNode == Node) 463 DEBUG(Node->dump(CurDAG)); 464 else 465 DEBUG(ResNode->dump(CurDAG)); 466 DEBUG(errs() << "\n"); 467 return ResNode; 468 } 469 470 bool MipsDAGToDAGISel:: 471 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 472 std::vector<SDValue> &OutOps) { 473 assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 474 OutOps.push_back(Op); 475 return false; 476 } 477 478 /// createMipsISelDag - This pass converts a legalized DAG into a 479 /// MIPS-specific DAG, ready for instruction scheduling. 480 FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { 481 return new MipsDAGToDAGISel(TM); 482 } 483