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