22 #define DEBUG_TYPE "avr-isel"
33 return "AVR DAG->DAG Instruction Selection";
44 std::vector<SDValue> &OutOps)
override;
47 #include "AVRGenDAGISel.inc"
50 void Select(
SDNode *
N)
override;
53 template <
unsigned NodeType>
bool select(
SDNode *
N);
54 bool selectMultiplication(
SDNode *
N);
85 int RHSC = (
int)
RHS->getZExtValue();
97 int FI = cast<FrameIndexSDNode>(
N.getOperand(0))->getIndex();
107 MVT VT = cast<MemSDNode>(
Op)->getMemoryVT().getSimpleVT();
111 Base =
N.getOperand(0);
124 MVT VT =
LD->getMemoryVT().getSimpleVT();
136 int Offs = cast<ConstantSDNode>(
LD->getOffset())->getSExtValue();
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;
161 LD->getBasePtr(),
LD->getChain());
177 "cannot load from extended program memory on this mcu");
180 int Offs = cast<ConstantSDNode>(
LD->getOffset())->getSExtValue();
185 Opcode = Bank > 0 ? AVR::ELPMBRdZPi : AVR::LPMRdZPi;
189 Opcode = Bank > 0 ? AVR::ELPMWRdZPi : AVR::LPMWRdZPi;
199 const SDValue &
Op,
unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
202 "Unexpected asm memory constraint");
215 OutOps.push_back(
Op);
223 OutOps.push_back(
Base);
224 OutOps.push_back(Disp);
235 SDValue CopyFromRegOp =
Op->getOperand(0);
244 cast<RegisterSDNode>(CopyFromRegOp->
getOperand(1));
247 AVR::PTRDISPREGSRegClass.contains(
Reg));
249 CanHandleRegImmOpt =
false;
254 if (CanHandleRegImmOpt) {
258 SDLoc dl(CopyFromRegOp);
268 Base = NewCopyFromRegOp;
270 Base = CopyFromRegOp;
280 OutOps.push_back(
Base);
281 OutOps.push_back(Disp);
301 template <>
bool AVRDAGToDAGISel::select<ISD::FrameIndex>(
SDNode *
N) {
302 auto DL = CurDAG->getDataLayout();
306 int FI = cast<FrameIndexSDNode>(
N)->getIndex();
308 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(
DL));
310 CurDAG->SelectNodeTo(
N, AVR::FRMIDX, getTargetLowering()->getPointerTy(
DL),
315 template <>
bool AVRDAGToDAGISel::select<ISD::STORE>(
SDNode *
N) {
322 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
329 if (!
RN || (
RN->getReg() != AVR::SP)) {
333 int CST = (
int)cast<ConstantSDNode>(BasePtr.getOperand(1))->getZExtValue();
335 EVT VT =
ST->getValue().getValueType();
338 SDValue Ops[] = {BasePtr.getOperand(0), Offset,
ST->getValue(), Chain};
339 unsigned Opc = (VT ==
MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr;
344 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {
ST->getMemOperand()});
347 CurDAG->RemoveDeadNode(
N);
352 template <>
bool AVRDAGToDAGISel::select<ISD::LOAD>(
SDNode *
N) {
356 return selectIndexedLoad(
N);
359 if (!Subtarget->hasLPM())
363 if (ProgMemBank < 0 || ProgMemBank > 5)
368 MVT VT =
LD->getMemoryVT().getSimpleVT();
374 Chain = CurDAG->getCopyToReg(Chain,
DL, AVR::R31R30, Ptr,
SDValue());
375 Ptr = CurDAG->getCopyFromReg(Chain,
DL, AVR::R31R30,
MVT::i16,
379 if (
unsigned LPMOpc = selectIndexedProgMemLoad(
LD, VT, ProgMemBank)) {
381 if (ProgMemBank == 0) {
388 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK,
DL,
MVT::i8,
NC);
396 if (ProgMemBank == 0) {
403 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK,
DL,
MVT::i8,
NC);
409 if (ProgMemBank == 0) {
416 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK,
DL,
MVT::i8,
NC);
417 ResNode = CurDAG->getMachineNode(AVR::ELPMWRdZ,
DL,
MVT::i16,
427 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {
LD->getMemOperand()});
431 CurDAG->RemoveDeadNode(
N);
436 template <>
bool AVRDAGToDAGISel::select<AVRISD::CALL>(
SDNode *
N) {
440 unsigned LastOpNum =
N->getNumOperands() - 1;
449 if (
N->getOperand(LastOpNum).getValueType() ==
MVT::Glue) {
454 Chain = CurDAG->getCopyToReg(Chain,
DL, AVR::R31R30,
Callee, InFlag);
456 Ops.push_back(CurDAG->getRegister(AVR::R31R30,
MVT::i16));
459 for (
unsigned i = 2,
e = LastOpNum + 1;
i !=
e; ++
i) {
460 Ops.push_back(
N->getOperand(
i));
463 Ops.push_back(Chain);
471 CurDAG->RemoveDeadNode(
N);
476 template <>
bool AVRDAGToDAGISel::select<ISD::BRIND>(
SDNode *
N) {
482 Chain = CurDAG->getCopyToReg(Chain,
DL, AVR::R31R30, JmpAddr);
486 CurDAG->RemoveDeadNode(
N);
491 bool AVRDAGToDAGISel::selectMultiplication(
llvm::SDNode *
N) {
493 MVT Type =
N->getSimpleValueType(0);
498 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
500 SDValue Lhs =
N->getOperand(0);
501 SDValue Rhs =
N->getOperand(1);
504 SDValue InGlue = SDValue(Mul, 0);
507 if (
N->hasAnyUseOfValue(0)) {
513 InChain = CopyFromLo.getValue(1);
514 InGlue = CopyFromLo.getValue(2);
518 if (
N->hasAnyUseOfValue(1)) {
524 InChain = CopyFromHi.getValue(1);
525 InGlue = CopyFromHi.getValue(2);
536 void AVRDAGToDAGISel::Select(SDNode *
N) {
538 if (
N->isMachineOpcode()) {
552 bool AVRDAGToDAGISel::trySelect(SDNode *
N) {
553 unsigned Opcode =
N->getOpcode();
559 return select<ISD::FrameIndex>(
N);
561 return select<ISD::BRIND>(
N);
564 return selectMultiplication(
N);
568 return select<ISD::STORE>(
N);
570 return select<ISD::LOAD>(
N);
572 return select<AVRISD::CALL>(
N);