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 bool SelectInlineAsmMemoryOperand(const SDValue &Op, 231 InlineAsm::ConstraintCode ConstraintID, 232 std::vector<SDValue> &OutOps) override; 233 234 // If Address Mode represents Frame Index store FI in Disp and 235 // Displacement bit size in Base. These values are read symmetrically by 236 // M68kRegisterInfo::eliminateFrameIndex method 237 inline bool getFrameIndexAddress(M68kISelAddressMode &AM, const SDLoc &DL, 238 SDValue &Disp, SDValue &Base) { 239 if (AM.BaseType == M68kISelAddressMode::Base::FrameIndexBase) { 240 Disp = getI32Imm(AM.Disp, DL); 241 Base = CurDAG->getTargetFrameIndex( 242 AM.BaseFrameIndex, TLI->getPointerTy(CurDAG->getDataLayout())); 243 return true; 244 } 245 246 return false; 247 } 248 249 // Gets a symbol plus optional displacement 250 inline bool getSymbolicDisplacement(M68kISelAddressMode &AM, const SDLoc &DL, 251 SDValue &Sym) { 252 if (AM.GV) { 253 Sym = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(), MVT::i32, AM.Disp, 254 AM.SymbolFlags); 255 return true; 256 } 257 258 if (AM.CP) { 259 Sym = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment, 260 AM.Disp, AM.SymbolFlags); 261 return true; 262 } 263 264 if (AM.ES) { 265 assert(!AM.Disp && "Non-zero displacement is ignored with ES."); 266 Sym = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags); 267 return true; 268 } 269 270 if (AM.MCSym) { 271 assert(!AM.Disp && "Non-zero displacement is ignored with MCSym."); 272 assert(AM.SymbolFlags == 0 && "oo"); 273 Sym = CurDAG->getMCSymbol(AM.MCSym, MVT::i32); 274 return true; 275 } 276 277 if (AM.JT != -1) { 278 assert(!AM.Disp && "Non-zero displacement is ignored with JT."); 279 Sym = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags); 280 return true; 281 } 282 283 if (AM.BlockAddr) { 284 Sym = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp, 285 AM.SymbolFlags); 286 return true; 287 } 288 289 return false; 290 } 291 292 /// Return a target constant with the specified value of type i8. 293 inline SDValue getI8Imm(int64_t Imm, const SDLoc &DL) { 294 return CurDAG->getTargetConstant(Imm, DL, MVT::i8); 295 } 296 297 /// Return a target constant with the specified value of type i8. 298 inline SDValue getI16Imm(int64_t Imm, const SDLoc &DL) { 299 return CurDAG->getTargetConstant(Imm, DL, MVT::i16); 300 } 301 302 /// Return a target constant with the specified value, of type i32. 303 inline SDValue getI32Imm(int64_t Imm, const SDLoc &DL) { 304 return CurDAG->getTargetConstant(Imm, DL, MVT::i32); 305 } 306 307 /// Return a reference to the TargetInstrInfo, casted to the target-specific 308 /// type. 309 const M68kInstrInfo *getInstrInfo() const { 310 return Subtarget->getInstrInfo(); 311 } 312 313 /// Return an SDNode that returns the value of the global base register. 314 /// Output instructions required to initialize the global base register, 315 /// if necessary. 316 SDNode *getGlobalBaseReg(); 317 }; 318 319 char M68kDAGToDAGISel::ID; 320 321 } // namespace 322 323 INITIALIZE_PASS(M68kDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false) 324 325 bool M68kDAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, 326 SDNode *Root) const { 327 if (OptLevel == CodeGenOptLevel::None) 328 return false; 329 330 if (U == Root) { 331 switch (U->getOpcode()) { 332 default: 333 return true; 334 case M68kISD::SUB: 335 case ISD::SUB: 336 // Prefer NEG instruction when zero subtracts a value. 337 // e.g. 338 // move.l #0, %d0 339 // sub.l (4,%sp), %d0 340 // vs. 341 // move.l (4,%sp), %d0 342 // neg.l %d0 343 if (llvm::isNullConstant(U->getOperand(0))) 344 return false; 345 break; 346 } 347 } 348 349 return true; 350 } 351 352 bool M68kDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 353 Subtarget = &MF.getSubtarget<M68kSubtarget>(); 354 return SelectionDAGISel::runOnMachineFunction(MF); 355 } 356 357 /// This pass converts a legalized DAG into a M68k-specific DAG, 358 /// ready for instruction scheduling. 359 FunctionPass *llvm::createM68kISelDag(M68kTargetMachine &TM) { 360 return new M68kDAGToDAGISel(TM); 361 } 362 363 static bool doesDispFitFI(M68kISelAddressMode &AM) { 364 if (!AM.isDispAddrType()) 365 return false; 366 // -1 to make sure that resolved FI will fit into Disp field 367 return isIntN(AM.getDispSize() - 1, AM.Disp); 368 } 369 370 static bool doesDispFit(M68kISelAddressMode &AM, int64_t Val) { 371 if (!AM.isDispAddrType()) 372 return false; 373 return isIntN(AM.getDispSize(), Val); 374 } 375 376 /// Return an SDNode that returns the value of the global base register. 377 /// Output instructions required to initialize the global base register, 378 /// if necessary. 379 SDNode *M68kDAGToDAGISel::getGlobalBaseReg() { 380 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); 381 auto &DL = MF->getDataLayout(); 382 return CurDAG->getRegister(GlobalBaseReg, TLI->getPointerTy(DL)).getNode(); 383 } 384 385 bool M68kDAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset, 386 M68kISelAddressMode &AM) { 387 // Cannot combine ExternalSymbol displacements with integer offsets. 388 if (Offset != 0 && (AM.ES || AM.MCSym)) 389 return false; 390 391 int64_t Val = AM.Disp + Offset; 392 393 if (doesDispFit(AM, Val)) { 394 AM.Disp = Val; 395 return true; 396 } 397 398 return false; 399 } 400 401 //===----------------------------------------------------------------------===// 402 // Matchers 403 //===----------------------------------------------------------------------===// 404 405 /// Helper for MatchAddress. Add the specified node to the 406 /// specified addressing mode without any further recursion. 407 bool M68kDAGToDAGISel::matchAddressBase(SDValue N, M68kISelAddressMode &AM) { 408 // Is the base register already occupied? 409 if (AM.hasBase()) { 410 // If so, check to see if the scale index register is set. 411 if (!AM.hasIndexReg()) { 412 AM.IndexReg = N; 413 AM.Scale = 1; 414 return true; 415 } 416 417 // Otherwise, we cannot select it. 418 return false; 419 } 420 421 // Default, generate it as a register. 422 AM.BaseType = M68kISelAddressMode::Base::RegBase; 423 AM.BaseReg = N; 424 return true; 425 } 426 427 /// TODO Add TLS support 428 bool M68kDAGToDAGISel::matchLoadInAddress(LoadSDNode *N, 429 M68kISelAddressMode &AM) { 430 return false; 431 } 432 433 bool M68kDAGToDAGISel::matchAddressRecursively(SDValue N, 434 M68kISelAddressMode &AM, 435 unsigned Depth) { 436 SDLoc DL(N); 437 438 // Limit recursion. 439 if (Depth > 5) 440 return matchAddressBase(N, AM); 441 442 // If this is already a %PC relative address, we can only merge immediates 443 // into it. Instead of handling this in every case, we handle it here. 444 // PC relative addressing: %PC + 16-bit displacement! 445 if (AM.isPCRelative()) { 446 // FIXME JumpTable and ExternalSymbol address currently don't like 447 // displacements. It isn't very important, but should be fixed for 448 // consistency. 449 450 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N)) 451 if (foldOffsetIntoAddress(Cst->getSExtValue(), AM)) 452 return true; 453 return false; 454 } 455 456 switch (N.getOpcode()) { 457 default: 458 break; 459 460 case ISD::Constant: { 461 uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); 462 if (foldOffsetIntoAddress(Val, AM)) 463 return true; 464 break; 465 } 466 467 case M68kISD::Wrapper: 468 case M68kISD::WrapperPC: 469 if (matchWrapper(N, AM)) 470 return true; 471 break; 472 473 case ISD::LOAD: 474 if (matchLoadInAddress(cast<LoadSDNode>(N), AM)) 475 return true; 476 break; 477 478 case ISD::OR: 479 // We want to look through a transform in InstCombine and DAGCombiner that 480 // turns 'add' into 'or', so we can treat this 'or' exactly like an 'add'. 481 // Example: (or (and x, 1), (shl y, 3)) --> (add (and x, 1), (shl y, 3)) 482 // An 'lea' can then be used to match the shift (multiply) and add: 483 // and $1, %esi 484 // lea (%rsi, %rdi, 8), %rax 485 if (CurDAG->haveNoCommonBitsSet(N.getOperand(0), N.getOperand(1)) && 486 matchADD(N, AM, Depth)) 487 return true; 488 break; 489 490 case ISD::ADD: 491 if (matchADD(N, AM, Depth)) 492 return true; 493 break; 494 495 case ISD::FrameIndex: 496 if (AM.isDispAddrType() && 497 AM.BaseType == M68kISelAddressMode::Base::RegBase && 498 AM.BaseReg.getNode() == nullptr && doesDispFitFI(AM)) { 499 AM.BaseType = M68kISelAddressMode::Base::FrameIndexBase; 500 AM.BaseFrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); 501 return true; 502 } 503 break; 504 505 case ISD::TargetGlobalTLSAddress: { 506 GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N); 507 AM.GV = GA->getGlobal(); 508 AM.SymbolFlags = GA->getTargetFlags(); 509 return true; 510 } 511 } 512 513 return matchAddressBase(N, AM); 514 } 515 516 /// Add the specified node to the specified addressing mode, returning true if 517 /// it cannot be done. This just pattern matches for the addressing mode. 518 bool M68kDAGToDAGISel::matchAddress(SDValue N, M68kISelAddressMode &AM) { 519 // TODO: Post-processing: Convert lea(,%reg,2) to lea(%reg,%reg), which has 520 // a smaller encoding and avoids a scaled-index. 521 // And make sure it is an indexed mode 522 523 // TODO: Post-processing: Convert foo to foo(%pc), even in non-PIC mode, 524 // because it has a smaller encoding. 525 // Make sure this must be done only if PC* modes are currently being matched 526 return matchAddressRecursively(N, AM, 0); 527 } 528 529 bool M68kDAGToDAGISel::matchADD(SDValue &N, M68kISelAddressMode &AM, 530 unsigned Depth) { 531 // Add an artificial use to this node so that we can keep track of 532 // it if it gets CSE'd with a different node. 533 HandleSDNode Handle(N); 534 535 M68kISelAddressMode Backup = AM; 536 if (matchAddressRecursively(N.getOperand(0), AM, Depth + 1) && 537 matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1)) { 538 return true; 539 } 540 AM = Backup; 541 542 // Try again after commuting the operands. 543 if (matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1) && 544 matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth + 1)) { 545 return true; 546 } 547 AM = Backup; 548 549 // If we couldn't fold both operands into the address at the same time, 550 // see if we can just put each operand into a register and fold at least 551 // the add. 552 if (!AM.hasBase() && !AM.hasIndexReg()) { 553 N = Handle.getValue(); 554 AM.BaseReg = N.getOperand(0); 555 AM.IndexReg = N.getOperand(1); 556 AM.Scale = 1; 557 return true; 558 } 559 560 N = Handle.getValue(); 561 return false; 562 } 563 564 /// Try to match M68kISD::Wrapper and M68kISD::WrapperPC nodes into an 565 /// addressing mode. These wrap things that will resolve down into a symbol 566 /// reference. If no match is possible, this returns true, otherwise it returns 567 /// false. 568 bool M68kDAGToDAGISel::matchWrapper(SDValue N, M68kISelAddressMode &AM) { 569 // If the addressing mode already has a symbol as the displacement, we can 570 // never match another symbol. 571 if (AM.hasSymbolicDisplacement()) 572 return false; 573 574 SDValue N0 = N.getOperand(0); 575 576 if (N.getOpcode() == M68kISD::WrapperPC) { 577 578 // If cannot match here just restore the old version 579 M68kISelAddressMode Backup = AM; 580 581 if (AM.hasBase()) { 582 return false; 583 } 584 585 if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) { 586 AM.GV = G->getGlobal(); 587 AM.SymbolFlags = G->getTargetFlags(); 588 if (!foldOffsetIntoAddress(G->getOffset(), AM)) { 589 AM = Backup; 590 return false; 591 } 592 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 593 AM.CP = CP->getConstVal(); 594 AM.Alignment = CP->getAlign(); 595 AM.SymbolFlags = CP->getTargetFlags(); 596 if (!foldOffsetIntoAddress(CP->getOffset(), AM)) { 597 AM = Backup; 598 return false; 599 } 600 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 601 AM.ES = S->getSymbol(); 602 AM.SymbolFlags = S->getTargetFlags(); 603 } else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) { 604 AM.MCSym = S->getMCSymbol(); 605 } else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) { 606 AM.JT = J->getIndex(); 607 AM.SymbolFlags = J->getTargetFlags(); 608 } else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) { 609 AM.BlockAddr = BA->getBlockAddress(); 610 AM.SymbolFlags = BA->getTargetFlags(); 611 if (!foldOffsetIntoAddress(BA->getOffset(), AM)) { 612 AM = Backup; 613 return false; 614 } 615 } else 616 llvm_unreachable("Unhandled symbol reference node."); 617 618 AM.setBaseReg(CurDAG->getRegister(M68k::PC, MVT::i32)); 619 return true; 620 } 621 622 // This wrapper requires 32bit disp/imm field for Medium CM 623 if (!AM.isDisp32()) { 624 return false; 625 } 626 627 if (N.getOpcode() == M68kISD::Wrapper) { 628 if (auto *G = dyn_cast<GlobalAddressSDNode>(N0)) { 629 AM.GV = G->getGlobal(); 630 AM.Disp += G->getOffset(); 631 AM.SymbolFlags = G->getTargetFlags(); 632 } else if (auto *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 633 AM.CP = CP->getConstVal(); 634 AM.Alignment = CP->getAlign(); 635 AM.Disp += CP->getOffset(); 636 AM.SymbolFlags = CP->getTargetFlags(); 637 } else if (auto *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 638 AM.ES = S->getSymbol(); 639 AM.SymbolFlags = S->getTargetFlags(); 640 } else if (auto *S = dyn_cast<MCSymbolSDNode>(N0)) { 641 AM.MCSym = S->getMCSymbol(); 642 } else if (auto *J = dyn_cast<JumpTableSDNode>(N0)) { 643 AM.JT = J->getIndex(); 644 AM.SymbolFlags = J->getTargetFlags(); 645 } else if (auto *BA = dyn_cast<BlockAddressSDNode>(N0)) { 646 AM.BlockAddr = BA->getBlockAddress(); 647 AM.Disp += BA->getOffset(); 648 AM.SymbolFlags = BA->getTargetFlags(); 649 } else 650 llvm_unreachable("Unhandled symbol reference node."); 651 return true; 652 } 653 654 return false; 655 } 656 657 //===----------------------------------------------------------------------===// 658 // Selectors 659 //===----------------------------------------------------------------------===// 660 661 void M68kDAGToDAGISel::Select(SDNode *Node) { 662 unsigned Opcode = Node->getOpcode(); 663 SDLoc DL(Node); 664 665 LLVM_DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n'); 666 667 if (Node->isMachineOpcode()) { 668 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n'); 669 Node->setNodeId(-1); 670 return; // Already selected. 671 } 672 673 switch (Opcode) { 674 default: 675 break; 676 677 case ISD::GLOBAL_OFFSET_TABLE: { 678 SDValue GOT = CurDAG->getTargetExternalSymbol( 679 "_GLOBAL_OFFSET_TABLE_", MVT::i32, M68kII::MO_GOTPCREL); 680 MachineSDNode *Res = 681 CurDAG->getMachineNode(M68k::LEA32q, DL, MVT::i32, GOT); 682 ReplaceNode(Node, Res); 683 return; 684 } 685 686 case M68kISD::GLOBAL_BASE_REG: 687 ReplaceNode(Node, getGlobalBaseReg()); 688 return; 689 } 690 691 SelectCode(Node); 692 } 693 694 bool M68kDAGToDAGISel::SelectARIPI(SDNode *Parent, SDValue N, SDValue &Base) { 695 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPI: "); 696 LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n"); 697 return false; 698 } 699 700 bool M68kDAGToDAGISel::SelectARIPD(SDNode *Parent, SDValue N, SDValue &Base) { 701 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARIPD: "); 702 LLVM_DEBUG(dbgs() << "NOT IMPLEMENTED\n"); 703 return false; 704 } 705 706 bool M68kDAGToDAGISel::SelectARID(SDNode *Parent, SDValue N, SDValue &Disp, 707 SDValue &Base) { 708 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARID: "); 709 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARID); 710 711 if (!matchAddress(N, AM)) 712 return false; 713 714 if (AM.isPCRelative()) { 715 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 716 return false; 717 } 718 719 // If this is a frame index, grab it 720 if (getFrameIndexAddress(AM, SDLoc(N), Disp, Base)) { 721 LLVM_DEBUG(dbgs() << "SUCCESS matched FI\n"); 722 return true; 723 } 724 725 if (AM.hasIndexReg()) { 726 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 727 return false; 728 } 729 730 if (!AM.hasBaseReg()) { 731 LLVM_DEBUG(dbgs() << "REJECT: No Base reg\n"); 732 return false; 733 } 734 735 Base = AM.BaseReg; 736 737 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 738 assert(!AM.Disp && "Should not be any displacement"); 739 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 740 return true; 741 } 742 743 // Give a chance to AddrType::ARI 744 if (AM.Disp == 0) { 745 LLVM_DEBUG(dbgs() << "REJECT: No displacement\n"); 746 return false; 747 } 748 749 Disp = getI16Imm(AM.Disp, SDLoc(N)); 750 751 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 752 return true; 753 } 754 755 static bool isAddressBase(const SDValue &N) { 756 switch (N.getOpcode()) { 757 case ISD::ADD: 758 case ISD::ADDC: 759 return llvm::any_of(N.getNode()->ops(), 760 [](const SDUse &U) { return isAddressBase(U.get()); }); 761 case M68kISD::Wrapper: 762 case M68kISD::WrapperPC: 763 case M68kISD::GLOBAL_BASE_REG: 764 return true; 765 default: 766 return false; 767 } 768 } 769 770 bool M68kDAGToDAGISel::SelectARII(SDNode *Parent, SDValue N, SDValue &Disp, 771 SDValue &Base, SDValue &Index) { 772 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARII); 773 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARII: "); 774 775 if (!matchAddress(N, AM)) 776 return false; 777 778 if (AM.isPCRelative()) { 779 LLVM_DEBUG(dbgs() << "REJECT: PC relative\n"); 780 return false; 781 } 782 783 if (!AM.hasIndexReg()) { 784 LLVM_DEBUG(dbgs() << "REJECT: No Index\n"); 785 return false; 786 } 787 788 if (!AM.hasBaseReg()) { 789 LLVM_DEBUG(dbgs() << "REJECT: No Base\n"); 790 return false; 791 } 792 793 if (!isAddressBase(AM.BaseReg) && isAddressBase(AM.IndexReg)) { 794 Base = AM.IndexReg; 795 Index = AM.BaseReg; 796 } else { 797 Base = AM.BaseReg; 798 Index = AM.IndexReg; 799 } 800 801 if (AM.hasSymbolicDisplacement()) { 802 LLVM_DEBUG(dbgs() << "REJECT, Cannot match symbolic displacement\n"); 803 return false; 804 } 805 806 // The idea here is that we want to use AddrType::ARII without displacement 807 // only if necessary like memory operations, otherwise this must be lowered 808 // into addition 809 if (AM.Disp == 0 && (!Parent || (Parent->getOpcode() != ISD::LOAD && 810 Parent->getOpcode() != ISD::STORE))) { 811 LLVM_DEBUG(dbgs() << "REJECT: Displacement is Zero\n"); 812 return false; 813 } 814 815 Disp = getI8Imm(AM.Disp, SDLoc(N)); 816 817 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 818 return true; 819 } 820 821 bool M68kDAGToDAGISel::SelectAL(SDNode *Parent, SDValue N, SDValue &Sym) { 822 LLVM_DEBUG(dbgs() << "Selecting AddrType::AL: "); 823 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::AL); 824 825 if (!matchAddress(N, AM)) { 826 LLVM_DEBUG(dbgs() << "REJECT: Match failed\n"); 827 return false; 828 } 829 830 if (AM.isPCRelative()) { 831 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 832 return false; 833 } 834 835 if (AM.hasBase()) { 836 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Base\n"); 837 return false; 838 } 839 840 if (AM.hasIndexReg()) { 841 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 842 return false; 843 } 844 845 if (getSymbolicDisplacement(AM, SDLoc(N), Sym)) { 846 LLVM_DEBUG(dbgs() << "SUCCESS: Matched symbol\n"); 847 return true; 848 } 849 850 if (AM.Disp) { 851 Sym = getI32Imm(AM.Disp, SDLoc(N)); 852 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 853 return true; 854 } 855 856 LLVM_DEBUG(dbgs() << "REJECT: Not Symbol or Disp\n"); 857 return false; 858 ; 859 } 860 861 bool M68kDAGToDAGISel::SelectPCD(SDNode *Parent, SDValue N, SDValue &Disp) { 862 LLVM_DEBUG(dbgs() << "Selecting AddrType::PCD: "); 863 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCD); 864 865 if (!matchAddress(N, AM)) 866 return false; 867 868 if (!AM.isPCRelative()) { 869 LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n"); 870 return false; 871 } 872 873 if (AM.hasIndexReg()) { 874 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index\n"); 875 return false; 876 } 877 878 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 879 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 880 return true; 881 } 882 883 Disp = getI16Imm(AM.Disp, SDLoc(N)); 884 885 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 886 return true; 887 } 888 889 bool M68kDAGToDAGISel::SelectPCI(SDNode *Parent, SDValue N, SDValue &Disp, 890 SDValue &Index) { 891 LLVM_DEBUG(dbgs() << "Selecting AddrType::PCI: "); 892 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::PCI); 893 894 if (!matchAddress(N, AM)) 895 return false; 896 897 if (!AM.isPCRelative()) { 898 LLVM_DEBUG(dbgs() << "REJECT: Not PC relative\n"); 899 return false; 900 } 901 902 if (!AM.hasIndexReg()) { 903 LLVM_DEBUG(dbgs() << "REJECT: No Index\n"); 904 return false; 905 } 906 907 Index = AM.IndexReg; 908 909 if (getSymbolicDisplacement(AM, SDLoc(N), Disp)) { 910 assert(!AM.Disp && "Should not be any displacement"); 911 LLVM_DEBUG(dbgs() << "SUCCESS, matched Symbol\n"); 912 return true; 913 } 914 915 Disp = getI8Imm(AM.Disp, SDLoc(N)); 916 917 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 918 return true; 919 } 920 921 bool M68kDAGToDAGISel::SelectARI(SDNode *Parent, SDValue N, SDValue &Base) { 922 LLVM_DEBUG(dbgs() << "Selecting AddrType::ARI: "); 923 M68kISelAddressMode AM(M68kISelAddressMode::AddrType::ARI); 924 925 if (!matchAddress(N, AM)) { 926 LLVM_DEBUG(dbgs() << "REJECT: Match failed\n"); 927 return false; 928 } 929 930 if (AM.isPCRelative()) { 931 LLVM_DEBUG(dbgs() << "REJECT: Cannot match PC relative address\n"); 932 return false; 933 } 934 935 // AddrType::ARI does not use these 936 if (AM.hasIndexReg() || AM.Disp != 0) { 937 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Index or Disp\n"); 938 return false; 939 } 940 941 // Must be matched by AddrType::AL 942 if (AM.hasSymbolicDisplacement()) { 943 LLVM_DEBUG(dbgs() << "REJECT: Cannot match Symbolic Disp\n"); 944 return false; 945 } 946 947 if (AM.hasBaseReg()) { 948 Base = AM.BaseReg; 949 LLVM_DEBUG(dbgs() << "SUCCESS\n"); 950 return true; 951 } 952 953 return false; 954 } 955 956 bool M68kDAGToDAGISel::SelectInlineAsmMemoryOperand( 957 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, 958 std::vector<SDValue> &OutOps) { 959 // In order to tell AsmPrinter the exact addressing mode we select here, which 960 // might comprise of multiple SDValues (hence MachineOperands), a 32-bit 961 // immediate value is prepended to the list of selected SDValues to indicate 962 // the addressing mode kind. 963 using AMK = M68k::MemAddrModeKind; 964 auto addKind = [this](SDValue &Opnd, AMK Kind) -> bool { 965 Opnd = CurDAG->getTargetConstant(unsigned(Kind), SDLoc(), MVT::i32); 966 return true; 967 }; 968 969 switch (ConstraintID) { 970 // Generic memory operand. 971 case InlineAsm::ConstraintCode::m: { 972 // Try every supported (memory) addressing modes. 973 SDValue Operands[4]; 974 975 // TODO: The ordering of the following SelectXXX is relatively...arbitrary, 976 // right now we simply sort them by descending complexity. Maybe we should 977 // adjust this by code model and/or relocation mode in the future. 978 if (SelectARII(nullptr, Op, Operands[1], Operands[2], Operands[3]) && 979 addKind(Operands[0], AMK::f)) { 980 OutOps.insert(OutOps.end(), &Operands[0], Operands + 4); 981 return false; 982 } 983 984 if ((SelectPCI(nullptr, Op, Operands[1], Operands[2]) && 985 addKind(Operands[0], AMK::k)) || 986 (SelectARID(nullptr, Op, Operands[1], Operands[2]) && 987 addKind(Operands[0], AMK::p))) { 988 OutOps.insert(OutOps.end(), &Operands[0], Operands + 3); 989 return false; 990 } 991 992 if ((SelectPCD(nullptr, Op, Operands[1]) && addKind(Operands[0], AMK::q)) || 993 (SelectARI(nullptr, Op, Operands[1]) && addKind(Operands[0], AMK::j)) || 994 (SelectAL(nullptr, Op, Operands[1]) && addKind(Operands[0], AMK::b))) { 995 OutOps.insert(OutOps.end(), {Operands[0], Operands[1]}); 996 return false; 997 } 998 999 return true; 1000 } 1001 // 'Q': Address register indirect addressing. 1002 case InlineAsm::ConstraintCode::Q: { 1003 SDValue AMKind, Base; 1004 // 'j' addressing mode. 1005 // TODO: Add support for 'o' and 'e' after their 1006 // select functions are implemented. 1007 if (SelectARI(nullptr, Op, Base) && addKind(AMKind, AMK::j)) { 1008 OutOps.insert(OutOps.end(), {AMKind, Base}); 1009 return false; 1010 } 1011 return true; 1012 } 1013 // 'U': Address register indirect w/ constant offset addressing. 1014 case InlineAsm::ConstraintCode::Um: { 1015 SDValue AMKind, Base, Offset; 1016 // 'p' addressing mode. 1017 if (SelectARID(nullptr, Op, Offset, Base) && addKind(AMKind, AMK::p)) { 1018 OutOps.insert(OutOps.end(), {AMKind, Offset, Base}); 1019 return false; 1020 } 1021 return true; 1022 } 1023 default: 1024 return true; 1025 } 1026 } 1027