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