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