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 
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 
M68kISelAddressMode__anonfd78cd6f0111::M68kISelAddressMode82   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 
hasSymbolicDisplacement__anonfd78cd6f0111::M68kISelAddressMode87   bool hasSymbolicDisplacement() const {
88     return GV != nullptr || CP != nullptr || ES != nullptr ||
89            MCSym != nullptr || JT != -1 || BlockAddr != nullptr;
90   }
91 
hasBase__anonfd78cd6f0111::M68kISelAddressMode92   bool hasBase() const {
93     return BaseType == Base::FrameIndexBase || BaseReg.getNode() != nullptr;
94   }
95 
hasFrameIndex__anonfd78cd6f0111::M68kISelAddressMode96   bool hasFrameIndex() const { return BaseType == Base::FrameIndexBase; }
97 
hasBaseReg__anonfd78cd6f0111::M68kISelAddressMode98   bool hasBaseReg() const {
99     return BaseType == Base::RegBase && BaseReg.getNode() != nullptr;
100   }
101 
hasIndexReg__anonfd78cd6f0111::M68kISelAddressMode102   bool hasIndexReg() const {
103     return BaseType == Base::RegBase && IndexReg.getNode() != nullptr;
104   }
105 
106   /// True if address mode type supports displacement
isDispAddrType__anonfd78cd6f0111::M68kISelAddressMode107   bool isDispAddrType() const {
108     return AM == AddrType::ARII || AM == AddrType::PCI ||
109            AM == AddrType::ARID || AM == AddrType::PCD || AM == AddrType::AL;
110   }
111 
getDispSize__anonfd78cd6f0111::M68kISelAddressMode112   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 
hasDisp__anonfd78cd6f0111::M68kISelAddressMode128   bool hasDisp() const { return getDispSize() != 0; }
isDisp8__anonfd78cd6f0111::M68kISelAddressMode129   bool isDisp8() const { return getDispSize() == 8; }
isDisp16__anonfd78cd6f0111::M68kISelAddressMode130   bool isDisp16() const { return getDispSize() == 16; }
isDisp32__anonfd78cd6f0111::M68kISelAddressMode131   bool isDisp32() const { return getDispSize() == 32; }
132 
133   /// Return true if this addressing mode is already PC-relative.
isPCRelative__anonfd78cd6f0111::M68kISelAddressMode134   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 
setBaseReg__anonfd78cd6f0111::M68kISelAddressMode142   void setBaseReg(SDValue Reg) {
143     BaseType = Base::RegBase;
144     BaseReg = Reg;
145   }
146 
setIndexReg__anonfd78cd6f0111::M68kISelAddressMode147   void setIndexReg(SDValue Reg) { IndexReg = Reg; }
148 
149 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump__anonfd78cd6f0111::M68kISelAddressMode150   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:
M68kDAGToDAGISel(M68kTargetMachine & TM)176   explicit M68kDAGToDAGISel(M68kTargetMachine &TM)
177       : SelectionDAGISel(TM), Subtarget(nullptr) {}
178 
getPassName() const179   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.
getTargetMachine()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
getFrameIndexAddress(M68kISelAddressMode & AM,const SDLoc & DL,SDValue & Disp,SDValue & Base)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
getSymbolicDisplacement(M68kISelAddressMode & AM,const SDLoc & DL,SDValue & Sym)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.
getI8Imm(int64_t Imm,const SDLoc & DL)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.
getI16Imm(int64_t Imm,const SDLoc & DL)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.
getI32Imm(int64_t Imm,const SDLoc & DL)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.
getInstrInfo() const303   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 
runOnMachineFunction(MachineFunction & MF)314 bool M68kDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
315   Subtarget = &static_cast<const M68kSubtarget &>(MF.getSubtarget());
316   return SelectionDAGISel::runOnMachineFunction(MF);
317 }
318 
319 /// This pass converts a legalized DAG into a M68k-specific DAG,
320 /// ready for instruction scheduling.
createM68kISelDag(M68kTargetMachine & TM)321 FunctionPass *llvm::createM68kISelDag(M68kTargetMachine &TM) {
322   return new M68kDAGToDAGISel(TM);
323 }
324 
doesDispFitFI(M68kISelAddressMode & AM)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 
doesDispFit(M68kISelAddressMode & AM,int64_t Val)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.
getGlobalBaseReg()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 
foldOffsetIntoAddress(uint64_t Offset,M68kISelAddressMode & AM)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.
matchAddressBase(SDValue N,M68kISelAddressMode & AM)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
matchLoadInAddress(LoadSDNode * N,M68kISelAddressMode & AM)390 bool M68kDAGToDAGISel::matchLoadInAddress(LoadSDNode *N,
391                                           M68kISelAddressMode &AM) {
392   return false;
393 }
394 
matchAddressRecursively(SDValue N,M68kISelAddressMode & AM,unsigned Depth)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.
matchAddress(SDValue N,M68kISelAddressMode & AM)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 
matchADD(SDValue & N,M68kISelAddressMode & AM,unsigned Depth)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.
matchWrapper(SDValue N,M68kISelAddressMode & AM)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 
Select(SDNode * Node)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 
632   case M68kISD::GLOBAL_BASE_REG:
633     ReplaceNode(Node, getGlobalBaseReg());
634     return;
635   }
636 
637   SelectCode(Node);
638 }
639 
SelectARIPI(SDNode * Parent,SDValue N,SDValue & Base)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 
SelectARIPD(SDNode * Parent,SDValue N,SDValue & Base)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 
SelectARID(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base)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 
isAddressBase(const SDValue & N)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:
708   case M68kISD::GLOBAL_BASE_REG:
709     return true;
710   default:
711     return false;
712   }
713 }
714 
SelectARII(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Base,SDValue & Index)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 
SelectAL(SDNode * Parent,SDValue N,SDValue & Sym)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 
SelectPCD(SDNode * Parent,SDValue N,SDValue & Disp)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 
SelectPCI(SDNode * Parent,SDValue N,SDValue & Disp,SDValue & Index)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 
SelectARI(SDNode * Parent,SDValue N,SDValue & Base)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 }
900