LLVM 22.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 = CurDAG->getMachineNode(Opc, DL, MVT::i8, MVT::Other, Ptr);
417 } else {
418 // Do not combine the LDI instruction into the ELPM pseudo instruction,
419 // since it may be reused by other ELPM pseudo instructions.
420 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
421 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
422 ResNode = CurDAG->getMachineNode(AVR::ELPMBRdZ, DL, MVT::i8, MVT::Other,
423 Ptr, SDValue(NP, 0));
424 }
425 break;
426 case MVT::i16:
427 if (ProgMemBank == 0) {
428 ResNode =
429 CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16, MVT::Other, Ptr);
430 } else {
431 // Do not combine the LDI instruction into the ELPM pseudo instruction,
432 // since LDI requires the destination register in range R16~R31.
433 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
434 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
435 ResNode = CurDAG->getMachineNode(AVR::ELPMWRdZ, DL, MVT::i16,
436 MVT::Other, Ptr, SDValue(NP, 0));
437 }
438 break;
439 default:
440 llvm_unreachable("Unsupported VT!");
441 }
442 }
443
444 // Transfer memory operands.
445 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()});
446
447 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
448 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
449 CurDAG->RemoveDeadNode(N);
450
451 return true;
452}
453
454template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
455 SDValue InGlue;
456 SDValue Chain = N->getOperand(0);
457 SDValue Callee = N->getOperand(1);
458 unsigned LastOpNum = N->getNumOperands() - 1;
459
460 // Direct calls are autogenerated.
461 unsigned Op = Callee.getOpcode();
463 return false;
464 }
465
466 // Skip the incoming flag if present
467 if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
468 --LastOpNum;
469 }
470
471 SDLoc DL(N);
472 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InGlue);
474 Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16));
475
476 // Map all operands into the new node.
477 for (unsigned i = 2, e = LastOpNum + 1; i != e; ++i) {
478 Ops.push_back(N->getOperand(i));
479 }
480
481 Ops.push_back(Chain);
482 Ops.push_back(Chain.getValue(1));
483
484 SDNode *ResNode = CurDAG->getMachineNode(
485 Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL, DL, MVT::Other,
486 MVT::Glue, Ops);
487
488 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
489 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
490 CurDAG->RemoveDeadNode(N);
491
492 return true;
493}
494
495template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
496 SDValue Chain = N->getOperand(0);
497 SDValue JmpAddr = N->getOperand(1);
498
499 SDLoc DL(N);
500 // Move the destination address of the indirect branch into R31R30.
501 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, JmpAddr);
502 SDNode *ResNode = CurDAG->getMachineNode(AVR::IJMP, DL, MVT::Other, Chain);
503
504 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
505 CurDAG->RemoveDeadNode(N);
506
507 return true;
508}
509
510bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
511 SDLoc DL(N);
512 MVT Type = N->getSimpleValueType(0);
513
514 assert(Type == MVT::i8 && "unexpected value type");
515
516 bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
517 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
518
519 SDValue Lhs = N->getOperand(0);
520 SDValue Rhs = N->getOperand(1);
521 SDNode *Mul = CurDAG->getMachineNode(MachineOp, DL, MVT::Glue, Lhs, Rhs);
522 SDValue InChain = CurDAG->getEntryNode();
523 SDValue InGlue = SDValue(Mul, 0);
524
525 // Copy the low half of the result, if it is needed.
526 if (N->hasAnyUseOfValue(0)) {
527 SDValue CopyFromLo =
528 CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
529
530 ReplaceUses(SDValue(N, 0), CopyFromLo);
531
532 InChain = CopyFromLo.getValue(1);
533 InGlue = CopyFromLo.getValue(2);
534 }
535
536 // Copy the high half of the result, if it is needed.
537 if (N->hasAnyUseOfValue(1)) {
538 SDValue CopyFromHi =
539 CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
540
541 ReplaceUses(SDValue(N, 1), CopyFromHi);
542
543 InChain = CopyFromHi.getValue(1);
544 InGlue = CopyFromHi.getValue(2);
545 }
546
547 CurDAG->RemoveDeadNode(N);
548
549 // We need to clear R1. This is currently done (dirtily)
550 // using a custom inserter.
551
552 return true;
553}
554
555void AVRDAGToDAGISel::Select(SDNode *N) {
556 // If we have a custom node, we already have selected!
557 if (N->isMachineOpcode()) {
558 LLVM_DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n");
559 N->setNodeId(-1);
560 return;
561 }
562
563 // See if subclasses can handle this node.
564 if (trySelect(N))
565 return;
566
567 // Select the default instruction
568 SelectCode(N);
569}
570
571bool AVRDAGToDAGISel::trySelect(SDNode *N) {
572 unsigned Opcode = N->getOpcode();
573
574 switch (Opcode) {
575 // Nodes we fully handle.
576 case ISD::FrameIndex:
578 case ISD::BRIND:
579 return select<ISD::BRIND>(N);
580 case ISD::UMUL_LOHI:
581 case ISD::SMUL_LOHI:
582 return selectMultiplication(N);
583
584 // Nodes we handle partially. Other cases are autogenerated
585 case ISD::STORE:
586 return select<ISD::STORE>(N);
587 case ISD::LOAD:
588 return select<ISD::LOAD>(N);
589 case AVRISD::CALL:
590 return select<AVRISD::CALL>(N);
591 default:
592 return false;
593 }
594}
595
597 CodeGenOptLevel OptLevel) {
598 return new AVRDAGToDAGISelLegacy(TM, OptLevel);
599}
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)
#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)
static bool isSigned(unsigned int Opcode)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
#define LLVM_DEBUG(...)
Definition: Debug.h:119
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:314
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.
LLVM_ABI 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:61
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:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
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.
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:270
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:259
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:1141
@ FrameIndex
Definition: ISDOpcodes.h:90
@ TargetExternalSymbol
Definition: ISDOpcodes.h:185
@ BRIND
BRIND - Indirect branch.
Definition: ISDOpcodes.h:1162
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition: ISDOpcodes.h:225
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition: ISDOpcodes.h:180
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition: ISDOpcodes.h:219
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
Definition: ISDOpcodes.h:1640
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:477
FunctionPass * createAVRISelDag(AVRTargetMachine &TM, CodeGenOptLevel OptLevel)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:82
LLVM_ABI 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