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