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
{
32 AVRDAGToDAGISel() = delete;
34 AVRDAGToDAGISel(AVRTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
35 : SelectionDAGISel(TM
, OptLevel
), Subtarget(nullptr) {}
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
, int Bank
);
44 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
,
45 InlineAsm::ConstraintCode ConstraintCode
,
46 std::vector
<SDValue
> &OutOps
) override
;
48 // Include the pieces autogenerated from the target description.
49 #include "AVRGenDAGISel.inc"
52 void Select(SDNode
*N
) override
;
53 bool trySelect(SDNode
*N
);
55 template <unsigned NodeType
> bool select(SDNode
*N
);
56 bool selectMultiplication(SDNode
*N
);
58 const AVRSubtarget
*Subtarget
;
61 class AVRDAGToDAGISelLegacy
: public SelectionDAGISelLegacy
{
64 AVRDAGToDAGISelLegacy(AVRTargetMachine
&TM
, CodeGenOptLevel OptLevel
)
65 : SelectionDAGISelLegacy(
66 ID
, std::make_unique
<AVRDAGToDAGISel
>(TM
, OptLevel
)) {}
71 char AVRDAGToDAGISelLegacy::ID
= 0;
73 INITIALIZE_PASS(AVRDAGToDAGISelLegacy
, DEBUG_TYPE
, PASS_NAME
, false, false)
75 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
76 Subtarget
= &MF
.getSubtarget
<AVRSubtarget
>();
77 return SelectionDAGISel::runOnMachineFunction(MF
);
80 bool AVRDAGToDAGISel::SelectAddr(SDNode
*Op
, SDValue N
, SDValue
&Base
,
83 auto DL
= CurDAG
->getDataLayout();
84 MVT PtrVT
= getTargetLowering()->getPointerTy(DL
);
86 // if the address is a frame index get the TargetFrameIndex.
87 if (const FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(N
)) {
88 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), PtrVT
);
89 Disp
= CurDAG
->getTargetConstant(0, dl
, MVT::i8
);
94 // Match simple Reg + uimm6 operands.
95 if (N
.getOpcode() != ISD::ADD
&& N
.getOpcode() != ISD::SUB
&&
96 !CurDAG
->isBaseWithConstantOffset(N
)) {
100 if (const ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(N
.getOperand(1))) {
101 int RHSC
= (int)RHS
->getZExtValue();
103 // Convert negative offsets into positives ones.
104 if (N
.getOpcode() == ISD::SUB
) {
108 // <#Frame index + const>
109 // Allow folding offsets bigger than 63 so the frame pointer can be used
110 // directly instead of copying it around by adjusting and restoring it for
112 if (N
.getOperand(0).getOpcode() == ISD::FrameIndex
) {
113 int FI
= cast
<FrameIndexSDNode
>(N
.getOperand(0))->getIndex();
115 Base
= CurDAG
->getTargetFrameIndex(FI
, PtrVT
);
116 Disp
= CurDAG
->getTargetConstant(RHSC
, dl
, MVT::i16
);
121 // The value type of the memory instruction determines what is the maximum
123 MVT VT
= cast
<MemSDNode
>(Op
)->getMemoryVT().getSimpleVT();
125 // We only accept offsets that fit in 6 bits (unsigned), with the exception
126 // of 16-bit loads - those can only go up to 62, because we desugar them
127 // into a pair of 8-bit loads like `ldd rx, RHSC` + `ldd ry, RHSC + 1`.
128 bool OkI8
= VT
== MVT::i8
&& RHSC
<= 63;
129 bool OkI16
= VT
== MVT::i16
&& RHSC
<= 62;
132 Base
= N
.getOperand(0);
133 Disp
= CurDAG
->getTargetConstant(RHSC
, dl
, MVT::i8
);
142 bool AVRDAGToDAGISel::selectIndexedLoad(SDNode
*N
) {
143 const LoadSDNode
*LD
= cast
<LoadSDNode
>(N
);
144 ISD::MemIndexedMode AM
= LD
->getAddressingMode();
145 MVT VT
= LD
->getMemoryVT().getSimpleVT();
146 auto PtrVT
= getTargetLowering()->getPointerTy(CurDAG
->getDataLayout());
148 // We only care if this load uses a POSTINC or PREDEC mode.
149 if ((LD
->getExtensionType() != ISD::NON_EXTLOAD
) ||
150 (AM
!= ISD::POST_INC
&& AM
!= ISD::PRE_DEC
)) {
156 bool isPre
= (AM
== ISD::PRE_DEC
);
157 int Offs
= cast
<ConstantSDNode
>(LD
->getOffset())->getSExtValue();
159 switch (VT
.SimpleTy
) {
161 if ((!isPre
&& Offs
!= 1) || (isPre
&& Offs
!= -1)) {
165 Opcode
= (isPre
) ? AVR::LDRdPtrPd
: AVR::LDRdPtrPi
;
169 if ((!isPre
&& Offs
!= 2) || (isPre
&& Offs
!= -2)) {
173 Opcode
= (isPre
) ? AVR::LDWRdPtrPd
: AVR::LDWRdPtrPi
;
181 CurDAG
->getMachineNode(Opcode
, SDLoc(N
), VT
, PtrVT
, MVT::Other
,
182 LD
->getBasePtr(), LD
->getChain());
183 ReplaceUses(N
, ResNode
);
184 CurDAG
->RemoveDeadNode(N
);
189 unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode
*LD
, MVT VT
,
191 // Progmem indexed loads only work in POSTINC mode.
192 if (LD
->getExtensionType() != ISD::NON_EXTLOAD
||
193 LD
->getAddressingMode() != ISD::POST_INC
)
196 // Feature ELPM is needed for loading from extended program memory.
197 assert((Bank
== 0 || Subtarget
->hasELPM()) &&
198 "cannot load from extended program memory on this mcu");
201 int Offs
= cast
<ConstantSDNode
>(LD
->getOffset())->getSExtValue();
203 if (VT
.SimpleTy
== MVT::i8
&& Offs
== 1 && Bank
== 0)
204 Opcode
= AVR::LPMRdZPi
;
206 // TODO: Implements the expansion of the following pseudo instructions.
207 // LPMWRdZPi: type == MVT::i16, offset == 2, Bank == 0.
208 // ELPMBRdZPi: type == MVT::i8, offset == 1, Bank > 0.
209 // ELPMWRdZPi: type == MVT::i16, offset == 2, Bank > 0.
214 bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(
215 const SDValue
&Op
, InlineAsm::ConstraintCode ConstraintCode
,
216 std::vector
<SDValue
> &OutOps
) {
217 assert((ConstraintCode
== InlineAsm::ConstraintCode::m
||
218 ConstraintCode
== InlineAsm::ConstraintCode::Q
) &&
219 "Unexpected asm memory constraint");
221 MachineRegisterInfo
&RI
= MF
->getRegInfo();
222 const AVRSubtarget
&STI
= MF
->getSubtarget
<AVRSubtarget
>();
223 const TargetLowering
&TL
= *STI
.getTargetLowering();
225 auto DL
= CurDAG
->getDataLayout();
227 const RegisterSDNode
*RegNode
= dyn_cast
<RegisterSDNode
>(Op
);
229 // If address operand is of PTRDISPREGS class, all is OK, then.
231 RI
.getRegClass(RegNode
->getReg()) == &AVR::PTRDISPREGSRegClass
) {
232 OutOps
.push_back(Op
);
236 if (Op
->getOpcode() == ISD::FrameIndex
) {
239 if (SelectAddr(Op
.getNode(), Op
, Base
, Disp
)) {
240 OutOps
.push_back(Base
);
241 OutOps
.push_back(Disp
);
249 // If Op is add 'register, immediate' and
250 // register is either virtual register or register of PTRDISPREGSRegClass
251 if (Op
->getOpcode() == ISD::ADD
|| Op
->getOpcode() == ISD::SUB
) {
252 SDValue CopyFromRegOp
= Op
->getOperand(0);
253 SDValue ImmOp
= Op
->getOperand(1);
254 ConstantSDNode
*ImmNode
= dyn_cast
<ConstantSDNode
>(ImmOp
);
257 bool CanHandleRegImmOpt
= ImmNode
&& ImmNode
->getAPIntValue().ult(64);
259 if (CopyFromRegOp
->getOpcode() == ISD::CopyFromReg
) {
260 RegisterSDNode
*RegNode
=
261 cast
<RegisterSDNode
>(CopyFromRegOp
->getOperand(1));
262 Reg
= RegNode
->getReg();
263 CanHandleRegImmOpt
&= (Register::isVirtualRegister(Reg
) ||
264 AVR::PTRDISPREGSRegClass
.contains(Reg
));
266 CanHandleRegImmOpt
= false;
269 // If we detect proper case - correct virtual register class
270 // if needed and go to another inlineasm operand.
271 if (CanHandleRegImmOpt
) {
274 if (RI
.getRegClass(Reg
) != &AVR::PTRDISPREGSRegClass
) {
275 SDLoc
dl(CopyFromRegOp
);
277 Register VReg
= RI
.createVirtualRegister(&AVR::PTRDISPREGSRegClass
);
280 CurDAG
->getCopyToReg(CopyFromRegOp
, dl
, VReg
, CopyFromRegOp
);
282 SDValue NewCopyFromRegOp
=
283 CurDAG
->getCopyFromReg(CopyToReg
, dl
, VReg
, TL
.getPointerTy(DL
));
285 Base
= NewCopyFromRegOp
;
287 Base
= CopyFromRegOp
;
290 if (ImmNode
->getValueType(0) != MVT::i8
) {
291 Disp
= CurDAG
->getTargetConstant(ImmNode
->getZExtValue(), dl
, MVT::i8
);
296 OutOps
.push_back(Base
);
297 OutOps
.push_back(Disp
);
303 // More generic case.
304 // Create chain that puts Op into pointer register
305 // and return that register.
306 Register VReg
= RI
.createVirtualRegister(&AVR::PTRDISPREGSRegClass
);
308 SDValue CopyToReg
= CurDAG
->getCopyToReg(Op
, dl
, VReg
, Op
);
309 SDValue CopyFromReg
=
310 CurDAG
->getCopyFromReg(CopyToReg
, dl
, VReg
, TL
.getPointerTy(DL
));
312 OutOps
.push_back(CopyFromReg
);
317 template <> bool AVRDAGToDAGISel::select
<ISD::FrameIndex
>(SDNode
*N
) {
318 auto DL
= CurDAG
->getDataLayout();
320 // Convert the frameindex into a temp instruction that will hold the
321 // effective address of the final stack slot.
322 int FI
= cast
<FrameIndexSDNode
>(N
)->getIndex();
324 CurDAG
->getTargetFrameIndex(FI
, getTargetLowering()->getPointerTy(DL
));
326 CurDAG
->SelectNodeTo(N
, AVR::FRMIDX
, getTargetLowering()->getPointerTy(DL
),
327 TFI
, CurDAG
->getTargetConstant(0, SDLoc(N
), MVT::i16
));
331 template <> bool AVRDAGToDAGISel::select
<ISD::STORE
>(SDNode
*N
) {
332 // Use the STD{W}SPQRr pseudo instruction when passing arguments through
333 // the stack on function calls for further expansion during the PEI phase.
334 const StoreSDNode
*ST
= cast
<StoreSDNode
>(N
);
335 SDValue BasePtr
= ST
->getBasePtr();
337 // Early exit when the base pointer is a frame index node or a constant.
338 if (isa
<FrameIndexSDNode
>(BasePtr
) || isa
<ConstantSDNode
>(BasePtr
) ||
343 const RegisterSDNode
*RN
= dyn_cast
<RegisterSDNode
>(BasePtr
.getOperand(0));
344 // Only stores where SP is the base pointer are valid.
345 if (!RN
|| (RN
->getReg() != AVR::SP
)) {
349 int CST
= (int)BasePtr
.getConstantOperandVal(1);
350 SDValue Chain
= ST
->getChain();
351 EVT VT
= ST
->getValue().getValueType();
353 SDValue Offset
= CurDAG
->getTargetConstant(CST
, DL
, MVT::i16
);
354 SDValue Ops
[] = {BasePtr
.getOperand(0), Offset
, ST
->getValue(), Chain
};
355 unsigned Opc
= (VT
== MVT::i16
) ? AVR::STDWSPQRr
: AVR::STDSPQRr
;
357 SDNode
*ResNode
= CurDAG
->getMachineNode(Opc
, DL
, MVT::Other
, Ops
);
359 // Transfer memory operands.
360 CurDAG
->setNodeMemRefs(cast
<MachineSDNode
>(ResNode
), {ST
->getMemOperand()});
362 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
363 CurDAG
->RemoveDeadNode(N
);
368 template <> bool AVRDAGToDAGISel::select
<ISD::LOAD
>(SDNode
*N
) {
369 const LoadSDNode
*LD
= cast
<LoadSDNode
>(N
);
370 if (!AVR::isProgramMemoryAccess(LD
)) {
371 // Check if the opcode can be converted into an indexed load.
372 return selectIndexedLoad(N
);
375 if (!Subtarget
->hasLPM())
376 report_fatal_error("cannot load from program memory on this mcu");
378 int ProgMemBank
= AVR::getProgramMemoryBank(LD
);
379 if (ProgMemBank
< 0 || ProgMemBank
> 5)
380 report_fatal_error("unexpected program memory bank");
381 if (ProgMemBank
> 0 && !Subtarget
->hasELPM())
382 report_fatal_error("unexpected program memory bank");
384 // This is a flash memory load, move the pointer into R31R30 and emit
385 // the lpm instruction.
386 MVT VT
= LD
->getMemoryVT().getSimpleVT();
387 SDValue Chain
= LD
->getChain();
388 SDValue Ptr
= LD
->getBasePtr();
392 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, Ptr
, SDValue());
393 Ptr
= CurDAG
->getCopyFromReg(Chain
, DL
, AVR::R31R30
, MVT::i16
,
396 // Check if the opcode can be converted into an indexed load.
397 if (unsigned LPMOpc
= selectIndexedProgMemLoad(LD
, VT
, ProgMemBank
)) {
398 // It is legal to fold the load into an indexed load.
399 if (ProgMemBank
== 0) {
401 CurDAG
->getMachineNode(LPMOpc
, DL
, VT
, MVT::i16
, MVT::Other
, Ptr
);
403 // Do not combine the LDI instruction into the ELPM pseudo instruction,
404 // since it may be reused by other ELPM pseudo instructions.
405 SDValue NC
= CurDAG
->getTargetConstant(ProgMemBank
, DL
, MVT::i8
);
406 auto *NP
= CurDAG
->getMachineNode(AVR::LDIRdK
, DL
, MVT::i8
, NC
);
407 ResNode
= CurDAG
->getMachineNode(LPMOpc
, DL
, VT
, MVT::i16
, MVT::Other
,
408 Ptr
, SDValue(NP
, 0));
411 // Selecting an indexed load is not legal, fallback to a normal load.
412 switch (VT
.SimpleTy
) {
414 if (ProgMemBank
== 0) {
415 unsigned Opc
= Subtarget
->hasLPMX() ? AVR::LPMRdZ
: AVR::LPMBRdZ
;
417 CurDAG
->getMachineNode(Opc
, DL
, MVT::i8
, MVT::Other
, Ptr
);
419 // Do not combine the LDI instruction into the ELPM pseudo instruction,
420 // since it may be reused by other ELPM pseudo instructions.
421 SDValue NC
= CurDAG
->getTargetConstant(ProgMemBank
, DL
, MVT::i8
);
422 auto *NP
= CurDAG
->getMachineNode(AVR::LDIRdK
, DL
, MVT::i8
, NC
);
423 ResNode
= CurDAG
->getMachineNode(AVR::ELPMBRdZ
, DL
, MVT::i8
, MVT::Other
,
424 Ptr
, SDValue(NP
, 0));
428 if (ProgMemBank
== 0) {
430 CurDAG
->getMachineNode(AVR::LPMWRdZ
, DL
, MVT::i16
, MVT::Other
, Ptr
);
432 // Do not combine the LDI instruction into the ELPM pseudo instruction,
433 // since LDI requires the destination register in range R16~R31.
434 SDValue NC
= CurDAG
->getTargetConstant(ProgMemBank
, DL
, MVT::i8
);
435 auto *NP
= CurDAG
->getMachineNode(AVR::LDIRdK
, DL
, MVT::i8
, NC
);
436 ResNode
= CurDAG
->getMachineNode(AVR::ELPMWRdZ
, DL
, MVT::i16
,
437 MVT::Other
, Ptr
, SDValue(NP
, 0));
441 llvm_unreachable("Unsupported VT!");
445 // Transfer memory operands.
446 CurDAG
->setNodeMemRefs(cast
<MachineSDNode
>(ResNode
), {LD
->getMemOperand()});
448 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
449 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
450 CurDAG
->RemoveDeadNode(N
);
455 template <> bool AVRDAGToDAGISel::select
<AVRISD::CALL
>(SDNode
*N
) {
457 SDValue Chain
= N
->getOperand(0);
458 SDValue Callee
= N
->getOperand(1);
459 unsigned LastOpNum
= N
->getNumOperands() - 1;
461 // Direct calls are autogenerated.
462 unsigned Op
= Callee
.getOpcode();
463 if (Op
== ISD::TargetGlobalAddress
|| Op
== ISD::TargetExternalSymbol
) {
467 // Skip the incoming flag if present
468 if (N
->getOperand(LastOpNum
).getValueType() == MVT::Glue
) {
473 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, Callee
, InGlue
);
474 SmallVector
<SDValue
, 8> Ops
;
475 Ops
.push_back(CurDAG
->getRegister(AVR::R31R30
, MVT::i16
));
477 // Map all operands into the new node.
478 for (unsigned i
= 2, e
= LastOpNum
+ 1; i
!= e
; ++i
) {
479 Ops
.push_back(N
->getOperand(i
));
482 Ops
.push_back(Chain
);
483 Ops
.push_back(Chain
.getValue(1));
485 SDNode
*ResNode
= CurDAG
->getMachineNode(
486 Subtarget
->hasEIJMPCALL() ? AVR::EICALL
: AVR::ICALL
, DL
, MVT::Other
,
489 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
490 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
491 CurDAG
->RemoveDeadNode(N
);
496 template <> bool AVRDAGToDAGISel::select
<ISD::BRIND
>(SDNode
*N
) {
497 SDValue Chain
= N
->getOperand(0);
498 SDValue JmpAddr
= N
->getOperand(1);
501 // Move the destination address of the indirect branch into R31R30.
502 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, JmpAddr
);
503 SDNode
*ResNode
= CurDAG
->getMachineNode(AVR::IJMP
, DL
, MVT::Other
, Chain
);
505 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
506 CurDAG
->RemoveDeadNode(N
);
511 bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode
*N
) {
513 MVT Type
= N
->getSimpleValueType(0);
515 assert(Type
== MVT::i8
&& "unexpected value type");
517 bool isSigned
= N
->getOpcode() == ISD::SMUL_LOHI
;
518 unsigned MachineOp
= isSigned
? AVR::MULSRdRr
: AVR::MULRdRr
;
520 SDValue Lhs
= N
->getOperand(0);
521 SDValue Rhs
= N
->getOperand(1);
522 SDNode
*Mul
= CurDAG
->getMachineNode(MachineOp
, DL
, MVT::Glue
, Lhs
, Rhs
);
523 SDValue InChain
= CurDAG
->getEntryNode();
524 SDValue InGlue
= SDValue(Mul
, 0);
526 // Copy the low half of the result, if it is needed.
527 if (N
->hasAnyUseOfValue(0)) {
529 CurDAG
->getCopyFromReg(InChain
, DL
, AVR::R0
, Type
, InGlue
);
531 ReplaceUses(SDValue(N
, 0), CopyFromLo
);
533 InChain
= CopyFromLo
.getValue(1);
534 InGlue
= CopyFromLo
.getValue(2);
537 // Copy the high half of the result, if it is needed.
538 if (N
->hasAnyUseOfValue(1)) {
540 CurDAG
->getCopyFromReg(InChain
, DL
, AVR::R1
, Type
, InGlue
);
542 ReplaceUses(SDValue(N
, 1), CopyFromHi
);
544 InChain
= CopyFromHi
.getValue(1);
545 InGlue
= CopyFromHi
.getValue(2);
548 CurDAG
->RemoveDeadNode(N
);
550 // We need to clear R1. This is currently done (dirtily)
551 // using a custom inserter.
556 void AVRDAGToDAGISel::Select(SDNode
*N
) {
557 // If we have a custom node, we already have selected!
558 if (N
->isMachineOpcode()) {
559 LLVM_DEBUG(errs() << "== "; N
->dump(CurDAG
); errs() << "\n");
564 // See if subclasses can handle this node.
568 // Select the default instruction
572 bool AVRDAGToDAGISel::trySelect(SDNode
*N
) {
573 unsigned Opcode
= N
->getOpcode();
577 // Nodes we fully handle.
578 case ISD::FrameIndex
:
579 return select
<ISD::FrameIndex
>(N
);
581 return select
<ISD::BRIND
>(N
);
584 return selectMultiplication(N
);
586 // Nodes we handle partially. Other cases are autogenerated
588 return select
<ISD::STORE
>(N
);
590 return select
<ISD::LOAD
>(N
);
592 return select
<AVRISD::CALL
>(N
);
598 FunctionPass
*llvm::createAVRISelDag(AVRTargetMachine
&TM
,
599 CodeGenOptLevel OptLevel
) {
600 return new AVRDAGToDAGISelLegacy(TM
, OptLevel
);