1 //===-- AVRISelDAGToDAG.cpp - A dag to dag inst selector for AVR ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines an instruction selector for the AVR target.
12 //===----------------------------------------------------------------------===//
15 #include "AVRTargetMachine.h"
16 #include "MCTargetDesc/AVRMCTargetDesc.h"
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"
23 #define DEBUG_TYPE "avr-isel"
27 /// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form).
28 class AVRDAGToDAGISel : public SelectionDAGISel {
30 AVRDAGToDAGISel(AVRTargetMachine &TM, CodeGenOpt::Level OptLevel)
31 : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
33 StringRef getPassName() const override {
34 return "AVR DAG->DAG Instruction Selection";
37 bool runOnMachineFunction(MachineFunction &MF) override;
39 bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
41 bool selectIndexedLoad(SDNode *N);
42 unsigned selectIndexedProgMemLoad(const LoadSDNode *LD, MVT VT);
44 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
45 std::vector<SDValue> &OutOps) override;
47 // Include the pieces autogenerated from the target description.
48 #include "AVRGenDAGISel.inc"
51 void Select(SDNode *N) override;
52 bool trySelect(SDNode *N);
54 template <unsigned NodeType> bool select(SDNode *N);
55 bool selectMultiplication(SDNode *N);
57 const AVRSubtarget *Subtarget;
60 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
61 Subtarget = &MF.getSubtarget<AVRSubtarget>();
62 return SelectionDAGISel::runOnMachineFunction(MF);
65 bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
68 auto DL = CurDAG->getDataLayout();
69 MVT PtrVT = getTargetLowering()->getPointerTy(DL);
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);
79 // Match simple Reg + uimm6 operands.
80 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
81 !CurDAG->isBaseWithConstantOffset(N)) {
85 if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
86 int RHSC = (int)RHS->getZExtValue();
88 // Convert negative offsets into positives ones.
89 if (N.getOpcode() == ISD::SUB) {
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
97 if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
98 int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
100 Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
101 Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i16);
106 // The value type of the memory instruction determines what is the maximum
108 MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
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);
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());
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)) {
136 bool isPre = (AM == ISD::PRE_DEC);
137 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
139 switch (VT.SimpleTy) {
141 if ((!isPre && Offs != 1) || (isPre && Offs != -1)) {
145 Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi;
149 if ((!isPre && Offs != 2) || (isPre && Offs != -2)) {
153 Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi;
160 SDNode *ResNode = CurDAG->getMachineNode(Opcode, SDLoc(N), VT,
162 LD->getBasePtr(), LD->getChain());
163 ReplaceUses(N, ResNode);
164 CurDAG->RemoveDeadNode(N);
169 unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode *LD,
171 ISD::MemIndexedMode AM = LD->getAddressingMode();
173 // Progmem indexed loads only work in POSTINC mode.
174 if (LD->getExtensionType() != ISD::NON_EXTLOAD || AM != ISD::POST_INC) {
179 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
181 switch (VT.SimpleTy) {
186 Opcode = AVR::LPMRdZPi;
193 Opcode = AVR::LPMWRdZPi;
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");
210 MachineRegisterInfo &RI = MF->getRegInfo();
211 const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
212 const TargetLowering &TL = *STI.getTargetLowering();
214 auto DL = CurDAG->getDataLayout();
216 const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op);
218 // If address operand is of PTRDISPREGS class, all is OK, then.
220 RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) {
221 OutOps.push_back(Op);
225 if (Op->getOpcode() == ISD::FrameIndex) {
228 if (SelectAddr(Op.getNode(), Op, Base, Disp)) {
229 OutOps.push_back(Base);
230 OutOps.push_back(Disp);
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);
246 bool CanHandleRegImmOpt = true;
248 CanHandleRegImmOpt &= ImmNode != 0;
249 CanHandleRegImmOpt &= ImmNode->getAPIntValue().getZExtValue() < 64;
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));
258 CanHandleRegImmOpt = false;
261 // If we detect proper case - correct virtual register class
262 // if needed and go to another inlineasm operand.
263 if (CanHandleRegImmOpt) {
266 if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
267 SDLoc dl(CopyFromRegOp);
269 unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
272 CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
274 SDValue NewCopyFromRegOp =
275 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
277 Base = NewCopyFromRegOp;
279 Base = CopyFromRegOp;
282 if (ImmNode->getValueType(0) != MVT::i8) {
283 Disp = CurDAG->getTargetConstant(ImmNode->getAPIntValue().getZExtValue(), dl, MVT::i8);
288 OutOps.push_back(Base);
289 OutOps.push_back(Disp);
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);
300 SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
301 SDValue CopyFromReg =
302 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
304 OutOps.push_back(CopyFromReg);
309 template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) {
310 auto DL = CurDAG->getDataLayout();
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();
316 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
318 CurDAG->SelectNodeTo(N, AVR::FRMIDX,
319 getTargetLowering()->getPointerTy(DL), TFI,
320 CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16));
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();
330 // Early exit when the base pointer is a frame index node or a constant.
331 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
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)) {
342 int CST = (int)cast<ConstantSDNode>(BasePtr.getOperand(1))->getZExtValue();
343 SDValue Chain = ST->getChain();
344 EVT VT = ST->getValue().getValueType();
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;
350 SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops);
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);
357 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
358 CurDAG->RemoveDeadNode(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);
370 assert(Subtarget->hasLPM() && "cannot load from program memory on this mcu");
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();
380 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue());
381 Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16,
384 SDValue RegZ = CurDAG->getRegister(AVR::R31R30, MVT::i16);
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,
391 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
393 // Selecting an indexed load is not legal, fallback to a normal load.
394 switch (VT.SimpleTy) {
396 ResNode = CurDAG->getMachineNode(AVR::LPMRdZ, DL, MVT::i8, MVT::Other,
400 ResNode = CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16,
401 MVT::Other, Ptr, RegZ);
402 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
405 llvm_unreachable("Unsupported VT!");
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);
414 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
415 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
416 CurDAG->RemoveDeadNode(N);
421 template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
423 SDValue Chain = N->getOperand(0);
424 SDValue Callee = N->getOperand(1);
425 unsigned LastOpNum = N->getNumOperands() - 1;
427 // Direct calls are autogenerated.
428 unsigned Op = Callee.getOpcode();
429 if (Op == ISD::TargetGlobalAddress || Op == ISD::TargetExternalSymbol) {
433 // Skip the incoming flag if present
434 if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
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));
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));
448 Ops.push_back(Chain);
449 Ops.push_back(Chain.getValue(1));
452 CurDAG->getMachineNode(AVR::ICALL, DL, MVT::Other, MVT::Glue, Ops);
454 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
455 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
456 CurDAG->RemoveDeadNode(N);
461 template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
462 SDValue Chain = N->getOperand(0);
463 SDValue JmpAddr = N->getOperand(1);
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);
470 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
471 CurDAG->RemoveDeadNode(N);
476 bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
478 MVT Type = N->getSimpleValueType(0);
480 assert(Type == MVT::i8 && "unexpected value type");
482 bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
483 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
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);
491 // Copy the low half of the result, if it is needed.
492 if (N->hasAnyUseOfValue(0)) {
494 CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
496 ReplaceUses(SDValue(N, 0), CopyFromLo);
498 InChain = CopyFromLo.getValue(1);
499 InGlue = CopyFromLo.getValue(2);
502 // Copy the high half of the result, if it is needed.
503 if (N->hasAnyUseOfValue(1)) {
505 CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
507 ReplaceUses(SDValue(N, 1), CopyFromHi);
509 InChain = CopyFromHi.getValue(1);
510 InGlue = CopyFromHi.getValue(2);
513 CurDAG->RemoveDeadNode(N);
515 // We need to clear R1. This is currently done (dirtily)
516 // using a custom inserter.
521 void AVRDAGToDAGISel::Select(SDNode *N) {
522 // Dump information about the Node being selected
523 DEBUG(errs() << "Selecting: "; N->dump(CurDAG); errs() << "\n");
525 // If we have a custom node, we already have selected!
526 if (N->isMachineOpcode()) {
527 DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n");
532 // See if subclasses can handle this node.
536 // Select the default instruction
540 bool AVRDAGToDAGISel::trySelect(SDNode *N) {
541 unsigned Opcode = N->getOpcode();
545 // Nodes we fully handle.
546 case ISD::FrameIndex: return select<ISD::FrameIndex>(N);
547 case ISD::BRIND: return select<ISD::BRIND>(N);
549 case ISD::SMUL_LOHI: return selectMultiplication(N);
551 // Nodes we handle partially. Other cases are autogenerated
552 case ISD::STORE: return select<ISD::STORE>(N);
553 case ISD::LOAD: return select<ISD::LOAD>(N);
554 case AVRISD::CALL: return select<AVRISD::CALL>(N);
555 default: return false;
559 FunctionPass *createAVRISelDag(AVRTargetMachine &TM,
560 CodeGenOpt::Level OptLevel) {
561 return new AVRDAGToDAGISel(TM, OptLevel);
564 } // end of namespace llvm