1 //===-- AVRISelDAGToDAG.cpp - A dag to dag inst selector for AVR ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines an instruction selector for the AVR target.
11 //===----------------------------------------------------------------------===//
14 #include "AVRTargetMachine.h"
15 #include "MCTargetDesc/AVRMCTargetDesc.h"
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"
22 #define DEBUG_TYPE "avr-isel"
23 #define PASS_NAME "AVR DAG->DAG Instruction Selection"
29 /// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form).
30 class AVRDAGToDAGISel
: public SelectionDAGISel
{
34 AVRDAGToDAGISel() = delete;
36 AVRDAGToDAGISel(AVRTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
37 : SelectionDAGISel(ID
, TM
, OptLevel
), Subtarget(nullptr) {}
39 bool runOnMachineFunction(MachineFunction
&MF
) override
;
41 bool SelectAddr(SDNode
*Op
, SDValue N
, SDValue
&Base
, SDValue
&Disp
);
43 bool selectIndexedLoad(SDNode
*N
);
44 unsigned selectIndexedProgMemLoad(const LoadSDNode
*LD
, MVT VT
, int Bank
);
46 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
,
47 InlineAsm::ConstraintCode ConstraintCode
,
48 std::vector
<SDValue
> &OutOps
) override
;
50 // Include the pieces autogenerated from the target description.
51 #include "AVRGenDAGISel.inc"
54 void Select(SDNode
*N
) override
;
55 bool trySelect(SDNode
*N
);
57 template <unsigned NodeType
> bool select(SDNode
*N
);
58 bool selectMultiplication(SDNode
*N
);
60 const AVRSubtarget
*Subtarget
;
65 char AVRDAGToDAGISel::ID
= 0;
67 INITIALIZE_PASS(AVRDAGToDAGISel
, DEBUG_TYPE
, PASS_NAME
, false, false)
69 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
70 Subtarget
= &MF
.getSubtarget
<AVRSubtarget
>();
71 return SelectionDAGISel::runOnMachineFunction(MF
);
74 bool AVRDAGToDAGISel::SelectAddr(SDNode
*Op
, SDValue N
, SDValue
&Base
,
77 auto DL
= CurDAG
->getDataLayout();
78 MVT PtrVT
= getTargetLowering()->getPointerTy(DL
);
80 // if the address is a frame index get the TargetFrameIndex.
81 if (const FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(N
)) {
82 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), PtrVT
);
83 Disp
= CurDAG
->getTargetConstant(0, dl
, MVT::i8
);
88 // Match simple Reg + uimm6 operands.
89 if (N
.getOpcode() != ISD::ADD
&& N
.getOpcode() != ISD::SUB
&&
90 !CurDAG
->isBaseWithConstantOffset(N
)) {
94 if (const ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(N
.getOperand(1))) {
95 int RHSC
= (int)RHS
->getZExtValue();
97 // Convert negative offsets into positives ones.
98 if (N
.getOpcode() == ISD::SUB
) {
102 // <#Frame index + const>
103 // Allow folding offsets bigger than 63 so the frame pointer can be used
104 // directly instead of copying it around by adjusting and restoring it for
106 if (N
.getOperand(0).getOpcode() == ISD::FrameIndex
) {
107 int FI
= cast
<FrameIndexSDNode
>(N
.getOperand(0))->getIndex();
109 Base
= CurDAG
->getTargetFrameIndex(FI
, PtrVT
);
110 Disp
= CurDAG
->getTargetConstant(RHSC
, dl
, MVT::i16
);
115 // The value type of the memory instruction determines what is the maximum
117 MVT VT
= cast
<MemSDNode
>(Op
)->getMemoryVT().getSimpleVT();
119 // We only accept offsets that fit in 6 bits (unsigned).
120 if (isUInt
<6>(RHSC
) && (VT
== MVT::i8
|| VT
== MVT::i16
)) {
121 Base
= N
.getOperand(0);
122 Disp
= CurDAG
->getTargetConstant(RHSC
, dl
, MVT::i8
);
131 bool AVRDAGToDAGISel::selectIndexedLoad(SDNode
*N
) {
132 const LoadSDNode
*LD
= cast
<LoadSDNode
>(N
);
133 ISD::MemIndexedMode AM
= LD
->getAddressingMode();
134 MVT VT
= LD
->getMemoryVT().getSimpleVT();
135 auto PtrVT
= getTargetLowering()->getPointerTy(CurDAG
->getDataLayout());
137 // We only care if this load uses a POSTINC or PREDEC mode.
138 if ((LD
->getExtensionType() != ISD::NON_EXTLOAD
) ||
139 (AM
!= ISD::POST_INC
&& AM
!= ISD::PRE_DEC
)) {
145 bool isPre
= (AM
== ISD::PRE_DEC
);
146 int Offs
= cast
<ConstantSDNode
>(LD
->getOffset())->getSExtValue();
148 switch (VT
.SimpleTy
) {
150 if ((!isPre
&& Offs
!= 1) || (isPre
&& Offs
!= -1)) {
154 Opcode
= (isPre
) ? AVR::LDRdPtrPd
: AVR::LDRdPtrPi
;
158 if ((!isPre
&& Offs
!= 2) || (isPre
&& Offs
!= -2)) {
162 Opcode
= (isPre
) ? AVR::LDWRdPtrPd
: AVR::LDWRdPtrPi
;
170 CurDAG
->getMachineNode(Opcode
, SDLoc(N
), VT
, PtrVT
, MVT::Other
,
171 LD
->getBasePtr(), LD
->getChain());
172 ReplaceUses(N
, ResNode
);
173 CurDAG
->RemoveDeadNode(N
);
178 unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode
*LD
, MVT VT
,
180 // Progmem indexed loads only work in POSTINC mode.
181 if (LD
->getExtensionType() != ISD::NON_EXTLOAD
||
182 LD
->getAddressingMode() != ISD::POST_INC
)
185 // Feature ELPM is needed for loading from extended program memory.
186 assert((Bank
== 0 || Subtarget
->hasELPM()) &&
187 "cannot load from extended program memory on this mcu");
190 int Offs
= cast
<ConstantSDNode
>(LD
->getOffset())->getSExtValue();
192 if (VT
.SimpleTy
== MVT::i8
&& Offs
== 1 && Bank
== 0)
193 Opcode
= AVR::LPMRdZPi
;
195 // TODO: Implements the expansion of the following pseudo instructions.
196 // LPMWRdZPi: type == MVT::i16, offset == 2, Bank == 0.
197 // ELPMBRdZPi: type == MVT::i8, offset == 1, Bank > 0.
198 // ELPMWRdZPi: type == MVT::i16, offset == 2, Bank > 0.
203 bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(
204 const SDValue
&Op
, InlineAsm::ConstraintCode ConstraintCode
,
205 std::vector
<SDValue
> &OutOps
) {
206 assert((ConstraintCode
== InlineAsm::ConstraintCode::m
||
207 ConstraintCode
== InlineAsm::ConstraintCode::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
= ImmNode
&& ImmNode
->getAPIntValue().ult(64);
248 if (CopyFromRegOp
->getOpcode() == ISD::CopyFromReg
) {
249 RegisterSDNode
*RegNode
=
250 cast
<RegisterSDNode
>(CopyFromRegOp
->getOperand(1));
251 Reg
= RegNode
->getReg();
252 CanHandleRegImmOpt
&= (Register::isVirtualRegister(Reg
) ||
253 AVR::PTRDISPREGSRegClass
.contains(Reg
));
255 CanHandleRegImmOpt
= false;
258 // If we detect proper case - correct virtual register class
259 // if needed and go to another inlineasm operand.
260 if (CanHandleRegImmOpt
) {
263 if (RI
.getRegClass(Reg
) != &AVR::PTRDISPREGSRegClass
) {
264 SDLoc
dl(CopyFromRegOp
);
266 Register VReg
= RI
.createVirtualRegister(&AVR::PTRDISPREGSRegClass
);
269 CurDAG
->getCopyToReg(CopyFromRegOp
, dl
, VReg
, CopyFromRegOp
);
271 SDValue NewCopyFromRegOp
=
272 CurDAG
->getCopyFromReg(CopyToReg
, dl
, VReg
, TL
.getPointerTy(DL
));
274 Base
= NewCopyFromRegOp
;
276 Base
= CopyFromRegOp
;
279 if (ImmNode
->getValueType(0) != MVT::i8
) {
280 Disp
= CurDAG
->getTargetConstant(ImmNode
->getZExtValue(), dl
, MVT::i8
);
285 OutOps
.push_back(Base
);
286 OutOps
.push_back(Disp
);
292 // More generic case.
293 // Create chain that puts Op into pointer register
294 // and return that register.
295 Register VReg
= RI
.createVirtualRegister(&AVR::PTRDISPREGSRegClass
);
297 SDValue CopyToReg
= CurDAG
->getCopyToReg(Op
, dl
, VReg
, Op
);
298 SDValue CopyFromReg
=
299 CurDAG
->getCopyFromReg(CopyToReg
, dl
, VReg
, TL
.getPointerTy(DL
));
301 OutOps
.push_back(CopyFromReg
);
306 template <> bool AVRDAGToDAGISel::select
<ISD::FrameIndex
>(SDNode
*N
) {
307 auto DL
= CurDAG
->getDataLayout();
309 // Convert the frameindex into a temp instruction that will hold the
310 // effective address of the final stack slot.
311 int FI
= cast
<FrameIndexSDNode
>(N
)->getIndex();
313 CurDAG
->getTargetFrameIndex(FI
, getTargetLowering()->getPointerTy(DL
));
315 CurDAG
->SelectNodeTo(N
, AVR::FRMIDX
, getTargetLowering()->getPointerTy(DL
),
316 TFI
, CurDAG
->getTargetConstant(0, SDLoc(N
), MVT::i16
));
320 template <> bool AVRDAGToDAGISel::select
<ISD::STORE
>(SDNode
*N
) {
321 // Use the STD{W}SPQRr pseudo instruction when passing arguments through
322 // the stack on function calls for further expansion during the PEI phase.
323 const StoreSDNode
*ST
= cast
<StoreSDNode
>(N
);
324 SDValue BasePtr
= ST
->getBasePtr();
326 // Early exit when the base pointer is a frame index node or a constant.
327 if (isa
<FrameIndexSDNode
>(BasePtr
) || isa
<ConstantSDNode
>(BasePtr
) ||
332 const RegisterSDNode
*RN
= dyn_cast
<RegisterSDNode
>(BasePtr
.getOperand(0));
333 // Only stores where SP is the base pointer are valid.
334 if (!RN
|| (RN
->getReg() != AVR::SP
)) {
338 int CST
= (int)cast
<ConstantSDNode
>(BasePtr
.getOperand(1))->getZExtValue();
339 SDValue Chain
= ST
->getChain();
340 EVT VT
= ST
->getValue().getValueType();
342 SDValue Offset
= CurDAG
->getTargetConstant(CST
, DL
, MVT::i16
);
343 SDValue Ops
[] = {BasePtr
.getOperand(0), Offset
, ST
->getValue(), Chain
};
344 unsigned Opc
= (VT
== MVT::i16
) ? AVR::STDWSPQRr
: AVR::STDSPQRr
;
346 SDNode
*ResNode
= CurDAG
->getMachineNode(Opc
, DL
, MVT::Other
, Ops
);
348 // Transfer memory operands.
349 CurDAG
->setNodeMemRefs(cast
<MachineSDNode
>(ResNode
), {ST
->getMemOperand()});
351 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
352 CurDAG
->RemoveDeadNode(N
);
357 template <> bool AVRDAGToDAGISel::select
<ISD::LOAD
>(SDNode
*N
) {
358 const LoadSDNode
*LD
= cast
<LoadSDNode
>(N
);
359 if (!AVR::isProgramMemoryAccess(LD
)) {
360 // Check if the opcode can be converted into an indexed load.
361 return selectIndexedLoad(N
);
364 if (!Subtarget
->hasLPM())
365 report_fatal_error("cannot load from program memory on this mcu");
367 int ProgMemBank
= AVR::getProgramMemoryBank(LD
);
368 if (ProgMemBank
< 0 || ProgMemBank
> 5)
369 report_fatal_error("unexpected program memory bank");
370 if (ProgMemBank
> 0 && !Subtarget
->hasELPM())
371 report_fatal_error("unexpected program memory bank");
373 // This is a flash memory load, move the pointer into R31R30 and emit
374 // the lpm instruction.
375 MVT VT
= LD
->getMemoryVT().getSimpleVT();
376 SDValue Chain
= LD
->getChain();
377 SDValue Ptr
= LD
->getBasePtr();
381 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, Ptr
, SDValue());
382 Ptr
= CurDAG
->getCopyFromReg(Chain
, DL
, AVR::R31R30
, MVT::i16
,
385 // Check if the opcode can be converted into an indexed load.
386 if (unsigned LPMOpc
= selectIndexedProgMemLoad(LD
, VT
, ProgMemBank
)) {
387 // It is legal to fold the load into an indexed load.
388 if (ProgMemBank
== 0) {
390 CurDAG
->getMachineNode(LPMOpc
, DL
, VT
, MVT::i16
, MVT::Other
, Ptr
);
392 // Do not combine the LDI instruction into the ELPM pseudo instruction,
393 // since it may be reused by other ELPM pseudo instructions.
394 SDValue NC
= CurDAG
->getTargetConstant(ProgMemBank
, DL
, MVT::i8
);
395 auto *NP
= CurDAG
->getMachineNode(AVR::LDIRdK
, DL
, MVT::i8
, NC
);
396 ResNode
= CurDAG
->getMachineNode(LPMOpc
, DL
, VT
, MVT::i16
, MVT::Other
,
397 Ptr
, SDValue(NP
, 0));
400 // Selecting an indexed load is not legal, fallback to a normal load.
401 switch (VT
.SimpleTy
) {
403 if (ProgMemBank
== 0) {
404 unsigned Opc
= Subtarget
->hasLPMX() ? AVR::LPMRdZ
: AVR::LPMBRdZ
;
406 CurDAG
->getMachineNode(Opc
, DL
, MVT::i8
, MVT::Other
, Ptr
);
408 // Do not combine the LDI instruction into the ELPM pseudo instruction,
409 // since it may be reused by other ELPM pseudo instructions.
410 SDValue NC
= CurDAG
->getTargetConstant(ProgMemBank
, DL
, MVT::i8
);
411 auto *NP
= CurDAG
->getMachineNode(AVR::LDIRdK
, DL
, MVT::i8
, NC
);
412 ResNode
= CurDAG
->getMachineNode(AVR::ELPMBRdZ
, DL
, MVT::i8
, MVT::Other
,
413 Ptr
, SDValue(NP
, 0));
417 if (ProgMemBank
== 0) {
419 CurDAG
->getMachineNode(AVR::LPMWRdZ
, DL
, MVT::i16
, MVT::Other
, Ptr
);
421 // Do not combine the LDI instruction into the ELPM pseudo instruction,
422 // since LDI requires the destination register in range R16~R31.
423 SDValue NC
= CurDAG
->getTargetConstant(ProgMemBank
, DL
, MVT::i8
);
424 auto *NP
= CurDAG
->getMachineNode(AVR::LDIRdK
, DL
, MVT::i8
, NC
);
425 ResNode
= CurDAG
->getMachineNode(AVR::ELPMWRdZ
, DL
, MVT::i16
,
426 MVT::Other
, Ptr
, SDValue(NP
, 0));
430 llvm_unreachable("Unsupported VT!");
434 // Transfer memory operands.
435 CurDAG
->setNodeMemRefs(cast
<MachineSDNode
>(ResNode
), {LD
->getMemOperand()});
437 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
438 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
439 CurDAG
->RemoveDeadNode(N
);
444 template <> bool AVRDAGToDAGISel::select
<AVRISD::CALL
>(SDNode
*N
) {
446 SDValue Chain
= N
->getOperand(0);
447 SDValue Callee
= N
->getOperand(1);
448 unsigned LastOpNum
= N
->getNumOperands() - 1;
450 // Direct calls are autogenerated.
451 unsigned Op
= Callee
.getOpcode();
452 if (Op
== ISD::TargetGlobalAddress
|| Op
== ISD::TargetExternalSymbol
) {
456 // Skip the incoming flag if present
457 if (N
->getOperand(LastOpNum
).getValueType() == MVT::Glue
) {
462 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, Callee
, InGlue
);
463 SmallVector
<SDValue
, 8> Ops
;
464 Ops
.push_back(CurDAG
->getRegister(AVR::R31R30
, MVT::i16
));
466 // Map all operands into the new node.
467 for (unsigned i
= 2, e
= LastOpNum
+ 1; i
!= e
; ++i
) {
468 Ops
.push_back(N
->getOperand(i
));
471 Ops
.push_back(Chain
);
472 Ops
.push_back(Chain
.getValue(1));
474 SDNode
*ResNode
= CurDAG
->getMachineNode(
475 Subtarget
->hasEIJMPCALL() ? AVR::EICALL
: AVR::ICALL
, DL
, MVT::Other
,
478 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
479 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
480 CurDAG
->RemoveDeadNode(N
);
485 template <> bool AVRDAGToDAGISel::select
<ISD::BRIND
>(SDNode
*N
) {
486 SDValue Chain
= N
->getOperand(0);
487 SDValue JmpAddr
= N
->getOperand(1);
490 // Move the destination address of the indirect branch into R31R30.
491 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, JmpAddr
);
492 SDNode
*ResNode
= CurDAG
->getMachineNode(AVR::IJMP
, DL
, MVT::Other
, Chain
);
494 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
495 CurDAG
->RemoveDeadNode(N
);
500 bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode
*N
) {
502 MVT Type
= N
->getSimpleValueType(0);
504 assert(Type
== MVT::i8
&& "unexpected value type");
506 bool isSigned
= N
->getOpcode() == ISD::SMUL_LOHI
;
507 unsigned MachineOp
= isSigned
? AVR::MULSRdRr
: AVR::MULRdRr
;
509 SDValue Lhs
= N
->getOperand(0);
510 SDValue Rhs
= N
->getOperand(1);
511 SDNode
*Mul
= CurDAG
->getMachineNode(MachineOp
, DL
, MVT::Glue
, Lhs
, Rhs
);
512 SDValue InChain
= CurDAG
->getEntryNode();
513 SDValue InGlue
= SDValue(Mul
, 0);
515 // Copy the low half of the result, if it is needed.
516 if (N
->hasAnyUseOfValue(0)) {
518 CurDAG
->getCopyFromReg(InChain
, DL
, AVR::R0
, Type
, InGlue
);
520 ReplaceUses(SDValue(N
, 0), CopyFromLo
);
522 InChain
= CopyFromLo
.getValue(1);
523 InGlue
= CopyFromLo
.getValue(2);
526 // Copy the high half of the result, if it is needed.
527 if (N
->hasAnyUseOfValue(1)) {
529 CurDAG
->getCopyFromReg(InChain
, DL
, AVR::R1
, Type
, InGlue
);
531 ReplaceUses(SDValue(N
, 1), CopyFromHi
);
533 InChain
= CopyFromHi
.getValue(1);
534 InGlue
= CopyFromHi
.getValue(2);
537 CurDAG
->RemoveDeadNode(N
);
539 // We need to clear R1. This is currently done (dirtily)
540 // using a custom inserter.
545 void AVRDAGToDAGISel::Select(SDNode
*N
) {
546 // If we have a custom node, we already have selected!
547 if (N
->isMachineOpcode()) {
548 LLVM_DEBUG(errs() << "== "; N
->dump(CurDAG
); errs() << "\n");
553 // See if subclasses can handle this node.
557 // Select the default instruction
561 bool AVRDAGToDAGISel::trySelect(SDNode
*N
) {
562 unsigned Opcode
= N
->getOpcode();
566 // Nodes we fully handle.
567 case ISD::FrameIndex
:
568 return select
<ISD::FrameIndex
>(N
);
570 return select
<ISD::BRIND
>(N
);
573 return selectMultiplication(N
);
575 // Nodes we handle partially. Other cases are autogenerated
577 return select
<ISD::STORE
>(N
);
579 return select
<ISD::LOAD
>(N
);
581 return select
<AVRISD::CALL
>(N
);
587 FunctionPass
*llvm::createAVRISelDag(AVRTargetMachine
&TM
,
588 CodeGenOptLevel OptLevel
) {
589 return new AVRDAGToDAGISel(TM
, OptLevel
);