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