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"
26 /// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form).
27 class AVRDAGToDAGISel
: public SelectionDAGISel
{
29 AVRDAGToDAGISel(AVRTargetMachine
&TM
, CodeGenOpt::Level OptLevel
)
30 : SelectionDAGISel(TM
, OptLevel
), Subtarget(nullptr) {}
32 StringRef
getPassName() const override
{
33 return "AVR DAG->DAG Instruction Selection";
36 bool runOnMachineFunction(MachineFunction
&MF
) override
;
38 bool SelectAddr(SDNode
*Op
, SDValue N
, SDValue
&Base
, SDValue
&Disp
);
40 bool selectIndexedLoad(SDNode
*N
);
41 unsigned selectIndexedProgMemLoad(const LoadSDNode
*LD
, MVT VT
);
43 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
, unsigned ConstraintCode
,
44 std::vector
<SDValue
> &OutOps
) override
;
46 // Include the pieces autogenerated from the target description.
47 #include "AVRGenDAGISel.inc"
50 void Select(SDNode
*N
) override
;
51 bool trySelect(SDNode
*N
);
53 template <unsigned NodeType
> bool select(SDNode
*N
);
54 bool selectMultiplication(SDNode
*N
);
56 const AVRSubtarget
*Subtarget
;
59 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction
&MF
) {
60 Subtarget
= &MF
.getSubtarget
<AVRSubtarget
>();
61 return SelectionDAGISel::runOnMachineFunction(MF
);
64 bool AVRDAGToDAGISel::SelectAddr(SDNode
*Op
, SDValue N
, SDValue
&Base
,
67 auto DL
= CurDAG
->getDataLayout();
68 MVT PtrVT
= getTargetLowering()->getPointerTy(DL
);
70 // if the address is a frame index get the TargetFrameIndex.
71 if (const FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(N
)) {
72 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), PtrVT
);
73 Disp
= CurDAG
->getTargetConstant(0, dl
, MVT::i8
);
78 // Match simple Reg + uimm6 operands.
79 if (N
.getOpcode() != ISD::ADD
&& N
.getOpcode() != ISD::SUB
&&
80 !CurDAG
->isBaseWithConstantOffset(N
)) {
84 if (const ConstantSDNode
*RHS
= dyn_cast
<ConstantSDNode
>(N
.getOperand(1))) {
85 int RHSC
= (int)RHS
->getZExtValue();
87 // Convert negative offsets into positives ones.
88 if (N
.getOpcode() == ISD::SUB
) {
92 // <#Frame index + const>
93 // Allow folding offsets bigger than 63 so the frame pointer can be used
94 // directly instead of copying it around by adjusting and restoring it for
96 if (N
.getOperand(0).getOpcode() == ISD::FrameIndex
) {
97 int FI
= cast
<FrameIndexSDNode
>(N
.getOperand(0))->getIndex();
99 Base
= CurDAG
->getTargetFrameIndex(FI
, PtrVT
);
100 Disp
= CurDAG
->getTargetConstant(RHSC
, dl
, MVT::i16
);
105 // The value type of the memory instruction determines what is the maximum
107 MVT VT
= cast
<MemSDNode
>(Op
)->getMemoryVT().getSimpleVT();
109 // We only accept offsets that fit in 6 bits (unsigned).
110 if (isUInt
<6>(RHSC
) && (VT
== MVT::i8
|| VT
== MVT::i16
)) {
111 Base
= N
.getOperand(0);
112 Disp
= CurDAG
->getTargetConstant(RHSC
, dl
, MVT::i8
);
121 bool AVRDAGToDAGISel::selectIndexedLoad(SDNode
*N
) {
122 const LoadSDNode
*LD
= cast
<LoadSDNode
>(N
);
123 ISD::MemIndexedMode AM
= LD
->getAddressingMode();
124 MVT VT
= LD
->getMemoryVT().getSimpleVT();
125 auto PtrVT
= getTargetLowering()->getPointerTy(CurDAG
->getDataLayout());
127 // We only care if this load uses a POSTINC or PREDEC mode.
128 if ((LD
->getExtensionType() != ISD::NON_EXTLOAD
) ||
129 (AM
!= ISD::POST_INC
&& AM
!= ISD::PRE_DEC
)) {
135 bool isPre
= (AM
== ISD::PRE_DEC
);
136 int Offs
= cast
<ConstantSDNode
>(LD
->getOffset())->getSExtValue();
138 switch (VT
.SimpleTy
) {
140 if ((!isPre
&& Offs
!= 1) || (isPre
&& Offs
!= -1)) {
144 Opcode
= (isPre
) ? AVR::LDRdPtrPd
: AVR::LDRdPtrPi
;
148 if ((!isPre
&& Offs
!= 2) || (isPre
&& Offs
!= -2)) {
152 Opcode
= (isPre
) ? AVR::LDWRdPtrPd
: AVR::LDWRdPtrPi
;
159 SDNode
*ResNode
= CurDAG
->getMachineNode(Opcode
, SDLoc(N
), VT
,
161 LD
->getBasePtr(), LD
->getChain());
162 ReplaceUses(N
, ResNode
);
163 CurDAG
->RemoveDeadNode(N
);
168 unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode
*LD
,
170 ISD::MemIndexedMode AM
= LD
->getAddressingMode();
172 // Progmem indexed loads only work in POSTINC mode.
173 if (LD
->getExtensionType() != ISD::NON_EXTLOAD
|| AM
!= ISD::POST_INC
) {
178 int Offs
= cast
<ConstantSDNode
>(LD
->getOffset())->getSExtValue();
180 switch (VT
.SimpleTy
) {
185 Opcode
= AVR::LPMRdZPi
;
192 Opcode
= AVR::LPMWRdZPi
;
202 bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue
&Op
,
203 unsigned ConstraintCode
,
204 std::vector
<SDValue
> &OutOps
) {
205 assert((ConstraintCode
== InlineAsm::Constraint_m
||
206 ConstraintCode
== InlineAsm::Constraint_Q
) &&
207 "Unexpected asm memory constraint");
209 MachineRegisterInfo
&RI
= MF
->getRegInfo();
210 const AVRSubtarget
&STI
= MF
->getSubtarget
<AVRSubtarget
>();
211 const TargetLowering
&TL
= *STI
.getTargetLowering();
213 auto DL
= CurDAG
->getDataLayout();
215 const RegisterSDNode
*RegNode
= dyn_cast
<RegisterSDNode
>(Op
);
217 // If address operand is of PTRDISPREGS class, all is OK, then.
219 RI
.getRegClass(RegNode
->getReg()) == &AVR::PTRDISPREGSRegClass
) {
220 OutOps
.push_back(Op
);
224 if (Op
->getOpcode() == ISD::FrameIndex
) {
227 if (SelectAddr(Op
.getNode(), Op
, Base
, Disp
)) {
228 OutOps
.push_back(Base
);
229 OutOps
.push_back(Disp
);
237 // If Op is add 'register, immediate' and
238 // register is either virtual register or register of PTRDISPREGSRegClass
239 if (Op
->getOpcode() == ISD::ADD
|| Op
->getOpcode() == ISD::SUB
) {
240 SDValue CopyFromRegOp
= Op
->getOperand(0);
241 SDValue ImmOp
= Op
->getOperand(1);
242 ConstantSDNode
*ImmNode
= dyn_cast
<ConstantSDNode
>(ImmOp
);
245 bool CanHandleRegImmOpt
= true;
247 CanHandleRegImmOpt
&= ImmNode
!= 0;
248 CanHandleRegImmOpt
&= ImmNode
->getAPIntValue().getZExtValue() < 64;
250 if (CopyFromRegOp
->getOpcode() == ISD::CopyFromReg
) {
251 RegisterSDNode
*RegNode
=
252 cast
<RegisterSDNode
>(CopyFromRegOp
->getOperand(1));
253 Reg
= RegNode
->getReg();
254 CanHandleRegImmOpt
&= (Register::isVirtualRegister(Reg
) ||
255 AVR::PTRDISPREGSRegClass
.contains(Reg
));
257 CanHandleRegImmOpt
= false;
260 // If we detect proper case - correct virtual register class
261 // if needed and go to another inlineasm operand.
262 if (CanHandleRegImmOpt
) {
265 if (RI
.getRegClass(Reg
) != &AVR::PTRDISPREGSRegClass
) {
266 SDLoc
dl(CopyFromRegOp
);
268 unsigned VReg
= RI
.createVirtualRegister(&AVR::PTRDISPREGSRegClass
);
271 CurDAG
->getCopyToReg(CopyFromRegOp
, dl
, VReg
, CopyFromRegOp
);
273 SDValue NewCopyFromRegOp
=
274 CurDAG
->getCopyFromReg(CopyToReg
, dl
, VReg
, TL
.getPointerTy(DL
));
276 Base
= NewCopyFromRegOp
;
278 Base
= CopyFromRegOp
;
281 if (ImmNode
->getValueType(0) != MVT::i8
) {
282 Disp
= CurDAG
->getTargetConstant(ImmNode
->getAPIntValue().getZExtValue(), dl
, MVT::i8
);
287 OutOps
.push_back(Base
);
288 OutOps
.push_back(Disp
);
294 // More generic case.
295 // Create chain that puts Op into pointer register
296 // and return that register.
297 unsigned VReg
= RI
.createVirtualRegister(&AVR::PTRDISPREGSRegClass
);
299 SDValue CopyToReg
= CurDAG
->getCopyToReg(Op
, dl
, VReg
, Op
);
300 SDValue CopyFromReg
=
301 CurDAG
->getCopyFromReg(CopyToReg
, dl
, VReg
, TL
.getPointerTy(DL
));
303 OutOps
.push_back(CopyFromReg
);
308 template <> bool AVRDAGToDAGISel::select
<ISD::FrameIndex
>(SDNode
*N
) {
309 auto DL
= CurDAG
->getDataLayout();
311 // Convert the frameindex into a temp instruction that will hold the
312 // effective address of the final stack slot.
313 int FI
= cast
<FrameIndexSDNode
>(N
)->getIndex();
315 CurDAG
->getTargetFrameIndex(FI
, getTargetLowering()->getPointerTy(DL
));
317 CurDAG
->SelectNodeTo(N
, AVR::FRMIDX
,
318 getTargetLowering()->getPointerTy(DL
), TFI
,
319 CurDAG
->getTargetConstant(0, SDLoc(N
), MVT::i16
));
323 template <> bool AVRDAGToDAGISel::select
<ISD::STORE
>(SDNode
*N
) {
324 // Use the STD{W}SPQRr pseudo instruction when passing arguments through
325 // the stack on function calls for further expansion during the PEI phase.
326 const StoreSDNode
*ST
= cast
<StoreSDNode
>(N
);
327 SDValue BasePtr
= ST
->getBasePtr();
329 // Early exit when the base pointer is a frame index node or a constant.
330 if (isa
<FrameIndexSDNode
>(BasePtr
) || isa
<ConstantSDNode
>(BasePtr
) ||
335 const RegisterSDNode
*RN
= dyn_cast
<RegisterSDNode
>(BasePtr
.getOperand(0));
336 // Only stores where SP is the base pointer are valid.
337 if (!RN
|| (RN
->getReg() != AVR::SP
)) {
341 int CST
= (int)cast
<ConstantSDNode
>(BasePtr
.getOperand(1))->getZExtValue();
342 SDValue Chain
= ST
->getChain();
343 EVT VT
= ST
->getValue().getValueType();
345 SDValue Offset
= CurDAG
->getTargetConstant(CST
, DL
, MVT::i16
);
346 SDValue Ops
[] = {BasePtr
.getOperand(0), Offset
, ST
->getValue(), Chain
};
347 unsigned Opc
= (VT
== MVT::i16
) ? AVR::STDWSPQRr
: AVR::STDSPQRr
;
349 SDNode
*ResNode
= CurDAG
->getMachineNode(Opc
, DL
, MVT::Other
, Ops
);
351 // Transfer memory operands.
352 CurDAG
->setNodeMemRefs(cast
<MachineSDNode
>(ResNode
), {ST
->getMemOperand()});
354 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
355 CurDAG
->RemoveDeadNode(N
);
360 template <> bool AVRDAGToDAGISel::select
<ISD::LOAD
>(SDNode
*N
) {
361 const LoadSDNode
*LD
= cast
<LoadSDNode
>(N
);
362 if (!AVR::isProgramMemoryAccess(LD
)) {
363 // Check if the opcode can be converted into an indexed load.
364 return selectIndexedLoad(N
);
367 assert(Subtarget
->hasLPM() && "cannot load from program memory on this mcu");
369 // This is a flash memory load, move the pointer into R31R30 and emit
370 // the lpm instruction.
371 MVT VT
= LD
->getMemoryVT().getSimpleVT();
372 SDValue Chain
= LD
->getChain();
373 SDValue Ptr
= LD
->getBasePtr();
377 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, Ptr
, SDValue());
378 Ptr
= CurDAG
->getCopyFromReg(Chain
, DL
, AVR::R31R30
, MVT::i16
,
381 SDValue RegZ
= CurDAG
->getRegister(AVR::R31R30
, MVT::i16
);
383 // Check if the opcode can be converted into an indexed load.
384 if (unsigned LPMOpc
= selectIndexedProgMemLoad(LD
, VT
)) {
385 // It is legal to fold the load into an indexed load.
386 ResNode
= CurDAG
->getMachineNode(LPMOpc
, DL
, VT
, MVT::i16
, MVT::Other
, Ptr
,
388 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
390 // Selecting an indexed load is not legal, fallback to a normal load.
391 switch (VT
.SimpleTy
) {
393 ResNode
= CurDAG
->getMachineNode(AVR::LPMRdZ
, DL
, MVT::i8
, MVT::Other
,
397 ResNode
= CurDAG
->getMachineNode(AVR::LPMWRdZ
, DL
, MVT::i16
,
398 MVT::Other
, Ptr
, RegZ
);
399 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
402 llvm_unreachable("Unsupported VT!");
406 // Transfer memory operands.
407 CurDAG
->setNodeMemRefs(cast
<MachineSDNode
>(ResNode
), {LD
->getMemOperand()});
409 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
410 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
411 CurDAG
->RemoveDeadNode(N
);
416 template <> bool AVRDAGToDAGISel::select
<AVRISD::CALL
>(SDNode
*N
) {
418 SDValue Chain
= N
->getOperand(0);
419 SDValue Callee
= N
->getOperand(1);
420 unsigned LastOpNum
= N
->getNumOperands() - 1;
422 // Direct calls are autogenerated.
423 unsigned Op
= Callee
.getOpcode();
424 if (Op
== ISD::TargetGlobalAddress
|| Op
== ISD::TargetExternalSymbol
) {
428 // Skip the incoming flag if present
429 if (N
->getOperand(LastOpNum
).getValueType() == MVT::Glue
) {
434 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, Callee
, InFlag
);
435 SmallVector
<SDValue
, 8> Ops
;
436 Ops
.push_back(CurDAG
->getRegister(AVR::R31R30
, MVT::i16
));
438 // Map all operands into the new node.
439 for (unsigned i
= 2, e
= LastOpNum
+ 1; i
!= e
; ++i
) {
440 Ops
.push_back(N
->getOperand(i
));
443 Ops
.push_back(Chain
);
444 Ops
.push_back(Chain
.getValue(1));
447 CurDAG
->getMachineNode(AVR::ICALL
, DL
, MVT::Other
, MVT::Glue
, Ops
);
449 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
450 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 1));
451 CurDAG
->RemoveDeadNode(N
);
456 template <> bool AVRDAGToDAGISel::select
<ISD::BRIND
>(SDNode
*N
) {
457 SDValue Chain
= N
->getOperand(0);
458 SDValue JmpAddr
= N
->getOperand(1);
461 // Move the destination address of the indirect branch into R31R30.
462 Chain
= CurDAG
->getCopyToReg(Chain
, DL
, AVR::R31R30
, JmpAddr
);
463 SDNode
*ResNode
= CurDAG
->getMachineNode(AVR::IJMP
, DL
, MVT::Other
, Chain
);
465 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 0));
466 CurDAG
->RemoveDeadNode(N
);
471 bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode
*N
) {
473 MVT Type
= N
->getSimpleValueType(0);
475 assert(Type
== MVT::i8
&& "unexpected value type");
477 bool isSigned
= N
->getOpcode() == ISD::SMUL_LOHI
;
478 unsigned MachineOp
= isSigned
? AVR::MULSRdRr
: AVR::MULRdRr
;
480 SDValue Lhs
= N
->getOperand(0);
481 SDValue Rhs
= N
->getOperand(1);
482 SDNode
*Mul
= CurDAG
->getMachineNode(MachineOp
, DL
, MVT::Glue
, Lhs
, Rhs
);
483 SDValue InChain
= CurDAG
->getEntryNode();
484 SDValue InGlue
= SDValue(Mul
, 0);
486 // Copy the low half of the result, if it is needed.
487 if (N
->hasAnyUseOfValue(0)) {
489 CurDAG
->getCopyFromReg(InChain
, DL
, AVR::R0
, Type
, InGlue
);
491 ReplaceUses(SDValue(N
, 0), CopyFromLo
);
493 InChain
= CopyFromLo
.getValue(1);
494 InGlue
= CopyFromLo
.getValue(2);
497 // Copy the high half of the result, if it is needed.
498 if (N
->hasAnyUseOfValue(1)) {
500 CurDAG
->getCopyFromReg(InChain
, DL
, AVR::R1
, Type
, InGlue
);
502 ReplaceUses(SDValue(N
, 1), CopyFromHi
);
504 InChain
= CopyFromHi
.getValue(1);
505 InGlue
= CopyFromHi
.getValue(2);
508 CurDAG
->RemoveDeadNode(N
);
510 // We need to clear R1. This is currently done (dirtily)
511 // using a custom inserter.
516 void AVRDAGToDAGISel::Select(SDNode
*N
) {
517 // If we have a custom node, we already have selected!
518 if (N
->isMachineOpcode()) {
519 LLVM_DEBUG(errs() << "== "; N
->dump(CurDAG
); errs() << "\n");
524 // See if subclasses can handle this node.
528 // Select the default instruction
532 bool AVRDAGToDAGISel::trySelect(SDNode
*N
) {
533 unsigned Opcode
= N
->getOpcode();
537 // Nodes we fully handle.
538 case ISD::FrameIndex
: return select
<ISD::FrameIndex
>(N
);
539 case ISD::BRIND
: return select
<ISD::BRIND
>(N
);
541 case ISD::SMUL_LOHI
: return selectMultiplication(N
);
543 // Nodes we handle partially. Other cases are autogenerated
544 case ISD::STORE
: return select
<ISD::STORE
>(N
);
545 case ISD::LOAD
: return select
<ISD::LOAD
>(N
);
546 case AVRISD::CALL
: return select
<AVRISD::CALL
>(N
);
547 default: return false;
551 FunctionPass
*createAVRISelDag(AVRTargetMachine
&TM
,
552 CodeGenOpt::Level OptLevel
) {
553 return new AVRDAGToDAGISel(TM
, OptLevel
);
556 } // end of namespace llvm