xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp (revision 6e516c87b6d779911edde7481d8aef165b837a03)
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