LCOV - code coverage report
Current view: top level - lib/Target/AVR - AVRISelDAGToDAG.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 148 199 74.4 %
Date: 2018-10-20 13:21:21 Functions: 13 15 86.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13