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
AVRDAGToDAGISel(AVRTargetMachine & TM,CodeGenOptLevel OptLevel)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;
AVRDAGToDAGISelLegacy(AVRTargetMachine & TM,CodeGenOptLevel OptLevel)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
INITIALIZE_PASS(AVRDAGToDAGISelLegacy,DEBUG_TYPE,PASS_NAME,false,false)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
SelectAddr(SDNode * Op,SDValue N,SDValue & Base,SDValue & Disp)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
selectIndexedLoad(SDNode * N)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
selectIndexedProgMemLoad(const LoadSDNode * LD,MVT VT,int Bank)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
SelectInlineAsmMemoryOperand(const SDValue & Op,InlineAsm::ConstraintCode ConstraintCode,std::vector<SDValue> & OutOps)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
select(SDNode * N)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
select(SDNode * N)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
select(SDNode * N)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
select(SDNode * N)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
select(SDNode * N)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
selectMultiplication(llvm::SDNode * N)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
Select(SDNode * N)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
trySelect(SDNode * N)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
createAVRISelDag(AVRTargetMachine & TM,CodeGenOptLevel OptLevel)598 FunctionPass *llvm::createAVRISelDag(AVRTargetMachine &TM,
599 CodeGenOptLevel OptLevel) {
600 return new AVRDAGToDAGISelLegacy(TM, OptLevel);
601 }
602