LLVM 23.0.0git
AVRISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- AVRISelDAGToDAG.cpp - A dag to dag inst selector for AVR ----------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines an instruction selector for the AVR target.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AVR.h"
14#include "AVRTargetMachine.h"
16
19#include "llvm/Support/Debug.h"
21
22#define DEBUG_TYPE "avr-isel"
23#define PASS_NAME "AVR DAG->DAG Instruction Selection"
24
25using namespace llvm;
26
27namespace {
28
29/// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form).
30class AVRDAGToDAGISel : public SelectionDAGISel {
31public:
32 AVRDAGToDAGISel() = delete;
33
34 AVRDAGToDAGISel(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
35 : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
36
37 bool runOnMachineFunction(MachineFunction &MF) override;
38
39 bool SelectAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Disp);
40
41 bool selectIndexedLoad(SDNode *N);
42 unsigned selectIndexedProgMemLoad(const LoadSDNode *LD, MVT VT, int Bank);
43
44 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
45 InlineAsm::ConstraintCode ConstraintCode,
46 std::vector<SDValue> &OutOps) override;
47
48// Include the pieces autogenerated from the target description.
49#include "AVRGenDAGISel.inc"
50
51private:
52 void Select(SDNode *N) override;
53 bool trySelect(SDNode *N);
54
55 template <unsigned NodeType> bool select(SDNode *N);
56 bool selectMultiplication(SDNode *N);
57
58 const AVRSubtarget *Subtarget;
59};
60
61class AVRDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
62public:
63 static char ID;
64 AVRDAGToDAGISelLegacy(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
66 ID, std::make_unique<AVRDAGToDAGISel>(TM, OptLevel)) {}
67};
68
69} // namespace
70
71char AVRDAGToDAGISelLegacy::ID = 0;
72
73INITIALIZE_PASS(AVRDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
74
75bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
76 Subtarget = &MF.getSubtarget<AVRSubtarget>();
78}
79
80bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
81 SDValue &Disp) {
82 SDLoc dl(Op);
83 auto DL = CurDAG->getDataLayout();
84 MVT PtrVT = getTargetLowering()->getPointerTy(DL);
85
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);
90
91 return true;
92 }
93
94 // Match simple Reg + uimm6 operands.
95 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB &&
96 !CurDAG->isBaseWithConstantOffset(N)) {
97 return false;
98 }
99
100 if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
101 int RHSC = (int)RHS->getZExtValue();
102
103 // Convert negative offsets into positives ones.
104 if (N.getOpcode() == ISD::SUB) {
105 RHSC = -RHSC;
106 }
107
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
111 // each access.
112 if (N.getOperand(0).getOpcode() == ISD::FrameIndex) {
113 int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
114
115 Base = CurDAG->getTargetFrameIndex(FI, PtrVT);
116 Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i16);
117
118 return true;
119 }
120
121 // The value type of the memory instruction determines what is the maximum
122 // offset allowed.
123 MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
124
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;
130
131 if (OkI8 || OkI16) {
132 Base = N.getOperand(0);
133 Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
134
135 return true;
136 }
137 }
138
139 return false;
140}
141
142bool 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());
147
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)) {
151
152 return false;
153 }
154
155 unsigned Opcode = 0;
156 bool isPre = (AM == ISD::PRE_DEC);
157 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
158
159 switch (VT.SimpleTy) {
160 case MVT::i8: {
161 if ((!isPre && Offs != 1) || (isPre && Offs != -1)) {
162 return false;
163 }
164
165 Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi;
166 break;
167 }
168 case MVT::i16: {
169 if ((!isPre && Offs != 2) || (isPre && Offs != -2)) {
170 return false;
171 }
172
173 Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi;
174 break;
175 }
176 default:
177 return false;
178 }
179
180 SDNode *ResNode =
181 CurDAG->getMachineNode(Opcode, SDLoc(N), VT, PtrVT, MVT::Other,
182 LD->getBasePtr(), LD->getChain());
183 ReplaceUses(N, ResNode);
184 CurDAG->RemoveDeadNode(N);
185
186 return true;
187}
188
189unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode *LD, MVT VT,
190 int Bank) {
191 // Progmem indexed loads only work in POSTINC mode.
192 if (LD->getExtensionType() != ISD::NON_EXTLOAD ||
193 LD->getAddressingMode() != ISD::POST_INC)
194 return 0;
195
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");
199
200 unsigned Opcode = 0;
201 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
202
203 if (VT.SimpleTy == MVT::i8 && Offs == 1 && Bank == 0)
204 Opcode = AVR::LPMRdZPi;
205
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.
210
211 return Opcode;
212}
213
214bool 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");
220
221 MachineRegisterInfo &RI = MF->getRegInfo();
222 const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
223 const TargetLowering &TL = *STI.getTargetLowering();
224 SDLoc dl(Op);
225 auto DL = CurDAG->getDataLayout();
226
227 const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op);
228
229 // If address operand is of PTRDISPREGS class, all is OK, then.
230 if (RegNode &&
231 RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) {
232 OutOps.push_back(Op);
233 return false;
234 }
235
236 if (Op->getOpcode() == ISD::FrameIndex) {
237 SDValue Base, Disp;
238
239 if (SelectAddr(Op.getNode(), Op, Base, Disp)) {
240 OutOps.push_back(Base);
241 OutOps.push_back(Disp);
242
243 return false;
244 }
245
246 return true;
247 }
248
249 // Select global addresses.
250 if (Op.getOpcode() == AVRISD::WRAPPER) {
251 SDValue Sub = Op.getOperand(0);
252 if (Sub.getOpcode() == ISD::TargetGlobalAddress &&
253 (Sub.getValueType() == MVT::i16 || Sub.getValueType() == MVT::i8)) {
254 OutOps.push_back(Sub);
255 return false;
256 }
257 }
258
259 // If Op is add 'register, immediate' and
260 // register is either virtual register or register of PTRDISPREGSRegClass
261 if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) {
262 SDValue CopyFromRegOp = Op->getOperand(0);
263 SDValue ImmOp = Op->getOperand(1);
264 ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp);
265
266 unsigned Reg;
267 bool CanHandleRegImmOpt = ImmNode && ImmNode->getAPIntValue().ult(64);
268
269 if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) {
270 RegisterSDNode *RegNode =
271 cast<RegisterSDNode>(CopyFromRegOp->getOperand(1));
272 Reg = RegNode->getReg();
273 CanHandleRegImmOpt &= (Register::isVirtualRegister(Reg) ||
274 AVR::PTRDISPREGSRegClass.contains(Reg));
275 } else {
276 CanHandleRegImmOpt = false;
277 }
278
279 // If we detect proper case - correct virtual register class
280 // if needed and go to another inlineasm operand.
281 if (CanHandleRegImmOpt) {
282 SDValue Base, Disp;
283
284 if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
285 SDLoc dl(CopyFromRegOp);
286
287 Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
288
290 CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
291
292 SDValue NewCopyFromRegOp =
293 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
294
295 Base = NewCopyFromRegOp;
296 } else {
297 Base = CopyFromRegOp;
298 }
299
300 if (ImmNode->getValueType(0) != MVT::i8) {
301 Disp = CurDAG->getTargetConstant(ImmNode->getZExtValue(), dl, MVT::i8);
302 } else {
303 Disp = ImmOp;
304 }
305
306 OutOps.push_back(Base);
307 OutOps.push_back(Disp);
308
309 return false;
310 }
311 }
312
313 // More generic case.
314 // Create chain that puts Op into pointer register
315 // and return that register.
316 Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
317
318 SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
320 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
321
322 OutOps.push_back(CopyFromReg);
323
324 return false;
325}
326
327template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) {
328 auto DL = CurDAG->getDataLayout();
329
330 // Convert the frameindex into a temp instruction that will hold the
331 // effective address of the final stack slot.
332 int FI = cast<FrameIndexSDNode>(N)->getIndex();
333 SDValue TFI =
334 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
335
336 CurDAG->SelectNodeTo(N, AVR::FRMIDX, getTargetLowering()->getPointerTy(DL),
337 TFI, CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16));
338 return true;
339}
340
341template <> bool AVRDAGToDAGISel::select<ISD::STORE>(SDNode *N) {
342 // Use the STD{W}SPQRr pseudo instruction when passing arguments through
343 // the stack on function calls for further expansion during the PEI phase.
344 const StoreSDNode *ST = cast<StoreSDNode>(N);
345 SDValue BasePtr = ST->getBasePtr();
346
347 // Early exit when the base pointer is a frame index node or a constant.
348 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
349 BasePtr.isUndef()) {
350 return false;
351 }
352
353 const RegisterSDNode *RN = dyn_cast<RegisterSDNode>(BasePtr.getOperand(0));
354 // Only stores where SP is the base pointer are valid.
355 if (!RN || (RN->getReg() != AVR::SP)) {
356 return false;
357 }
358
359 int CST = (int)BasePtr.getConstantOperandVal(1);
360 SDValue Chain = ST->getChain();
361 EVT VT = ST->getValue().getValueType();
362 SDLoc DL(N);
363 SDValue Offset = CurDAG->getTargetConstant(CST, DL, MVT::i16);
364 SDValue Ops[] = {BasePtr.getOperand(0), Offset, ST->getValue(), Chain};
365 unsigned Opc = (VT == MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr;
366
367 SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops);
368
369 // Transfer memory operands.
370 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {ST->getMemOperand()});
371
372 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
373 CurDAG->RemoveDeadNode(N);
374
375 return true;
376}
377
378template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) {
379 const LoadSDNode *LD = cast<LoadSDNode>(N);
381 // Check if the opcode can be converted into an indexed load.
382 return selectIndexedLoad(N);
383 }
384
385 if (!Subtarget->hasLPM())
386 report_fatal_error("cannot load from program memory on this mcu");
387
388 int ProgMemBank = AVR::getProgramMemoryBank(LD);
389 if (ProgMemBank < 0 || ProgMemBank > 5)
390 report_fatal_error("unexpected program memory bank");
391 if (ProgMemBank > 0 && !Subtarget->hasELPM())
392 report_fatal_error("unexpected program memory bank");
393
394 // This is a flash memory load, move the pointer into R31R30 and emit
395 // the lpm instruction.
396 MVT VT = LD->getMemoryVT().getSimpleVT();
397 SDValue Chain = LD->getChain();
398 SDValue Ptr = LD->getBasePtr();
399 SDNode *ResNode;
400 SDLoc DL(N);
401
402 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue());
403 Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16,
404 Chain.getValue(1));
405
406 // Check if the opcode can be converted into an indexed load.
407 if (unsigned LPMOpc = selectIndexedProgMemLoad(LD, VT, ProgMemBank)) {
408 // It is legal to fold the load into an indexed load.
409 if (ProgMemBank == 0) {
410 ResNode =
411 CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other, Ptr);
412 } else {
413 // Do not combine the LDI instruction into the ELPM pseudo instruction,
414 // since it may be reused by other ELPM pseudo instructions.
415 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
416 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
417 ResNode = CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other,
418 Ptr, SDValue(NP, 0));
419 }
420 } else {
421 // Selecting an indexed load is not legal, fallback to a normal load.
422 switch (VT.SimpleTy) {
423 case MVT::i8:
424 if (ProgMemBank == 0) {
425 unsigned Opc = Subtarget->hasLPMX() ? AVR::LPMRdZ : AVR::LPMBRdZ;
426 ResNode = CurDAG->getMachineNode(Opc, DL, MVT::i8, MVT::Other, Ptr);
427 } else {
428 // Do not combine the LDI instruction into the ELPM pseudo instruction,
429 // since it may be reused by other ELPM pseudo instructions.
430 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
431 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
432 ResNode = CurDAG->getMachineNode(AVR::ELPMBRdZ, DL, MVT::i8, MVT::Other,
433 Ptr, SDValue(NP, 0));
434 }
435 break;
436 case MVT::i16:
437 if (ProgMemBank == 0) {
438 ResNode =
439 CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16, MVT::Other, Ptr);
440 } else {
441 // Do not combine the LDI instruction into the ELPM pseudo instruction,
442 // since LDI requires the destination register in range R16~R31.
443 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
444 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
445 ResNode = CurDAG->getMachineNode(AVR::ELPMWRdZ, DL, MVT::i16,
446 MVT::Other, Ptr, SDValue(NP, 0));
447 }
448 break;
449 default:
450 llvm_unreachable("Unsupported VT!");
451 }
452 }
453
454 // Transfer memory operands.
455 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()});
456
457 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
458 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
459 CurDAG->RemoveDeadNode(N);
460
461 return true;
462}
463
464template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
465 SDValue InGlue;
466 SDValue Chain = N->getOperand(0);
467 SDValue Callee = N->getOperand(1);
468 unsigned LastOpNum = N->getNumOperands() - 1;
469
470 // Direct calls are autogenerated.
471 unsigned Op = Callee.getOpcode();
473 return false;
474 }
475
476 // Skip the incoming flag if present
477 if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
478 --LastOpNum;
479 }
480
481 SDLoc DL(N);
482 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InGlue);
484 Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16));
485
486 // Map all operands into the new node.
487 for (unsigned i = 2, e = LastOpNum + 1; i != e; ++i) {
488 Ops.push_back(N->getOperand(i));
489 }
490
491 Ops.push_back(Chain);
492 Ops.push_back(Chain.getValue(1));
493
494 SDNode *ResNode = CurDAG->getMachineNode(
495 Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL, DL, MVT::Other,
496 MVT::Glue, Ops);
497
498 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
499 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
500 CurDAG->RemoveDeadNode(N);
501
502 return true;
503}
504
505template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
506 SDValue Chain = N->getOperand(0);
507 SDValue JmpAddr = N->getOperand(1);
508
509 SDLoc DL(N);
510 // Move the destination address of the indirect branch into R31R30.
511 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, JmpAddr);
512 SDNode *ResNode = CurDAG->getMachineNode(AVR::IJMP, DL, MVT::Other, Chain);
513
514 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
515 CurDAG->RemoveDeadNode(N);
516
517 return true;
518}
519
520bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
521 SDLoc DL(N);
522 MVT Type = N->getSimpleValueType(0);
523
524 assert(Type == MVT::i8 && "unexpected value type");
525
526 bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
527 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
528
529 SDValue Lhs = N->getOperand(0);
530 SDValue Rhs = N->getOperand(1);
531 SDNode *Mul = CurDAG->getMachineNode(MachineOp, DL, MVT::Glue, Lhs, Rhs);
532 SDValue InChain = CurDAG->getEntryNode();
533 SDValue InGlue = SDValue(Mul, 0);
534
535 // Copy the low half of the result, if it is needed.
536 if (N->hasAnyUseOfValue(0)) {
537 SDValue CopyFromLo =
538 CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
539
540 ReplaceUses(SDValue(N, 0), CopyFromLo);
541
542 InChain = CopyFromLo.getValue(1);
543 InGlue = CopyFromLo.getValue(2);
544 }
545
546 // Copy the high half of the result, if it is needed.
547 if (N->hasAnyUseOfValue(1)) {
548 SDValue CopyFromHi =
549 CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
550
551 ReplaceUses(SDValue(N, 1), CopyFromHi);
552
553 InChain = CopyFromHi.getValue(1);
554 InGlue = CopyFromHi.getValue(2);
555 }
556
557 CurDAG->RemoveDeadNode(N);
558
559 // We need to clear R1. This is currently done (dirtily)
560 // using a custom inserter.
561
562 return true;
563}
564
565void AVRDAGToDAGISel::Select(SDNode *N) {
566 // If we have a custom node, we already have selected!
567 if (N->isMachineOpcode()) {
568 LLVM_DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n");
569 N->setNodeId(-1);
570 return;
571 }
572
573 // See if subclasses can handle this node.
574 if (trySelect(N))
575 return;
576
577 // Select the default instruction
578 SelectCode(N);
579}
580
581bool AVRDAGToDAGISel::trySelect(SDNode *N) {
582 unsigned Opcode = N->getOpcode();
583
584 switch (Opcode) {
585 // Nodes we fully handle.
586 case ISD::FrameIndex:
588 case ISD::BRIND:
589 return select<ISD::BRIND>(N);
590 case ISD::UMUL_LOHI:
591 case ISD::SMUL_LOHI:
592 return selectMultiplication(N);
593
594 // Nodes we handle partially. Other cases are autogenerated
595 case ISD::STORE:
596 return select<ISD::STORE>(N);
597 case ISD::LOAD:
598 return select<ISD::LOAD>(N);
599 case AVRISD::CALL:
600 return select<AVRISD::CALL>(N);
601 default:
602 return false;
603 }
604}
605
607 CodeGenOptLevel OptLevel) {
608 return new AVRDAGToDAGISelLegacy(TM, OptLevel);
609}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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 Opcode)
#define DEBUG_TYPE
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register Reg
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define PASS_NAME
Value * RHS
BinaryOperator * Mul
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition APInt.h:1118
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.
Definition Pass.h:314
This class is used to represent ISD::LOAD nodes.
Machine Value Type.
SimpleValueType SimpleTy
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
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...
virtual bool runOnMachineFunction(MachineFunction &mf)
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isProgramMemoryAccess(MemSDNode const *N)
Definition AVR.h:75
int getProgramMemoryBank(MemSDNode const *N)
Definition AVR.h:86
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ TargetExternalSymbol
Definition ISDOpcodes.h:190
@ BRIND
BRIND - Indirect branch.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:230
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:185
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:557
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionPass * createAVRISelDag(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
#define NC
Definition regutils.h:42
Extended Value Type.
Definition ValueTypes.h:35