Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
35266 views
1
//===-- AVRISelDAGToDAG.cpp - A dag to dag inst selector for AVR ----------===//
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
// This file defines an instruction selector for the AVR target.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "AVR.h"
14
#include "AVRTargetMachine.h"
15
#include "MCTargetDesc/AVRMCTargetDesc.h"
16
17
#include "llvm/CodeGen/MachineRegisterInfo.h"
18
#include "llvm/CodeGen/SelectionDAGISel.h"
19
#include "llvm/Support/Debug.h"
20
#include "llvm/Support/raw_ostream.h"
21
22
#define DEBUG_TYPE "avr-isel"
23
#define PASS_NAME "AVR DAG->DAG Instruction Selection"
24
25
using namespace llvm;
26
27
namespace {
28
29
/// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form).
30
class AVRDAGToDAGISel : public SelectionDAGISel {
31
public:
32
AVRDAGToDAGISel() = delete;
33
34
AVRDAGToDAGISel(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
35
: SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
36
37
bool runOnMachineFunction(MachineFunction &MF) override;
38
39
bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
40
41
bool selectIndexedLoad(SDNode *N);
42
unsigned selectIndexedProgMemLoad(const LoadSDNode *LD, MVT VT, int Bank);
43
44
bool SelectInlineAsmMemoryOperand(const SDValue &Op,
45
InlineAsm::ConstraintCode ConstraintCode,
46
std::vector<SDValue> &OutOps) override;
47
48
// Include the pieces autogenerated from the target description.
49
#include "AVRGenDAGISel.inc"
50
51
private:
52
void Select(SDNode *N) override;
53
bool trySelect(SDNode *N);
54
55
template <unsigned NodeType> bool select(SDNode *N);
56
bool selectMultiplication(SDNode *N);
57
58
const AVRSubtarget *Subtarget;
59
};
60
61
class AVRDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
62
public:
63
static char ID;
64
AVRDAGToDAGISelLegacy(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
65
: SelectionDAGISelLegacy(
66
ID, std::make_unique<AVRDAGToDAGISel>(TM, OptLevel)) {}
67
};
68
69
} // namespace
70
71
char AVRDAGToDAGISelLegacy::ID = 0;
72
73
INITIALIZE_PASS(AVRDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
74
75
bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
76
Subtarget = &MF.getSubtarget<AVRSubtarget>();
77
return SelectionDAGISel::runOnMachineFunction(MF);
78
}
79
80
bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
81
SDValue &Disp) {
82
SDLoc dl(Op);
83
auto DL = CurDAG->getDataLayout();
84
MVT PtrVT = getTargetLowering()->getPointerTy(DL);
85
86
// if the address is a frame index get the TargetFrameIndex.
87
if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
88
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
89
Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
90
91
return true;
92
}
93
94
// Match simple Reg + uimm6 operands.
95
if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
96
!CurDAG->isBaseWithConstantOffset(N)) {
97
return false;
98
}
99
100
if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
101
int RHSC = (int)RHS->getZExtValue();
102
103
// Convert negative offsets into positives ones.
104
if (N.getOpcode() == ISD::SUB) {
105
RHSC = -RHSC;
106
}
107
108
// <#Frame index + const>
109
// Allow folding offsets bigger than 63 so the frame pointer can be used
110
// directly instead of copying it around by adjusting and restoring it for
111
// each access.
112
if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
113
int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
114
115
Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
116
Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i16);
117
118
return true;
119
}
120
121
// The value type of the memory instruction determines what is the maximum
122
// offset allowed.
123
MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
124
125
// We only accept offsets that fit in 6 bits (unsigned), with the exception
126
// of 16-bit loads - those can only go up to 62, because we desugar them
127
// into a pair of 8-bit loads like `ldd rx, RHSC` + `ldd ry, RHSC + 1`.
128
bool OkI8 = VT == MVT::i8 && RHSC <= 63;
129
bool OkI16 = VT == MVT::i16 && RHSC <= 62;
130
131
if (OkI8 || OkI16) {
132
Base = N.getOperand(0);
133
Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
134
135
return true;
136
}
137
}
138
139
return false;
140
}
141
142
bool AVRDAGToDAGISel::selectIndexedLoad(SDNode *N) {
143
const LoadSDNode *LD = cast<LoadSDNode>(N);
144
ISD::MemIndexedMode AM = LD->getAddressingMode();
145
MVT VT = LD->getMemoryVT().getSimpleVT();
146
auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
147
148
// We only care if this load uses a POSTINC or PREDEC mode.
149
if ((LD->getExtensionType() != ISD::NON_EXTLOAD) ||
150
(AM != ISD::POST_INC && AM != ISD::PRE_DEC)) {
151
152
return false;
153
}
154
155
unsigned Opcode = 0;
156
bool isPre = (AM == ISD::PRE_DEC);
157
int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
158
159
switch (VT.SimpleTy) {
160
case MVT::i8: {
161
if ((!isPre && Offs != 1) || (isPre && Offs != -1)) {
162
return false;
163
}
164
165
Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi;
166
break;
167
}
168
case MVT::i16: {
169
if ((!isPre && Offs != 2) || (isPre && Offs != -2)) {
170
return false;
171
}
172
173
Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi;
174
break;
175
}
176
default:
177
return false;
178
}
179
180
SDNode *ResNode =
181
CurDAG->getMachineNode(Opcode, SDLoc(N), VT, PtrVT, MVT::Other,
182
LD->getBasePtr(), LD->getChain());
183
ReplaceUses(N, ResNode);
184
CurDAG->RemoveDeadNode(N);
185
186
return true;
187
}
188
189
unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode *LD, MVT VT,
190
int Bank) {
191
// Progmem indexed loads only work in POSTINC mode.
192
if (LD->getExtensionType() != ISD::NON_EXTLOAD ||
193
LD->getAddressingMode() != ISD::POST_INC)
194
return 0;
195
196
// Feature ELPM is needed for loading from extended program memory.
197
assert((Bank == 0 || Subtarget->hasELPM()) &&
198
"cannot load from extended program memory on this mcu");
199
200
unsigned Opcode = 0;
201
int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
202
203
if (VT.SimpleTy == MVT::i8 && Offs == 1 && Bank == 0)
204
Opcode = AVR::LPMRdZPi;
205
206
// TODO: Implements the expansion of the following pseudo instructions.
207
// LPMWRdZPi: type == MVT::i16, offset == 2, Bank == 0.
208
// ELPMBRdZPi: type == MVT::i8, offset == 1, Bank > 0.
209
// ELPMWRdZPi: type == MVT::i16, offset == 2, Bank > 0.
210
211
return Opcode;
212
}
213
214
bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(
215
const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode,
216
std::vector<SDValue> &OutOps) {
217
assert((ConstraintCode == InlineAsm::ConstraintCode::m ||
218
ConstraintCode == InlineAsm::ConstraintCode::Q) &&
219
"Unexpected asm memory constraint");
220
221
MachineRegisterInfo &RI = MF->getRegInfo();
222
const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
223
const TargetLowering &TL = *STI.getTargetLowering();
224
SDLoc dl(Op);
225
auto DL = CurDAG->getDataLayout();
226
227
const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op);
228
229
// If address operand is of PTRDISPREGS class, all is OK, then.
230
if (RegNode &&
231
RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) {
232
OutOps.push_back(Op);
233
return false;
234
}
235
236
if (Op->getOpcode() == ISD::FrameIndex) {
237
SDValue Base, Disp;
238
239
if (SelectAddr(Op.getNode(), Op, Base, Disp)) {
240
OutOps.push_back(Base);
241
OutOps.push_back(Disp);
242
243
return false;
244
}
245
246
return true;
247
}
248
249
// If Op is add 'register, immediate' and
250
// register is either virtual register or register of PTRDISPREGSRegClass
251
if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) {
252
SDValue CopyFromRegOp = Op->getOperand(0);
253
SDValue ImmOp = Op->getOperand(1);
254
ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp);
255
256
unsigned Reg;
257
bool CanHandleRegImmOpt = ImmNode && ImmNode->getAPIntValue().ult(64);
258
259
if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) {
260
RegisterSDNode *RegNode =
261
cast<RegisterSDNode>(CopyFromRegOp->getOperand(1));
262
Reg = RegNode->getReg();
263
CanHandleRegImmOpt &= (Register::isVirtualRegister(Reg) ||
264
AVR::PTRDISPREGSRegClass.contains(Reg));
265
} else {
266
CanHandleRegImmOpt = false;
267
}
268
269
// If we detect proper case - correct virtual register class
270
// if needed and go to another inlineasm operand.
271
if (CanHandleRegImmOpt) {
272
SDValue Base, Disp;
273
274
if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
275
SDLoc dl(CopyFromRegOp);
276
277
Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
278
279
SDValue CopyToReg =
280
CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
281
282
SDValue NewCopyFromRegOp =
283
CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
284
285
Base = NewCopyFromRegOp;
286
} else {
287
Base = CopyFromRegOp;
288
}
289
290
if (ImmNode->getValueType(0) != MVT::i8) {
291
Disp = CurDAG->getTargetConstant(ImmNode->getZExtValue(), dl, MVT::i8);
292
} else {
293
Disp = ImmOp;
294
}
295
296
OutOps.push_back(Base);
297
OutOps.push_back(Disp);
298
299
return false;
300
}
301
}
302
303
// More generic case.
304
// Create chain that puts Op into pointer register
305
// and return that register.
306
Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
307
308
SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
309
SDValue CopyFromReg =
310
CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
311
312
OutOps.push_back(CopyFromReg);
313
314
return false;
315
}
316
317
template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) {
318
auto DL = CurDAG->getDataLayout();
319
320
// Convert the frameindex into a temp instruction that will hold the
321
// effective address of the final stack slot.
322
int FI = cast<FrameIndexSDNode>(N)->getIndex();
323
SDValue TFI =
324
CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
325
326
CurDAG->SelectNodeTo(N, AVR::FRMIDX, getTargetLowering()->getPointerTy(DL),
327
TFI, CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16));
328
return true;
329
}
330
331
template <> bool AVRDAGToDAGISel::select<ISD::STORE>(SDNode *N) {
332
// Use the STD{W}SPQRr pseudo instruction when passing arguments through
333
// the stack on function calls for further expansion during the PEI phase.
334
const StoreSDNode *ST = cast<StoreSDNode>(N);
335
SDValue BasePtr = ST->getBasePtr();
336
337
// Early exit when the base pointer is a frame index node or a constant.
338
if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
339
BasePtr.isUndef()) {
340
return false;
341
}
342
343
const RegisterSDNode *RN = dyn_cast<RegisterSDNode>(BasePtr.getOperand(0));
344
// Only stores where SP is the base pointer are valid.
345
if (!RN || (RN->getReg() != AVR::SP)) {
346
return false;
347
}
348
349
int CST = (int)BasePtr.getConstantOperandVal(1);
350
SDValue Chain = ST->getChain();
351
EVT VT = ST->getValue().getValueType();
352
SDLoc DL(N);
353
SDValue Offset = CurDAG->getTargetConstant(CST, DL, MVT::i16);
354
SDValue Ops[] = {BasePtr.getOperand(0), Offset, ST->getValue(), Chain};
355
unsigned Opc = (VT == MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr;
356
357
SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops);
358
359
// Transfer memory operands.
360
CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {ST->getMemOperand()});
361
362
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
363
CurDAG->RemoveDeadNode(N);
364
365
return true;
366
}
367
368
template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) {
369
const LoadSDNode *LD = cast<LoadSDNode>(N);
370
if (!AVR::isProgramMemoryAccess(LD)) {
371
// Check if the opcode can be converted into an indexed load.
372
return selectIndexedLoad(N);
373
}
374
375
if (!Subtarget->hasLPM())
376
report_fatal_error("cannot load from program memory on this mcu");
377
378
int ProgMemBank = AVR::getProgramMemoryBank(LD);
379
if (ProgMemBank < 0 || ProgMemBank > 5)
380
report_fatal_error("unexpected program memory bank");
381
if (ProgMemBank > 0 && !Subtarget->hasELPM())
382
report_fatal_error("unexpected program memory bank");
383
384
// This is a flash memory load, move the pointer into R31R30 and emit
385
// the lpm instruction.
386
MVT VT = LD->getMemoryVT().getSimpleVT();
387
SDValue Chain = LD->getChain();
388
SDValue Ptr = LD->getBasePtr();
389
SDNode *ResNode;
390
SDLoc DL(N);
391
392
Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue());
393
Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16,
394
Chain.getValue(1));
395
396
// Check if the opcode can be converted into an indexed load.
397
if (unsigned LPMOpc = selectIndexedProgMemLoad(LD, VT, ProgMemBank)) {
398
// It is legal to fold the load into an indexed load.
399
if (ProgMemBank == 0) {
400
ResNode =
401
CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other, Ptr);
402
} else {
403
// Do not combine the LDI instruction into the ELPM pseudo instruction,
404
// since it may be reused by other ELPM pseudo instructions.
405
SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
406
auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
407
ResNode = CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other,
408
Ptr, SDValue(NP, 0));
409
}
410
} else {
411
// Selecting an indexed load is not legal, fallback to a normal load.
412
switch (VT.SimpleTy) {
413
case MVT::i8:
414
if (ProgMemBank == 0) {
415
unsigned Opc = Subtarget->hasLPMX() ? AVR::LPMRdZ : AVR::LPMBRdZ;
416
ResNode =
417
CurDAG->getMachineNode(Opc, DL, MVT::i8, MVT::Other, Ptr);
418
} else {
419
// Do not combine the LDI instruction into the ELPM pseudo instruction,
420
// since it may be reused by other ELPM pseudo instructions.
421
SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
422
auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
423
ResNode = CurDAG->getMachineNode(AVR::ELPMBRdZ, DL, MVT::i8, MVT::Other,
424
Ptr, SDValue(NP, 0));
425
}
426
break;
427
case MVT::i16:
428
if (ProgMemBank == 0) {
429
ResNode =
430
CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16, MVT::Other, Ptr);
431
} else {
432
// Do not combine the LDI instruction into the ELPM pseudo instruction,
433
// since LDI requires the destination register in range R16~R31.
434
SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
435
auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
436
ResNode = CurDAG->getMachineNode(AVR::ELPMWRdZ, DL, MVT::i16,
437
MVT::Other, Ptr, SDValue(NP, 0));
438
}
439
break;
440
default:
441
llvm_unreachable("Unsupported VT!");
442
}
443
}
444
445
// Transfer memory operands.
446
CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()});
447
448
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
449
ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
450
CurDAG->RemoveDeadNode(N);
451
452
return true;
453
}
454
455
template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
456
SDValue InGlue;
457
SDValue Chain = N->getOperand(0);
458
SDValue Callee = N->getOperand(1);
459
unsigned LastOpNum = N->getNumOperands() - 1;
460
461
// Direct calls are autogenerated.
462
unsigned Op = Callee.getOpcode();
463
if (Op == ISD::TargetGlobalAddress || Op == ISD::TargetExternalSymbol) {
464
return false;
465
}
466
467
// Skip the incoming flag if present
468
if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
469
--LastOpNum;
470
}
471
472
SDLoc DL(N);
473
Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InGlue);
474
SmallVector<SDValue, 8> Ops;
475
Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16));
476
477
// Map all operands into the new node.
478
for (unsigned i = 2, e = LastOpNum + 1; i != e; ++i) {
479
Ops.push_back(N->getOperand(i));
480
}
481
482
Ops.push_back(Chain);
483
Ops.push_back(Chain.getValue(1));
484
485
SDNode *ResNode = CurDAG->getMachineNode(
486
Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL, DL, MVT::Other,
487
MVT::Glue, Ops);
488
489
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
490
ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
491
CurDAG->RemoveDeadNode(N);
492
493
return true;
494
}
495
496
template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
497
SDValue Chain = N->getOperand(0);
498
SDValue JmpAddr = N->getOperand(1);
499
500
SDLoc DL(N);
501
// Move the destination address of the indirect branch into R31R30.
502
Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, JmpAddr);
503
SDNode *ResNode = CurDAG->getMachineNode(AVR::IJMP, DL, MVT::Other, Chain);
504
505
ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
506
CurDAG->RemoveDeadNode(N);
507
508
return true;
509
}
510
511
bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
512
SDLoc DL(N);
513
MVT Type = N->getSimpleValueType(0);
514
515
assert(Type == MVT::i8 && "unexpected value type");
516
517
bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
518
unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
519
520
SDValue Lhs = N->getOperand(0);
521
SDValue Rhs = N->getOperand(1);
522
SDNode *Mul = CurDAG->getMachineNode(MachineOp, DL, MVT::Glue, Lhs, Rhs);
523
SDValue InChain = CurDAG->getEntryNode();
524
SDValue InGlue = SDValue(Mul, 0);
525
526
// Copy the low half of the result, if it is needed.
527
if (N->hasAnyUseOfValue(0)) {
528
SDValue CopyFromLo =
529
CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
530
531
ReplaceUses(SDValue(N, 0), CopyFromLo);
532
533
InChain = CopyFromLo.getValue(1);
534
InGlue = CopyFromLo.getValue(2);
535
}
536
537
// Copy the high half of the result, if it is needed.
538
if (N->hasAnyUseOfValue(1)) {
539
SDValue CopyFromHi =
540
CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
541
542
ReplaceUses(SDValue(N, 1), CopyFromHi);
543
544
InChain = CopyFromHi.getValue(1);
545
InGlue = CopyFromHi.getValue(2);
546
}
547
548
CurDAG->RemoveDeadNode(N);
549
550
// We need to clear R1. This is currently done (dirtily)
551
// using a custom inserter.
552
553
return true;
554
}
555
556
void AVRDAGToDAGISel::Select(SDNode *N) {
557
// If we have a custom node, we already have selected!
558
if (N->isMachineOpcode()) {
559
LLVM_DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n");
560
N->setNodeId(-1);
561
return;
562
}
563
564
// See if subclasses can handle this node.
565
if (trySelect(N))
566
return;
567
568
// Select the default instruction
569
SelectCode(N);
570
}
571
572
bool AVRDAGToDAGISel::trySelect(SDNode *N) {
573
unsigned Opcode = N->getOpcode();
574
SDLoc DL(N);
575
576
switch (Opcode) {
577
// Nodes we fully handle.
578
case ISD::FrameIndex:
579
return select<ISD::FrameIndex>(N);
580
case ISD::BRIND:
581
return select<ISD::BRIND>(N);
582
case ISD::UMUL_LOHI:
583
case ISD::SMUL_LOHI:
584
return selectMultiplication(N);
585
586
// Nodes we handle partially. Other cases are autogenerated
587
case ISD::STORE:
588
return select<ISD::STORE>(N);
589
case ISD::LOAD:
590
return select<ISD::LOAD>(N);
591
case AVRISD::CALL:
592
return select<AVRISD::CALL>(N);
593
default:
594
return false;
595
}
596
}
597
598
FunctionPass *llvm::createAVRISelDag(AVRTargetMachine &TM,
599
CodeGenOptLevel OptLevel) {
600
return new AVRDAGToDAGISelLegacy(TM, OptLevel);
601
}
602
603