AVRISelDAGToDAG.cpp revision 341825
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
25namespace llvm {
26
27/// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form).
28class AVRDAGToDAGISel : public SelectionDAGISel {
29public:
30  AVRDAGToDAGISel(AVRTargetMachine &TM, CodeGenOpt::Level OptLevel)
31      : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
32
33  StringRef getPassName() const override {
34    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
50private:
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
60bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
61  Subtarget = &MF.getSubtarget<AVRSubtarget>();
62  return SelectionDAGISel::runOnMachineFunction(MF);
63}
64
65bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
66                                 SDValue &Disp) {
67  SDLoc dl(Op);
68  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    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
74    Disp = CurDAG->getTargetConstant(0, dl, MVT::i8);
75
76    return true;
77  }
78
79  // Match simple Reg + uimm6 operands.
80  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
81      !CurDAG->isBaseWithConstantOffset(N)) {
82    return false;
83  }
84
85  if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
86    int RHSC = (int)RHS->getZExtValue();
87
88    // Convert negative offsets into positives ones.
89    if (N.getOpcode() == ISD::SUB) {
90      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    if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
98      int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
99
100      Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
101      Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i16);
102
103      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    if (isUInt<6>(RHSC) && (VT == MVT::i8 || VT == MVT::i16)) {
112      Base = N.getOperand(0);
113      Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
114
115      return true;
116    }
117  }
118
119  return false;
120}
121
122bool AVRDAGToDAGISel::selectIndexedLoad(SDNode *N) {
123  const LoadSDNode *LD = cast<LoadSDNode>(N);
124  ISD::MemIndexedMode AM = LD->getAddressingMode();
125  MVT VT = LD->getMemoryVT().getSimpleVT();
126  auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
127
128  // We only care if this load uses a POSTINC or PREDEC mode.
129  if ((LD->getExtensionType() != ISD::NON_EXTLOAD) ||
130      (AM != ISD::POST_INC && AM != ISD::PRE_DEC)) {
131
132    return false;
133  }
134
135  unsigned Opcode = 0;
136  bool isPre = (AM == ISD::PRE_DEC);
137  int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
138
139  switch (VT.SimpleTy) {
140  case MVT::i8: {
141    if ((!isPre && Offs != 1) || (isPre && Offs != -1)) {
142      return false;
143    }
144
145    Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi;
146    break;
147  }
148  case MVT::i16: {
149    if ((!isPre && Offs != 2) || (isPre && Offs != -2)) {
150      return false;
151    }
152
153    Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi;
154    break;
155  }
156  default:
157    return false;
158  }
159
160  SDNode *ResNode = CurDAG->getMachineNode(Opcode, SDLoc(N), VT,
161                                           PtrVT, MVT::Other,
162                                           LD->getBasePtr(), LD->getChain());
163  ReplaceUses(N, ResNode);
164  CurDAG->RemoveDeadNode(N);
165
166  return true;
167}
168
169unsigned 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  if (LD->getExtensionType() != ISD::NON_EXTLOAD || AM != ISD::POST_INC) {
175    return 0;
176  }
177
178  unsigned Opcode = 0;
179  int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
180
181  switch (VT.SimpleTy) {
182  case MVT::i8: {
183    if (Offs != 1) {
184      return 0;
185    }
186    Opcode = AVR::LPMRdZPi;
187    break;
188  }
189  case MVT::i16: {
190    if (Offs != 2) {
191      return 0;
192    }
193    Opcode = AVR::LPMWRdZPi;
194    break;
195  }
196  default:
197    return 0;
198  }
199
200  return Opcode;
201}
202
203bool 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  MachineRegisterInfo &RI = MF->getRegInfo();
211  const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
212  const TargetLowering &TL = *STI.getTargetLowering();
213  SDLoc dl(Op);
214  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  if (RegNode &&
220      RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) {
221    OutOps.push_back(Op);
222    return false;
223  }
224
225  if (Op->getOpcode() == ISD::FrameIndex) {
226    SDValue Base, Disp;
227
228    if (SelectAddr(Op.getNode(), Op, Base, Disp)) {
229      OutOps.push_back(Base);
230      OutOps.push_back(Disp);
231
232      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  if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) {
241    SDValue CopyFromRegOp = Op->getOperand(0);
242    SDValue ImmOp = Op->getOperand(1);
243    ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp);
244
245    unsigned Reg;
246    bool CanHandleRegImmOpt = true;
247
248    CanHandleRegImmOpt &= ImmNode != 0;
249    CanHandleRegImmOpt &= ImmNode->getAPIntValue().getZExtValue() < 64;
250
251    if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) {
252      RegisterSDNode *RegNode =
253          cast<RegisterSDNode>(CopyFromRegOp->getOperand(1));
254      Reg = RegNode->getReg();
255      CanHandleRegImmOpt &= (TargetRegisterInfo::isVirtualRegister(Reg) ||
256                             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    if (CanHandleRegImmOpt) {
264      SDValue Base, Disp;
265
266      if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
267        SDLoc dl(CopyFromRegOp);
268
269        unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
270
271        SDValue CopyToReg =
272            CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
273
274        SDValue NewCopyFromRegOp =
275            CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
276
277        Base = NewCopyFromRegOp;
278      } else {
279        Base = CopyFromRegOp;
280      }
281
282      if (ImmNode->getValueType(0) != MVT::i8) {
283        Disp = CurDAG->getTargetConstant(ImmNode->getAPIntValue().getZExtValue(), dl, MVT::i8);
284      } else {
285        Disp = ImmOp;
286      }
287
288      OutOps.push_back(Base);
289      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  unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
299
300  SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
301  SDValue CopyFromReg =
302      CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
303
304  OutOps.push_back(CopyFromReg);
305
306  return false;
307}
308
309template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) {
310  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  int FI = cast<FrameIndexSDNode>(N)->getIndex();
315  SDValue TFI =
316    CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
317
318  CurDAG->SelectNodeTo(N, AVR::FRMIDX,
319                       getTargetLowering()->getPointerTy(DL), TFI,
320                       CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16));
321  return true;
322}
323
324template <> 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  SDValue BasePtr = ST->getBasePtr();
329
330  // Early exit when the base pointer is a frame index node or a constant.
331  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  if (!RN || (RN->getReg() != AVR::SP)) {
339    return false;
340  }
341
342  int CST = (int)cast<ConstantSDNode>(BasePtr.getOperand(1))->getZExtValue();
343  SDValue Chain = ST->getChain();
344  EVT VT = ST->getValue().getValueType();
345  SDLoc DL(N);
346  SDValue Offset = CurDAG->getTargetConstant(CST, DL, MVT::i16);
347  SDValue Ops[] = {BasePtr.getOperand(0), Offset, ST->getValue(), Chain};
348  unsigned Opc = (VT == MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr;
349
350  SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops);
351
352  // Transfer memory operands.
353  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
354  MemOp[0] = ST->getMemOperand();
355  cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
356
357  ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
358  CurDAG->RemoveDeadNode(N);
359
360  return true;
361}
362
363template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) {
364  const LoadSDNode *LD = cast<LoadSDNode>(N);
365  if (!AVR::isProgramMemoryAccess(LD)) {
366    // Check if the opcode can be converted into an indexed load.
367    return selectIndexedLoad(N);
368  }
369
370  assert(Subtarget->hasLPM() && "cannot load from program memory on this mcu");
371
372  // This is a flash memory load, move the pointer into R31R30 and emit
373  // the lpm instruction.
374  MVT VT = LD->getMemoryVT().getSimpleVT();
375  SDValue Chain = LD->getChain();
376  SDValue Ptr = LD->getBasePtr();
377  SDNode *ResNode;
378  SDLoc DL(N);
379
380  Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue());
381  Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16,
382                               Chain.getValue(1));
383
384  SDValue RegZ = CurDAG->getRegister(AVR::R31R30, MVT::i16);
385
386  // Check if the opcode can be converted into an indexed load.
387  if (unsigned LPMOpc = selectIndexedProgMemLoad(LD, VT)) {
388    // It is legal to fold the load into an indexed load.
389    ResNode = CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other, Ptr,
390                                     RegZ);
391    ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
392  } else {
393    // Selecting an indexed load is not legal, fallback to a normal load.
394    switch (VT.SimpleTy) {
395    case MVT::i8:
396      ResNode = CurDAG->getMachineNode(AVR::LPMRdZ, DL, MVT::i8, MVT::Other,
397                                       Ptr, RegZ);
398      break;
399    case MVT::i16:
400      ResNode = CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16,
401                                       MVT::Other, Ptr, RegZ);
402      ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
403      break;
404    default:
405      llvm_unreachable("Unsupported VT!");
406    }
407  }
408
409  // Transfer memory operands.
410  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
411  MemOp[0] = LD->getMemOperand();
412  cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
413
414  ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
415  ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
416  CurDAG->RemoveDeadNode(N);
417
418  return true;
419}
420
421template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
422  SDValue InFlag;
423  SDValue Chain = N->getOperand(0);
424  SDValue Callee = N->getOperand(1);
425  unsigned LastOpNum = N->getNumOperands() - 1;
426
427  // Direct calls are autogenerated.
428  unsigned Op = Callee.getOpcode();
429  if (Op == ISD::TargetGlobalAddress || Op == ISD::TargetExternalSymbol) {
430    return false;
431  }
432
433  // Skip the incoming flag if present
434  if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
435    --LastOpNum;
436  }
437
438  SDLoc DL(N);
439  Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InFlag);
440  SmallVector<SDValue, 8> Ops;
441  Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16));
442
443  // Map all operands into the new node.
444  for (unsigned i = 2, e = LastOpNum + 1; i != e; ++i) {
445    Ops.push_back(N->getOperand(i));
446  }
447
448  Ops.push_back(Chain);
449  Ops.push_back(Chain.getValue(1));
450
451  SDNode *ResNode =
452    CurDAG->getMachineNode(AVR::ICALL, DL, MVT::Other, MVT::Glue, Ops);
453
454  ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
455  ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
456  CurDAG->RemoveDeadNode(N);
457
458  return true;
459}
460
461template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
462  SDValue Chain = N->getOperand(0);
463  SDValue JmpAddr = N->getOperand(1);
464
465  SDLoc DL(N);
466  // Move the destination address of the indirect branch into R31R30.
467  Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, JmpAddr);
468  SDNode *ResNode = CurDAG->getMachineNode(AVR::IJMP, DL, MVT::Other, Chain);
469
470  ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
471  CurDAG->RemoveDeadNode(N);
472
473  return true;
474}
475
476bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
477  SDLoc DL(N);
478  MVT Type = N->getSimpleValueType(0);
479
480  assert(Type == MVT::i8 && "unexpected value type");
481
482  bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
483  unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
484
485  SDValue Lhs = N->getOperand(0);
486  SDValue Rhs = N->getOperand(1);
487  SDNode *Mul = CurDAG->getMachineNode(MachineOp, DL, MVT::Glue, Lhs, Rhs);
488  SDValue InChain = CurDAG->getEntryNode();
489  SDValue InGlue = SDValue(Mul, 0);
490
491  // Copy the low half of the result, if it is needed.
492  if (N->hasAnyUseOfValue(0)) {
493    SDValue CopyFromLo =
494        CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
495
496    ReplaceUses(SDValue(N, 0), CopyFromLo);
497
498    InChain = CopyFromLo.getValue(1);
499    InGlue = CopyFromLo.getValue(2);
500  }
501
502  // Copy the high half of the result, if it is needed.
503  if (N->hasAnyUseOfValue(1)) {
504    SDValue CopyFromHi =
505        CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
506
507    ReplaceUses(SDValue(N, 1), CopyFromHi);
508
509    InChain = CopyFromHi.getValue(1);
510    InGlue = CopyFromHi.getValue(2);
511  }
512
513  CurDAG->RemoveDeadNode(N);
514
515  // We need to clear R1. This is currently done (dirtily)
516  // using a custom inserter.
517
518  return true;
519}
520
521void AVRDAGToDAGISel::Select(SDNode *N) {
522  // If we have a custom node, we already have selected!
523  if (N->isMachineOpcode()) {
524    LLVM_DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n");
525    N->setNodeId(-1);
526    return;
527  }
528
529  // See if subclasses can handle this node.
530  if (trySelect(N))
531    return;
532
533  // Select the default instruction
534  SelectCode(N);
535}
536
537bool AVRDAGToDAGISel::trySelect(SDNode *N) {
538  unsigned Opcode = N->getOpcode();
539  SDLoc DL(N);
540
541  switch (Opcode) {
542  // Nodes we fully handle.
543  case ISD::FrameIndex: return select<ISD::FrameIndex>(N);
544  case ISD::BRIND:      return select<ISD::BRIND>(N);
545  case ISD::UMUL_LOHI:
546  case ISD::SMUL_LOHI:  return selectMultiplication(N);
547
548  // Nodes we handle partially. Other cases are autogenerated
549  case ISD::STORE:   return select<ISD::STORE>(N);
550  case ISD::LOAD:    return select<ISD::LOAD>(N);
551  case AVRISD::CALL: return select<AVRISD::CALL>(N);
552  default:           return false;
553  }
554}
555
556FunctionPass *createAVRISelDag(AVRTargetMachine &TM,
557                               CodeGenOpt::Level OptLevel) {
558  return new AVRDAGToDAGISel(TM, OptLevel);
559}
560
561} // end of namespace llvm
562
563