22#define DEBUG_TYPE "avr-isel"
23#define PASS_NAME "AVR DAG->DAG Instruction Selection"
34 AVRDAGToDAGISel() =
delete;
43 bool selectIndexedLoad(
SDNode *
N);
44 unsigned selectIndexedProgMemLoad(
const LoadSDNode *LD,
MVT VT,
int Bank);
47 std::vector<SDValue> &OutOps)
override;
50#include "AVRGenDAGISel.inc"
56 template <
unsigned NodeType>
bool select(
SDNode *
N);
57 bool selectMultiplication(
SDNode *
N);
64char AVRDAGToDAGISel::ID = 0;
76 auto DL = CurDAG->getDataLayout();
77 MVT PtrVT = getTargetLowering()->getPointerTy(
DL);
81 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT);
82 Disp = CurDAG->getTargetConstant(0, dl,
MVT::i8);
89 !CurDAG->isBaseWithConstantOffset(
N)) {
93 if (
const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(
N.getOperand(1))) {
94 int RHSC = (int)
RHS->getZExtValue();
106 int FI = cast<FrameIndexSDNode>(
N.getOperand(0))->getIndex();
108 Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
109 Disp = CurDAG->getTargetConstant(RHSC, dl,
MVT::i16);
116 MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
120 Base =
N.getOperand(0);
121 Disp = CurDAG->getTargetConstant(RHSC, dl,
MVT::i8);
130bool AVRDAGToDAGISel::selectIndexedLoad(
SDNode *
N) {
133 MVT VT =
LD->getMemoryVT().getSimpleVT();
134 auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
145 int Offs = cast<ConstantSDNode>(
LD->getOffset())->getSExtValue();
149 if ((!isPre && Offs != 1) || (isPre && Offs != -1)) {
153 Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi;
157 if ((!isPre && Offs != 2) || (isPre && Offs != -2)) {
161 Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi;
170 LD->getBasePtr(),
LD->getChain());
171 ReplaceUses(
N, ResNode);
172 CurDAG->RemoveDeadNode(
N);
177unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(
const LoadSDNode *LD,
MVT VT,
185 assert((Bank == 0 || Subtarget->hasELPM()) &&
186 "cannot load from extended program memory on this mcu");
189 int Offs = cast<ConstantSDNode>(
LD->getOffset())->getSExtValue();
192 Opcode = AVR::LPMRdZPi;
202bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(
203 const SDValue &Op,
unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
206 "Unexpected asm memory constraint");
212 auto DL = CurDAG->getDataLayout();
219 OutOps.push_back(Op);
226 if (SelectAddr(
Op.getNode(), Op,
Base, Disp)) {
227 OutOps.push_back(
Base);
228 OutOps.push_back(Disp);
239 SDValue CopyFromRegOp =
Op->getOperand(0);
248 cast<RegisterSDNode>(CopyFromRegOp->
getOperand(1));
251 AVR::PTRDISPREGSRegClass.contains(Reg));
253 CanHandleRegImmOpt =
false;
258 if (CanHandleRegImmOpt) {
261 if (RI.
getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
262 SDLoc dl(CopyFromRegOp);
267 CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
270 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(
DL));
272 Base = NewCopyFromRegOp;
274 Base = CopyFromRegOp;
283 OutOps.push_back(
Base);
284 OutOps.push_back(Disp);
297 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(
DL));
299 OutOps.push_back(CopyFromReg);
304template <>
bool AVRDAGToDAGISel::select<ISD::FrameIndex>(
SDNode *
N) {
305 auto DL = CurDAG->getDataLayout();
309 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
311 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(
DL));
313 CurDAG->SelectNodeTo(
N, AVR::FRMIDX, getTargetLowering()->getPointerTy(
DL),
318template <>
bool AVRDAGToDAGISel::select<ISD::STORE>(
SDNode *
N) {
322 SDValue BasePtr = ST->getBasePtr();
325 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
330 const RegisterSDNode *RN = dyn_cast<RegisterSDNode>(BasePtr.getOperand(0));
332 if (!RN || (RN->getReg() != AVR::SP)) {
336 int CST = (int)cast<ConstantSDNode>(BasePtr.getOperand(1))->getZExtValue();
337 SDValue Chain = ST->getChain();
338 EVT VT = ST->getValue().getValueType();
341 SDValue Ops[] = {BasePtr.getOperand(0),
Offset, ST->getValue(), Chain};
342 unsigned Opc = (VT ==
MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr;
347 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {ST->getMemOperand()});
350 CurDAG->RemoveDeadNode(
N);
355template <>
bool AVRDAGToDAGISel::select<ISD::LOAD>(
SDNode *
N) {
359 return selectIndexedLoad(
N);
362 if (!Subtarget->hasLPM())
366 if (ProgMemBank < 0 || ProgMemBank > 5)
368 if (ProgMemBank > 0 && !Subtarget->hasELPM())
373 MVT VT = LD->getMemoryVT().getSimpleVT();
374 SDValue Chain = LD->getChain();
379 Chain = CurDAG->getCopyToReg(Chain,
DL, AVR::R31R30,
Ptr,
SDValue());
380 Ptr = CurDAG->getCopyFromReg(Chain,
DL, AVR::R31R30,
MVT::i16,
384 if (
unsigned LPMOpc = selectIndexedProgMemLoad(LD, VT, ProgMemBank)) {
386 if (ProgMemBank == 0) {
393 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK,
DL,
MVT::i8,
NC);
401 if (ProgMemBank == 0) {
402 unsigned Opc = Subtarget->hasLPMX() ? AVR::LPMRdZ : AVR::LPMBRdZ;
409 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK,
DL,
MVT::i8,
NC);
415 if (ProgMemBank == 0) {
422 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK,
DL,
MVT::i8,
NC);
423 ResNode = CurDAG->getMachineNode(AVR::ELPMWRdZ,
DL,
MVT::i16,
433 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()});
437 CurDAG->RemoveDeadNode(
N);
442template <>
bool AVRDAGToDAGISel::select<AVRISD::CALL>(
SDNode *
N) {
446 unsigned LastOpNum =
N->getNumOperands() - 1;
449 unsigned Op =
Callee.getOpcode();
455 if (
N->getOperand(LastOpNum).getValueType() ==
MVT::Glue) {
460 Chain = CurDAG->getCopyToReg(Chain,
DL, AVR::R31R30,
Callee, InFlag);
465 for (
unsigned i = 2, e = LastOpNum + 1; i != e; ++i) {
472 SDNode *ResNode = CurDAG->getMachineNode(
473 Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL,
DL,
MVT::Other,
478 CurDAG->RemoveDeadNode(
N);
483template <>
bool AVRDAGToDAGISel::select<ISD::BRIND>(
SDNode *
N) {
489 Chain = CurDAG->getCopyToReg(Chain,
DL, AVR::R31R30, JmpAddr);
493 CurDAG->RemoveDeadNode(
N);
500 MVT Type =
N->getSimpleValueType(0);
505 unsigned MachineOp =
isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
510 SDValue InChain = CurDAG->getEntryNode();
514 if (
N->hasAnyUseOfValue(0)) {
516 CurDAG->getCopyFromReg(InChain,
DL, AVR::R0,
Type, InGlue);
518 ReplaceUses(
SDValue(
N, 0), CopyFromLo);
525 if (
N->hasAnyUseOfValue(1)) {
527 CurDAG->getCopyFromReg(InChain,
DL, AVR::R1,
Type, InGlue);
529 ReplaceUses(
SDValue(
N, 1), CopyFromHi);
535 CurDAG->RemoveDeadNode(
N);
543void AVRDAGToDAGISel::Select(
SDNode *
N) {
545 if (
N->isMachineOpcode()) {
559bool AVRDAGToDAGISel::trySelect(
SDNode *
N) {
560 unsigned Opcode =
N->getOpcode();
571 return selectMultiplication(
N);
587 return new AVRDAGToDAGISel(
TM, OptLevel);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu AMDGPU Register Bank Select
bool AVRDAGToDAGISel::select< ISD::LOAD >(SDNode *N)
bool AVRDAGToDAGISel::select< ISD::FrameIndex >(SDNode *N)
bool AVRDAGToDAGISel::select< ISD::BRIND >(SDNode *N)
bool AVRDAGToDAGISel::select< AVRISD::CALL >(SDNode *N)
bool AVRDAGToDAGISel::select< ISD::STORE >(SDNode *N)
static bool isSigned(unsigned int Opcode)
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool ult(const APInt &RHS) const
Unsigned less than comparison.
A specific AVR target MCU.
const AVRTargetLowering * getTargetLowering() const override
A generic AVR implementation.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
FunctionPass class - This class is used to implement most global optimizations.
This class is used to represent ISD::LOAD nodes.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Wrapper class representing virtual and physical registers.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDValue getValue(unsigned R) const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
The instances of the Type class are immutable: once they are created, they are never changed.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ CALL
Represents an abstract call instruction, which includes a bunch of information.
bool isProgramMemoryAccess(MemSDNode const *N)
int getProgramMemoryBank(MemSDNode const *N)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Level
Code generation optimization level.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ BRIND
BRIND - Indirect branch.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createAVRISelDag(AVRTargetMachine &TM, CodeGenOpt::Level OptLevel)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.