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