LLVM 20.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
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 // 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);
255
256 unsigned Reg;
257 bool CanHandleRegImmOpt = ImmNode && ImmNode->getAPIntValue().ult(64);
258
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));
265 } else {
266 CanHandleRegImmOpt = false;
267 }
268
269 // If we detect proper case - correct virtual register class
270 // if needed and go to another inlineasm operand.
271 if (CanHandleRegImmOpt) {
272 SDValue Base, Disp;
273
274 if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
275 SDLoc dl(CopyFromRegOp);
276
277 Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
278
280 CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
281
282 SDValue NewCopyFromRegOp =
283 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
284
285 Base = NewCopyFromRegOp;
286 } else {
287 Base = CopyFromRegOp;
288 }
289
290 if (ImmNode->getValueType(0) != MVT::i8) {
291 Disp = CurDAG->getTargetConstant(ImmNode->getZExtValue(), dl, MVT::i8);
292 } else {
293 Disp = ImmOp;
294 }
295
296 OutOps.push_back(Base);
297 OutOps.push_back(Disp);
298
299 return false;
300 }
301 }
302
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);
307
308 SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
310 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
311
312 OutOps.push_back(CopyFromReg);
313
314 return false;
315}
316
317template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) {
318 auto DL = CurDAG->getDataLayout();
319
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();
323 SDValue TFI =
324 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
325
326 CurDAG->SelectNodeTo(N, AVR::FRMIDX, getTargetLowering()->getPointerTy(DL),
327 TFI, CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16));
328 return true;
329}
330
331template <> 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();
336
337 // Early exit when the base pointer is a frame index node or a constant.
338 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
339 BasePtr.isUndef()) {
340 return false;
341 }
342
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)) {
346 return false;
347 }
348
349 int CST = (int)BasePtr.getConstantOperandVal(1);
350 SDValue Chain = ST->getChain();
351 EVT VT = ST->getValue().getValueType();
352 SDLoc DL(N);
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;
356
357 SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops);
358
359 // Transfer memory operands.
360 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {ST->getMemOperand()});
361
362 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
363 CurDAG->RemoveDeadNode(N);
364
365 return true;
366}
367
368template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) {
369 const LoadSDNode *LD = cast<LoadSDNode>(N);
371 // Check if the opcode can be converted into an indexed load.
372 return selectIndexedLoad(N);
373 }
374
375 if (!Subtarget->hasLPM())
376 report_fatal_error("cannot load from program memory on this mcu");
377
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");
383
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();
389 SDNode *ResNode;
390 SDLoc DL(N);
391
392 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue());
393 Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16,
394 Chain.getValue(1));
395
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) {
400 ResNode =
401 CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other, Ptr);
402 } else {
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));
409 }
410 } else {
411 // Selecting an indexed load is not legal, fallback to a normal load.
412 switch (VT.SimpleTy) {
413 case MVT::i8:
414 if (ProgMemBank == 0) {
415 unsigned Opc = Subtarget->hasLPMX() ? AVR::LPMRdZ : AVR::LPMBRdZ;
416 ResNode =
417 CurDAG->getMachineNode(Opc, DL, MVT::i8, MVT::Other, Ptr);
418 } else {
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));
425 }
426 break;
427 case MVT::i16:
428 if (ProgMemBank == 0) {
429 ResNode =
430 CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16, MVT::Other, Ptr);
431 } else {
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));
438 }
439 break;
440 default:
441 llvm_unreachable("Unsupported VT!");
442 }
443 }
444
445 // Transfer memory operands.
446 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()});
447
448 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
449 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
450 CurDAG->RemoveDeadNode(N);
451
452 return true;
453}
454
455template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
456 SDValue InGlue;
457 SDValue Chain = N->getOperand(0);
458 SDValue Callee = N->getOperand(1);
459 unsigned LastOpNum = N->getNumOperands() - 1;
460
461 // Direct calls are autogenerated.
462 unsigned Op = Callee.getOpcode();
464 return false;
465 }
466
467 // Skip the incoming flag if present
468 if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
469 --LastOpNum;
470 }
471
472 SDLoc DL(N);
473 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InGlue);
475 Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16));
476
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));
480 }
481
482 Ops.push_back(Chain);
483 Ops.push_back(Chain.getValue(1));
484
485 SDNode *ResNode = CurDAG->getMachineNode(
486 Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL, DL, MVT::Other,
487 MVT::Glue, Ops);
488
489 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
490 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
491 CurDAG->RemoveDeadNode(N);
492
493 return true;
494}
495
496template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
497 SDValue Chain = N->getOperand(0);
498 SDValue JmpAddr = N->getOperand(1);
499
500 SDLoc DL(N);
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);
504
505 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
506 CurDAG->RemoveDeadNode(N);
507
508 return true;
509}
510
511bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
512 SDLoc DL(N);
513 MVT Type = N->getSimpleValueType(0);
514
515 assert(Type == MVT::i8 && "unexpected value type");
516
517 bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
518 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
519
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);
525
526 // Copy the low half of the result, if it is needed.
527 if (N->hasAnyUseOfValue(0)) {
528 SDValue CopyFromLo =
529 CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
530
531 ReplaceUses(SDValue(N, 0), CopyFromLo);
532
533 InChain = CopyFromLo.getValue(1);
534 InGlue = CopyFromLo.getValue(2);
535 }
536
537 // Copy the high half of the result, if it is needed.
538 if (N->hasAnyUseOfValue(1)) {
539 SDValue CopyFromHi =
540 CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
541
542 ReplaceUses(SDValue(N, 1), CopyFromHi);
543
544 InChain = CopyFromHi.getValue(1);
545 InGlue = CopyFromHi.getValue(2);
546 }
547
548 CurDAG->RemoveDeadNode(N);
549
550 // We need to clear R1. This is currently done (dirtily)
551 // using a custom inserter.
552
553 return true;
554}
555
556void 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");
560 N->setNodeId(-1);
561 return;
562 }
563
564 // See if subclasses can handle this node.
565 if (trySelect(N))
566 return;
567
568 // Select the default instruction
569 SelectCode(N);
570}
571
572bool AVRDAGToDAGISel::trySelect(SDNode *N) {
573 unsigned Opcode = N->getOpcode();
574 SDLoc DL(N);
575
576 switch (Opcode) {
577 // Nodes we fully handle.
578 case ISD::FrameIndex:
580 case ISD::BRIND:
581 return select<ISD::BRIND>(N);
582 case ISD::UMUL_LOHI:
583 case ISD::SMUL_LOHI:
584 return selectMultiplication(N);
585
586 // Nodes we handle partially. Other cases are autogenerated
587 case ISD::STORE:
588 return select<ISD::STORE>(N);
589 case ISD::LOAD:
590 return select<ISD::LOAD>(N);
591 case AVRISD::CALL:
592 return select<AVRISD::CALL>(N);
593 default:
594 return false;
595 }
596}
597
599 CodeGenOptLevel OptLevel) {
600 return new AVRDAGToDAGISelLegacy(TM, OptLevel);
601}
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
bool AVRDAGToDAGISel::select< ISD::LOAD >(SDNode *N)
#define PASS_NAME
#define DEBUG_TYPE
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)
#define LLVM_DEBUG(...)
Definition: Debug.h:106
static bool isSigned(unsigned int Opcode)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Value * RHS
BinaryOperator * Mul
bool ult(const APInt &RHS) const
Unsigned less than comparison.
Definition: APInt.h:1111
A specific AVR target MCU.
Definition: AVRSubtarget.h:32
const AVRTargetLowering * getTargetLowering() const override
Definition: AVRSubtarget.h:46
A generic AVR implementation.
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
This class is used to represent ISD::LOAD nodes.
Machine Value Type.
SimpleValueType SimpleTy
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...
Register getReg() const
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:71
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 SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
virtual bool runOnMachineFunction(MachineFunction &mf)
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
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.
Definition: Type.h:45
#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)
Definition: AVR.h:74
int getProgramMemoryBank(MemSDNode const *N)
Definition: AVR.h:85
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:257
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1102
@ FrameIndex
Definition: ISDOpcodes.h:80
@ TargetExternalSymbol
Definition: ISDOpcodes.h:175
@ BRIND
BRIND - Indirect branch.
Definition: ISDOpcodes.h:1123
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition: ISDOpcodes.h:215
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:170
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition: ISDOpcodes.h:209
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
Definition: ISDOpcodes.h:1562
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
FunctionPass * createAVRISelDag(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
#define N
#define NC
Definition: regutils.h:42
Extended Value Type.
Definition: ValueTypes.h:35