1 //===-- M68kISelDAGToDAG.cpp - M68k Dag to Dag Inst Selector ----*- C++ -*-===// 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 /// \file 10 /// This file defines an instruction selector for the M68K target. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "M68k.h" 15 16 #include "M68kMachineFunction.h" 17 #include "M68kRegisterInfo.h" 18 #include "M68kTargetMachine.h" 19 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/SelectionDAGISel.h" 26 #include "llvm/CodeGen/SelectionDAGNodes.h" 27 #include "llvm/IR/CFG.h" 28 #include "llvm/IR/GlobalValue.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/IR/Intrinsics.h" 31 #include "llvm/IR/Type.h" 32 #include "llvm/Support/Alignment.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/ErrorHandling.h" 35 #include "llvm/Support/MathExtras.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include "llvm/Target/TargetMachine.h" 38 39 using namespace llvm; 40 41 #define DEBUG_TYPE "m68k-isel" 42 #define PASS_NAME "M68k DAG->DAG Pattern Instruction Selection" 43 44 namespace { 45 46 // For reference, the full order of operands for memory references is: 47 // (Operand), Displacement, Base, Index, Scale 48 struct M68kISelAddressMode { 49 enum class AddrType { 50 ARI, // Address Register Indirect 51 ARIPI, // Address Register Indirect with Postincrement 52 ARIPD, // Address Register Indirect with Postdecrement 53 ARID, // Address Register Indirect with Displacement 54 ARII, // Address Register Indirect with Index 55 PCD, // Program Counter Indirect with Displacement 56 PCI, // Program Counter Indirect with Index 57 AL, // Absolute 58 }; 59 AddrType AM; 60 61 enum class Base { RegBase, FrameIndexBase }; 62 Base BaseType; 63 64 int64_t Disp; 65 66 // This is really a union, discriminated by BaseType! 67 SDValue BaseReg; 68 int BaseFrameIndex; 69 70 SDValue IndexReg; 71 unsigned Scale; 72 73 const GlobalValue *GV; 74 const Constant *CP; 75 const BlockAddress *BlockAddr; 76 const char *ES; 77 MCSymbol *MCSym; 78 int JT; 79 Align Alignment; // CP alignment. 80 81 unsigned char SymbolFlags; // M68kII::MO_* 82 83 M68kISelAddressMode(AddrType AT) 84 : AM(AT), BaseType(Base::RegBase), Disp(0), BaseFrameIndex(0), IndexReg(), 85 Scale(1), GV(nullptr), CP(nullptr), BlockAddr(nullptr), ES(nullptr), 86 MCSym(nullptr), JT(-1), Alignment(), SymbolFlags(M68kII::MO_NO_FLAG) {} 87 88 bool hasSymbolicDisplacement() const { 89 return GV != nullptr || CP != nullptr || ES != nullptr || 90 MCSym != nullptr || JT != -1 || BlockAddr != nullptr; 91 } 92 93 bool hasBase() const { 94 return BaseType == Base::FrameIndexBase || BaseReg.getNode() != nullptr; 95 } 96 97 bool hasFrameIndex() const { return BaseType == Base::FrameIndexBase; } 98 99 bool hasBaseReg() const { 100 return BaseType == Base::RegBase && BaseReg.getNode() != nullptr; 101 } 102 103 bool hasIndexReg() const { 104 return BaseType == Base::RegBase && IndexReg.getNode() != nullptr; 105 } 106 107 /// True if address mode type supports displacement 108 bool isDispAddrType() const { 109 return AM == AddrType::ARII || AM == AddrType::PCI || 110 AM == AddrType::ARID || AM == AddrType::PCD || AM == AddrType::AL; 111 } 112 113 unsigned getDispSize() const { 114 switch (AM) { 115 default: 116 return 0; 117 case AddrType::ARII: 118 case AddrType::PCI: 119 return 8; 120 // These two in the next chip generations can hold upto 32 bit 121 case AddrType::ARID: 122 case AddrType::PCD: 123 return 16; 124 case AddrType::AL: 125 return 32; 126 } 127 } 128 129 bool hasDisp() const { return getDispSize() != 0; } 130 bool isDisp8() const { return getDispSize() == 8; } 131 bool isDisp16() const { return getDispSize() == 16; } 132 bool isDisp32() const { return getDispSize() == 32; } 133 134 /// Return true if this addressing mode is already PC-relative. 135 bool isPCRelative() const { 136 if (BaseType != Base::RegBase) 137 return false; 138 if (auto *RegNode = dyn_cast_or_null<RegisterSDNode>(BaseReg.getNode())) 139 return RegNode->getReg() == M68k::PC; 140 return false; 141 } 142 143 void setBaseReg(SDValue Reg) { 144 BaseType = Base::RegBase; 145 BaseReg = Reg; 146 } 147 148 void setIndexReg(SDValue Reg) { IndexReg = Reg; } 149 150 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 151 void dump() { 152 dbgs() << "M68kISelAddressMode " << this; 153 dbgs() << "\nDisp: " << Disp; 154 dbgs() << ", BaseReg: "; 155 if (BaseReg.getNode()) 156 BaseReg.getNode()->dump(); 157 else 158 dbgs() << "null"; 159 dbgs() << ", BaseFI: " << BaseFrameIndex; 160 dbgs() << ", IndexReg: "; 161 if (IndexReg.getNode()) { 162 IndexReg.getNode()->dump(); 163 } else { 164 dbgs() << "null"; 165 dbgs() << ", Scale: " << Scale; 166 } 167 dbgs() << '\n'; 168 } 169 #endif 170 }; 171 } // end anonymous namespace 172 173 namespace { 174 175 class M68kDAGToDAGISel : public SelectionDAGISel { 176 public: 177 static char ID; 178 179 M68kDAGToDAGISel() = delete; 180 181 explicit M68kDAGToDAGISel(M68kTargetMachine &TM) 182 : SelectionDAGISel(ID, TM), Subtarget(nullptr) {} 183 184 bool runOnMachineFunction(MachineFunction &MF) override; 185 bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const override; 186 187 private: 188 /// Keep a pointer to the M68kSubtarget around so that we can 189 /// make the right decision when generating code for different targets. 190 const M68kSubtarget *Subtarget; 191 192 // Include the pieces autogenerated from the target description. 193 #include "M68kGenDAGISel.inc" 194 195 /// getTargetMachine - Return a reference to the TargetMachine, casted 196 /// to the target-specific type. 197 const M68kTargetMachine &getTargetMachine() { 198 return static_cast<const M68kTargetMachine &>(TM); 199 } 200 201 void Select(SDNode *N) override; 202 203 // Insert instructions to initialize the global base register in the 204 // first MBB of the function. 205 // HMM... do i need this? 206 void initGlobalBaseReg(MachineFunction &MF); 207 208 bool foldOffsetIntoAddress(uint64_t Offset, M68kISelAddressMode &AM); 209 210 bool matchLoadInAddress(LoadSDNode *N, M68kISelAddressMode &AM); 211 bool matchAddress(SDValue N, M68kISelAddressMode &AM); 212 bool matchAddressBase(SDValue N, M68kISelAddressMode &AM); 213 bool matchAddressRecursively(SDValue N, M68kISelAddressMode &AM, 214 unsigned Depth); 215 bool matchADD(SDValue &N, M68kISelAddressMode &AM, unsigned Depth); 216 bool matchWrapper(SDValue N, M68kISelAddressMode &AM); 217 218 std::pair<bool, SDNode *> selectNode(SDNode *Node); 219 220 bool SelectARI(SDNode *Parent, SDValue N, SDValue &Base); 221 bool SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base); 222 bool SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base); 223 bool SelectARID(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Base); 224 bool SelectARII(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Base, 225 SDValue &Index); 226 bool SelectAL(SDNode *Parent, SDValue N, SDValue &Sym); 227 bool SelectPCD(SDNode *Parent, SDValue N, SDValue &Imm); 228 bool SelectPCI(SDNode *Parent, SDValue N, SDValue &Imm, SDValue &Index); 229 230 // If Address Mode represents Frame Index store FI in Disp and 231 // Displacement bit size in Base. These values are read symmetrically by 232 // M68kRegisterInfo::eliminateFrameIndex method 233 inline bool getFrameIndexAddress(M68kISelAddressMode &AM, const SDLoc &DL, 234 SDValue &Disp, SDValue &Base) { 235 if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) { 236 Disp = getI32Imm(AM.Disp, DL); 237 Base = CurDAG->getTargetFrameIndex( 238 AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout())); 239 return true; 240 } 241 242 return false; 243 } 244 245 // Gets a symbol plus optional displacement 246 inline bool getSymbolicDisplacement(M68kISelAddressMode &AM, const SDLoc &DL, 247 SDValue &Sym) { 248 if (AM.GV) { 249 Sym = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(), MVT::i32, AM.Disp, 250 AM.SymbolFlags); 251 return true; 252 } 253 254 if (AM.CP) { 255 Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment, 256 AM.Disp, AM.SymbolFlags); 257 return true; 258 } 259 260 if (AM.ES) { 261 assert(!AM.Disp && "Non-zero displacement is ignored with ES."); 262 Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags); 263 return true; 264 } 265 266 if (AM.MCSym) { 267 assert(!AM.Disp && "Non-zero displacement is ignored with MCSym."); 268 assert(AM.SymbolFlags == 0 && "oo"); 269 Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32); 270 return true; 271 } 272 273 if (AM.JT != -1) { 274 assert(!AM.Disp && "Non-zero displacement is ignored with JT."); 275 Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags); 276 return true; 277 } 278 279 if (AM.BlockAddr) { 280 Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp, 281 AM.SymbolFlags); 282 return true; 283 } 284 285 return false; 286 } 287 288 /// Return a target constant with the specified value of type i8. 289 inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) { 290 return CurDAG->getTargetConstant(Imm, DL, MVT::i8); 291 } 292 293 /// Return a target constant with the specified value of type i8. 294 inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) { 295 return CurDAG->getTargetConstant(Imm, DL, MVT::i16); 296 } 297 298 /// Return a target constant with the specified value, of type i32. 299 inline SDValue getI32Imm(int64_t Imm, const SDLoc &DL) { 300 return CurDAG->getTargetConstant(Imm, DL, MVT::i32); 301 } 302 303 /// Return a reference to the TargetInstrInfo, casted to the target-specific 304 /// type. 305 const M68kInstrInfo *getInstrInfo() const { 306 return Subtarget->getInstrInfo(); 307 } 308 309 /// Return an SDNode that returns the value of the global base register. 310 /// Output instructions required to initialize the global base register, 311 /// if necessary. 312 SDNode *getGlobalBaseReg(); 313 }; 314 315 char M68kDAGToDAGISel::ID; 316 317 } // namespace 318 319 INITIALIZE_PASS(M68kDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false) 320 321 bool M68kDAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, 322 SDNode *Root) const { 323 if (OptLevel == CodeGenOpt::None) 324 return false; 325 326 if (U == Root) { 327 switch (U->getOpcode()) { 328 default: 329 return true; 330 case M68kISD::SUB: 331 case ISD::SUB: 332 // Prefer NEG instruction when zero subtracts a value. 333 // e.g. 334 // move.l #0, %d0 335 // sub.l (4,%sp), %d0 336 // vs. 337 // move.l (4,%sp), %d0 338 // neg.l %d0 339 if (llvm::isNullConstant(U->getOperand(0))) 340 return false; 341 break; 342 } 343 } 344 345 return true; 346 } 347 348 bool M68kDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 349 Subtarget = &MF.getSubtarget<M68kSubtarget>(); 350 return SelectionDAGISel::runOnMachineFunction(MF); 351 } 352 353 /// This pass converts a legalized DAG into a M68k-specific DAG, 354 /// ready for instruction scheduling. 355 FunctionPass *llvm::createM68kISelDag(M68kTargetMachine &TM) { 356 return new M68kDAGToDAGISel(TM); 357 } 358 359 static bool doesDispFitFI(M68kISelAddressMode &AM) { 360 if (!AM.isDispAddrType()) 361 return false; 362 // -1 to make sure that resolved FI will fit into Disp field 363 return isIntN(AM.getDispSize() - 1, AM.Disp); 364 } 365 366 static bool doesDispFit(M68kISelAddressMode &AM, int64_t Val) { 367 if (!AM.isDispAddrType()) 368 return false; 369 return isIntN(AM.getDispSize(), Val); 370 } 371 372 /// Return an SDNode that returns the value of the global base register. 373 /// Output instructions required to initialize the global base register, 374 /// if necessary. 375 SDNode *M68kDAGToDAGISel::getGlobalBaseReg() { 376 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); 377 auto &DL = MF->getDataLayout(); 378 return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(DL)).getNode(); 379 } 380 381 bool M68kDAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset, 382 M68kISelAddressMode &AM) { 383 // Cannot combine ExternalSymbol displacements with integer offsets. 384 if (Offset != 0 && (AM.ES || AM.MCSym)) 385 return false; 386 387 int64_t Val = AM.Disp + Offset; 388 389 if (doesDispFit(AM, Val)) { 390 AM.Disp = Val; 391 return true; 392 } 393 394 return false; 395 } 396 397 //===----------------------------------------------------------------------===// 398 // Matchers 399 //===----------------------------------------------------------------------===// 400 401 /// Helper for MatchAddress. Add the specified node to the 402 /// specified addressing mode without any further recursion. 403 bool M68kDAGToDAGISel::matchAddressBase(SDValue N, M68kISelAddressMode &AM) { 404 // Is the base register already occupied? 405 if (AM.hasBase()) { 406 // If so, check to see if the scale index register is set. 407 if (!AM.hasIndexReg()) { 408 AM.IndexReg = N; 409 AM.Scale = 1; 410 return true; 411 } 412 413 // Otherwise, we cannot select it. 414 return false; 415 } 416 417 // Default, generate it as a register. 418 AM.BaseType = M68kISelAddressMode::Base::RegBase; 419 AM.BaseReg = N; 420 return true; 421 } 422 423 /// TODO Add TLS support 424 bool M68kDAGToDAGISel::matchLoadInAddress(LoadSDNode *N, 425 M68kISelAddressMode &AM) { 426 return false; 427 } 428 429 bool M68kDAGToDAGISel::matchAddressRecursively(SDValue N, 430 M68kISelAddressMode &AM, 431 unsigned Depth) { 432 SDLoc DL(N); 433 434 // Limit recursion. 435 if (Depth > 5) 436 return matchAddressBase(N, AM); 437 438 // If this is already a %PC relative address, we can only merge immediates 439 // into it. Instead of handling this in every case, we handle it here. 440 // PC relative addressing: %PC + 16-bit displacement! 441 if (AM.isPCRelative()) { 442 // FIXME JumpTable and ExternalSymbol address currently don't like 443 // displacements. It isn't very important, but should be fixed for 444 // consistency. 445 446 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N)) 447 if (foldOffsetIntoAddress(Cst->getSExtValue(), AM)) 448 return true; 449 return false; 450 } 451 452 switch (N.getOpcode()) { 453 default: 454 break; 455 456 case ISD::Constant: { 457 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); 458 if (foldOffsetIntoAddress(Val, AM)) 459 return true; 460 break; 461 } 462 463 case M68kISD::Wrapper: 464 case M68kISD::WrapperPC: 465 if (matchWrapper(N, AM)) 466 return true; 467 break; 468 469 case ISD::LOAD: 470 if (matchLoadInAddress(cast<LoadSDNode>(N), AM)) 471 return true; 472 break; 473 474 case ISD::OR: 475 // We want to look through a transform in InstCombine and DAGCombiner that 476 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 477 // Example: (or (and x, 1), (shl y, 3)) --> (add (and x, 1), (shl y, 3)) 478 // An 'lea' can then be used to match the shift (multiply) and add: 479 // and $1, %esi 480 // lea (%rsi, %rdi, 8), %rax 481 if (CurDAG->haveNoCommonBitsSet(N.getOperand(0), N.getOperand(1)) && 482 matchADD(N, AM, Depth)) 483 return true; 484 break; 485 486 case ISD::ADD: 487 if (matchADD(N, AM, Depth)) 488 return true; 489 break; 490 491 case ISD::FrameIndex: 492 if (AM.isDispAddrType() && 493 AM.BaseType == M68kISelAddressMode::Base::RegBase && 494 AM.BaseReg.getNode() == nullptr && doesDispFitFI(AM)) { 495 AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase; 496 AM.BaseFrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); 497 return true; 498 } 499 break; 500 } 501 502 return matchAddressBase(N, AM); 503 } 504 505 /// Add the specified node to the specified addressing mode, returning true if 506 /// it cannot be done. This just pattern matches for the addressing mode. 507 bool M68kDAGToDAGISel::matchAddress(SDValue N, M68kISelAddressMode &AM) { 508 // TODO: Post-processing: Convert lea(,%reg,2) to lea(%reg,%reg), which has 509 // a smaller encoding and avoids a scaled-index. 510 // And make sure it is an indexed mode 511 512 // TODO: Post-processing: Convert foo to foo(%pc), even in non-PIC mode, 513 // because it has a smaller encoding. 514 // Make sure this must be done only if PC* modes are currently being matched 515 return matchAddressRecursively(N, AM, 0); 516 } 517 518 bool M68kDAGToDAGISel::matchADD(SDValue &N, M68kISelAddressMode &AM, 519 unsigned Depth) { 520 // Add an artificial use to this node so that we can keep track of 521 // it if it gets CSE'd with a different node. 522 HandleSDNode Handle(N); 523 524 M68kISelAddressMode Backup = AM; 525 if (matchAddressRecursively(N.getOperand(0), AM, Depth + 1) && 526 matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1)) { 527 return true; 528 } 529 AM = Backup; 530 531 // Try again after commuting the operands. 532 if (matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1) && 533 matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth + 1)) { 534 return true; 535 } 536 AM = Backup; 537 538 // If we couldn't fold both operands into the address at the same time, 539 // see if we can just put each operand into a register and fold at least 540 // the add. 541 if (!AM.hasBase() && !AM.hasIndexReg()) { 542 N = Handle.getValue(); 543 AM.BaseReg = N.getOperand(0); 544 AM.IndexReg = N.getOperand(1); 545 AM.Scale = 1; 546 return true; 547 } 548 549 N = Handle.getValue(); 550 return false; 551 } 552 553 /// Try to match M68kISD::Wrapper and M68kISD::WrapperPC nodes into an 554 /// addressing mode. These wrap things that will resolve down into a symbol 555 /// reference. If no match is possible, this returns true, otherwise it returns 556 /// false. 557 bool M68kDAGToDAGISel::matchWrapper(SDValue N, M68kISelAddressMode &AM) { 558 // If the addressing mode already has a symbol as the displacement, we can 559 // never match another symbol. 560 if (AM.hasSymbolicDisplacement()) 561 return false; 562 563 SDValue N0 = N.getOperand(0); 564 565 if (N.getOpcode() == M68kISD::WrapperPC) { 566 567 // If cannot match here just restore the old version 568 M68kISelAddressMode Backup = AM; 569 570 if (AM.hasBase()) { 571 return false; 572 } 573 574 if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) { 575 AM.GV = G->getGlobal(); 576 AM.SymbolFlags = G->getTargetFlags(); 577 if (!foldOffsetIntoAddress(G->getOffset(), AM)) { 578 AM = Backup; 579 return false; 580 } 581 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 582 AM.CP = CP->getConstVal(); 583 AM.Alignment = CP->getAlign(); 584 AM.SymbolFlags = CP->getTargetFlags(); 585 if (!foldOffsetIntoAddress(CP->getOffset(), AM)) { 586 AM = Backup; 587 return false; 588 } 589 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 590 AM.ES = S->getSymbol(); 591 AM.SymbolFlags = S->getTargetFlags(); 592 } else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) { 593 AM.MCSym = S->getMCSymbol(); 594 } else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) { 595 AM.JT = J->getIndex(); 596 AM.SymbolFlags = J->getTargetFlags(); 597 } else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) { 598 AM.BlockAddr = BA->getBlockAddress(); 599 AM.SymbolFlags = BA->getTargetFlags(); 600 if (!foldOffsetIntoAddress(BA->getOffset(), AM)) { 601 AM = Backup; 602 return false; 603 } 604 } else 605 llvm_unreachable("Unhandled symbol reference node."); 606 607 AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32)); 608 return true; 609 } 610 611 // This wrapper requires 32bit disp/imm field for Medium CM 612 if (!AM.isDisp32()) { 613 return false; 614 } 615 616 if (N.getOpcode() == M68kISD::Wrapper) { 617 if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) { 618 AM.GV = G->getGlobal(); 619 AM.Disp += G->getOffset(); 620 AM.SymbolFlags = G->getTargetFlags(); 621 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 622 AM.CP = CP->getConstVal(); 623 AM.Alignment = CP->getAlign(); 624 AM.Disp += CP->getOffset(); 625 AM.SymbolFlags = CP->getTargetFlags(); 626 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 627 AM.ES = S->getSymbol(); 628 AM.SymbolFlags = S->getTargetFlags(); 629 } else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) { 630 AM.MCSym = S->getMCSymbol(); 631 } else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) { 632 AM.JT = J->getIndex(); 633 AM.SymbolFlags = J->getTargetFlags(); 634 } else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) { 635 AM.BlockAddr = BA->getBlockAddress(); 636 AM.Disp += BA->getOffset(); 637 AM.SymbolFlags = BA->getTargetFlags(); 638 } else 639 llvm_unreachable("Unhandled symbol reference node."); 640 return true; 641 } 642 643 return false; 644 } 645 646 //===----------------------------------------------------------------------===// 647 // Selectors 648 //===----------------------------------------------------------------------===// 649 650 void M68kDAGToDAGISel::Select(SDNode *Node) { 651 unsigned Opcode = Node->getOpcode(); 652 SDLoc DL(Node); 653 654 LLVM_DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n'); 655 656 if (Node->isMachineOpcode()) { 657 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n'); 658 Node->setNodeId(-1); 659 return; // Already selected. 660 } 661 662 switch (Opcode) { 663 default: 664 break; 665 666 case M68kISD::GLOBAL_BASE_REG: 667 ReplaceNode(Node, getGlobalBaseReg()); 668 return; 669 } 670 671 SelectCode(Node); 672 } 673 674 bool M68kDAGToDAGISel::SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base) { 675 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPI: "); 676 LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n"); 677 return false; 678 } 679 680 bool M68kDAGToDAGISel::SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base) { 681 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPD: "); 682 LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n"); 683 return false; 684 } 685 686 bool M68kDAGToDAGISel::SelectARID(SDNode *Parent, SDValue N, SDValue &Disp, 687 SDValue &Base) { 688 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARID: "); 689 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID); 690 691 if (!matchAddress(N, AM)) 692 return false; 693 694 if (AM.isPCRelative()) { 695 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 696 return false; 697 } 698 699 // If this is a frame index, grab it 700 if (getFrameIndexAddress(AM, SDLoc(N), Disp, Base)) { 701 LLVM_DEBUG(dbgs() << "SUCCESS matched FI\n"); 702 return true; 703 } 704 705 if (AM.hasIndexReg()) { 706 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 707 return false; 708 } 709 710 if (!AM.hasBaseReg()) { 711 LLVM_DEBUG(dbgs() << "REJECT: No Base reg\n"); 712 return false; 713 } 714 715 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 716 assert(!AM.Disp && "Should not be any displacement"); 717 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 718 return true; 719 } 720 721 // Give a chance to AddrType::ARI 722 if (AM.Disp == 0) { 723 LLVM_DEBUG(dbgs() << "REJECT: No displacement\n"); 724 return false; 725 } 726 727 Base = AM.BaseReg; 728 Disp = getI16Imm(AM.Disp, SDLoc(N)); 729 730 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 731 return true; 732 } 733 734 static bool isAddressBase(const SDValue &N) { 735 switch (N.getOpcode()) { 736 case ISD::ADD: 737 case ISD::ADDC: 738 return llvm::any_of(N.getNode()->ops(), 739 [](const SDUse &U) { return isAddressBase(U.get()); }); 740 case M68kISD::Wrapper: 741 case M68kISD::WrapperPC: 742 case M68kISD::GLOBAL_BASE_REG: 743 return true; 744 default: 745 return false; 746 } 747 } 748 749 bool M68kDAGToDAGISel::SelectARII(SDNode *Parent, SDValue N, SDValue &Disp, 750 SDValue &Base, SDValue &Index) { 751 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII); 752 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARII: "); 753 754 if (!matchAddress(N, AM)) 755 return false; 756 757 if (AM.isPCRelative()) { 758 LLVM_DEBUG(dbgs() << "REJECT: PC relative\n"); 759 return false; 760 } 761 762 if (!AM.hasIndexReg()) { 763 LLVM_DEBUG(dbgs() << "REJECT: No Index\n"); 764 return false; 765 } 766 767 if (!AM.hasBaseReg()) { 768 LLVM_DEBUG(dbgs() << "REJECT: No Base\n"); 769 return false; 770 } 771 772 if (!isAddressBase(AM.BaseReg) && isAddressBase(AM.IndexReg)) { 773 Base = AM.IndexReg; 774 Index = AM.BaseReg; 775 } else { 776 Base = AM.BaseReg; 777 Index = AM.IndexReg; 778 } 779 780 if (AM.hasSymbolicDisplacement()) { 781 LLVM_DEBUG(dbgs() << "REJECT, Cannot match symbolic displacement\n"); 782 return false; 783 } 784 785 // The idea here is that we want to use AddrType::ARII without displacement 786 // only if necessary like memory operations, otherwise this must be lowered 787 // into addition 788 if (AM.Disp == 0 && (!Parent || (Parent->getOpcode() != ISD::LOAD && 789 Parent->getOpcode() != ISD::STORE))) { 790 LLVM_DEBUG(dbgs() << "REJECT: Displacement is Zero\n"); 791 return false; 792 } 793 794 Disp = getI8Imm(AM.Disp, SDLoc(N)); 795 796 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 797 return true; 798 } 799 800 bool M68kDAGToDAGISel::SelectAL(SDNode *Parent, SDValue N, SDValue &Sym) { 801 LLVM_DEBUG(dbgs() << "Selecting AddrType::AL: "); 802 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL); 803 804 if (!matchAddress(N, AM)) { 805 LLVM_DEBUG(dbgs() << "REJECT: Match failed\n"); 806 return false; 807 } 808 809 if (AM.isPCRelative()) { 810 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 811 return false; 812 } 813 814 if (AM.hasBase()) { 815 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Base\n"); 816 return false; 817 } 818 819 if (AM.hasIndexReg()) { 820 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 821 return false; 822 } 823 824 if (getSymbolicDisplacement(AM, SDLoc(N), Sym)) { 825 LLVM_DEBUG(dbgs() << "SUCCESS: Matched symbol\n"); 826 return true; 827 } 828 829 if (AM.Disp) { 830 Sym = getI32Imm(AM.Disp, SDLoc(N)); 831 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 832 return true; 833 } 834 835 LLVM_DEBUG(dbgs() << "REJECT: Not Symbol or Disp\n"); 836 return false; 837 ; 838 } 839 840 bool M68kDAGToDAGISel::SelectPCD(SDNode *Parent, SDValue N, SDValue &Disp) { 841 LLVM_DEBUG(dbgs() << "Selecting AddrType::PCD: "); 842 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD); 843 844 if (!matchAddress(N, AM)) 845 return false; 846 847 if (!AM.isPCRelative()) { 848 LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n"); 849 return false; 850 } 851 852 if (AM.hasIndexReg()) { 853 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 854 return false; 855 } 856 857 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 858 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 859 return true; 860 } 861 862 Disp = getI16Imm(AM.Disp, SDLoc(N)); 863 864 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 865 return true; 866 } 867 868 bool M68kDAGToDAGISel::SelectPCI(SDNode *Parent, SDValue N, SDValue &Disp, 869 SDValue &Index) { 870 LLVM_DEBUG(dbgs() << "Selecting AddrType::PCI: "); 871 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI); 872 873 if (!matchAddress(N, AM)) 874 return false; 875 876 if (!AM.isPCRelative()) { 877 LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n"); 878 return false; 879 } 880 881 if (!AM.hasIndexReg()) { 882 LLVM_DEBUG(dbgs() << "REJECT: No Index\n"); 883 return false; 884 } 885 886 Index = AM.IndexReg; 887 888 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 889 assert(!AM.Disp && "Should not be any displacement"); 890 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 891 return true; 892 } 893 894 Disp = getI8Imm(AM.Disp, SDLoc(N)); 895 896 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 897 return true; 898 } 899 900 bool M68kDAGToDAGISel::SelectARI(SDNode *Parent, SDValue N, SDValue &Base) { 901 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARI: "); 902 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI); 903 904 if (!matchAddress(N, AM)) { 905 LLVM_DEBUG(dbgs() << "REJECT: Match failed\n"); 906 return false; 907 } 908 909 if (AM.isPCRelative()) { 910 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 911 return false; 912 } 913 914 // AddrType::ARI does not use these 915 if (AM.hasIndexReg() || AM.Disp != 0) { 916 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index or Disp\n"); 917 return false; 918 } 919 920 // Must be matched by AddrType::AL 921 if (AM.hasSymbolicDisplacement()) { 922 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Symbolic Disp\n"); 923 return false; 924 } 925 926 if (AM.hasBaseReg()) { 927 Base = AM.BaseReg; 928 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 929 return true; 930 } 931 932 return false; 933 } 934