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:
AVRDAGToDAGISel(AVRTargetMachine & TM,CodeGenOpt::Level OptLevel)30   AVRDAGToDAGISel(AVRTargetMachine &TM, CodeGenOpt::Level OptLevel)
31       : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
32 
getPassName() const33   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 
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 
runOnMachineFunction(MachineFunction & MF)60 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
61   Subtarget = &MF.getSubtarget<AVRSubtarget>();
62   return SelectionDAGISel::runOnMachineFunction(MF);
63 }
64 
SelectAddr(SDNode * Op,SDValue N,SDValue & Base,SDValue & Disp)65 bool 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 
selectIndexedLoad(SDNode * N)122 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   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 
selectIndexedProgMemLoad(const LoadSDNode * LD,MVT VT)169 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   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 
SelectInlineAsmMemoryOperand(const SDValue & Op,unsigned ConstraintCode,std::vector<SDValue> & OutOps)203 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   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 
select(SDNode * N)309 template <> 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 
select(SDNode * N)324 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   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 
select(SDNode * N)363 template <> 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 
select(SDNode * N)421 template <> 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 
select(SDNode * N)461 template <> 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 
selectMultiplication(llvm::SDNode * N)476 bool 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 
Select(SDNode * N)521 void 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 
trySelect(SDNode * N)537 bool 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 
createAVRISelDag(AVRTargetMachine & TM,CodeGenOpt::Level OptLevel)556 FunctionPass *createAVRISelDag(AVRTargetMachine &TM,
557                                CodeGenOpt::Level OptLevel) {
558   return new AVRDAGToDAGISel(TM, OptLevel);
559 }
560 
561 } // end of namespace llvm
562 
563