LLVM 19.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).
126 if (isUInt<6>(RHSC) && (VT == MVT::i8 || VT == MVT::i16)) {
127 Base = N.getOperand(0);
128 Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
129
130 return true;
131 }
132 }
133
134 return false;
135}
136
137bool AVRDAGToDAGISel::selectIndexedLoad(SDNode *N) {
138 const LoadSDNode *LD = cast<LoadSDNode>(N);
139 ISD::MemIndexedMode AM = LD->getAddressingMode();
140 MVT VT = LD->getMemoryVT().getSimpleVT();
141 auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
142
143 // We only care if this load uses a POSTINC or PREDEC mode.
144 if ((LD->getExtensionType() != ISD::NON_EXTLOAD) ||
145 (AM != ISD::POST_INC && AM != ISD::PRE_DEC)) {
146
147 return false;
148 }
149
150 unsigned Opcode = 0;
151 bool isPre = (AM == ISD::PRE_DEC);
152 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
153
154 switch (VT.SimpleTy) {
155 case MVT::i8: {
156 if ((!isPre && Offs != 1) || (isPre && Offs != -1)) {
157 return false;
158 }
159
160 Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi;
161 break;
162 }
163 case MVT::i16: {
164 if ((!isPre && Offs != 2) || (isPre && Offs != -2)) {
165 return false;
166 }
167
168 Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi;
169 break;
170 }
171 default:
172 return false;
173 }
174
175 SDNode *ResNode =
176 CurDAG->getMachineNode(Opcode, SDLoc(N), VT, PtrVT, MVT::Other,
177 LD->getBasePtr(), LD->getChain());
178 ReplaceUses(N, ResNode);
179 CurDAG->RemoveDeadNode(N);
180
181 return true;
182}
183
184unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode *LD, MVT VT,
185 int Bank) {
186 // Progmem indexed loads only work in POSTINC mode.
187 if (LD->getExtensionType() != ISD::NON_EXTLOAD ||
188 LD->getAddressingMode() != ISD::POST_INC)
189 return 0;
190
191 // Feature ELPM is needed for loading from extended program memory.
192 assert((Bank == 0 || Subtarget->hasELPM()) &&
193 "cannot load from extended program memory on this mcu");
194
195 unsigned Opcode = 0;
196 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue();
197
198 if (VT.SimpleTy == MVT::i8 && Offs == 1 && Bank == 0)
199 Opcode = AVR::LPMRdZPi;
200
201 // TODO: Implements the expansion of the following pseudo instructions.
202 // LPMWRdZPi: type == MVT::i16, offset == 2, Bank == 0.
203 // ELPMBRdZPi: type == MVT::i8, offset == 1, Bank > 0.
204 // ELPMWRdZPi: type == MVT::i16, offset == 2, Bank > 0.
205
206 return Opcode;
207}
208
209bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(
210 const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode,
211 std::vector<SDValue> &OutOps) {
212 assert((ConstraintCode == InlineAsm::ConstraintCode::m ||
213 ConstraintCode == InlineAsm::ConstraintCode::Q) &&
214 "Unexpected asm memory constraint");
215
216 MachineRegisterInfo &RI = MF->getRegInfo();
217 const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
218 const TargetLowering &TL = *STI.getTargetLowering();
219 SDLoc dl(Op);
220 auto DL = CurDAG->getDataLayout();
221
222 const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op);
223
224 // If address operand is of PTRDISPREGS class, all is OK, then.
225 if (RegNode &&
226 RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) {
227 OutOps.push_back(Op);
228 return false;
229 }
230
231 if (Op->getOpcode() == ISD::FrameIndex) {
232 SDValue Base, Disp;
233
234 if (SelectAddr(Op.getNode(), Op, Base, Disp)) {
235 OutOps.push_back(Base);
236 OutOps.push_back(Disp);
237
238 return false;
239 }
240
241 return true;
242 }
243
244 // If Op is add 'register, immediate' and
245 // register is either virtual register or register of PTRDISPREGSRegClass
246 if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) {
247 SDValue CopyFromRegOp = Op->getOperand(0);
248 SDValue ImmOp = Op->getOperand(1);
249 ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp);
250
251 unsigned Reg;
252 bool CanHandleRegImmOpt = ImmNode && ImmNode->getAPIntValue().ult(64);
253
254 if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) {
255 RegisterSDNode *RegNode =
256 cast<RegisterSDNode>(CopyFromRegOp->getOperand(1));
257 Reg = RegNode->getReg();
258 CanHandleRegImmOpt &= (Register::isVirtualRegister(Reg) ||
259 AVR::PTRDISPREGSRegClass.contains(Reg));
260 } else {
261 CanHandleRegImmOpt = false;
262 }
263
264 // If we detect proper case - correct virtual register class
265 // if needed and go to another inlineasm operand.
266 if (CanHandleRegImmOpt) {
267 SDValue Base, Disp;
268
269 if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) {
270 SDLoc dl(CopyFromRegOp);
271
272 Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
273
275 CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp);
276
277 SDValue NewCopyFromRegOp =
278 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
279
280 Base = NewCopyFromRegOp;
281 } else {
282 Base = CopyFromRegOp;
283 }
284
285 if (ImmNode->getValueType(0) != MVT::i8) {
286 Disp = CurDAG->getTargetConstant(ImmNode->getZExtValue(), dl, MVT::i8);
287 } else {
288 Disp = ImmOp;
289 }
290
291 OutOps.push_back(Base);
292 OutOps.push_back(Disp);
293
294 return false;
295 }
296 }
297
298 // More generic case.
299 // Create chain that puts Op into pointer register
300 // and return that register.
301 Register VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass);
302
303 SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op);
305 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL));
306
307 OutOps.push_back(CopyFromReg);
308
309 return false;
310}
311
312template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) {
313 auto DL = CurDAG->getDataLayout();
314
315 // Convert the frameindex into a temp instruction that will hold the
316 // effective address of the final stack slot.
317 int FI = cast<FrameIndexSDNode>(N)->getIndex();
318 SDValue TFI =
319 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL));
320
321 CurDAG->SelectNodeTo(N, AVR::FRMIDX, getTargetLowering()->getPointerTy(DL),
322 TFI, CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16));
323 return true;
324}
325
326template <> bool AVRDAGToDAGISel::select<ISD::STORE>(SDNode *N) {
327 // Use the STD{W}SPQRr pseudo instruction when passing arguments through
328 // the stack on function calls for further expansion during the PEI phase.
329 const StoreSDNode *ST = cast<StoreSDNode>(N);
330 SDValue BasePtr = ST->getBasePtr();
331
332 // Early exit when the base pointer is a frame index node or a constant.
333 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) ||
334 BasePtr.isUndef()) {
335 return false;
336 }
337
338 const RegisterSDNode *RN = dyn_cast<RegisterSDNode>(BasePtr.getOperand(0));
339 // Only stores where SP is the base pointer are valid.
340 if (!RN || (RN->getReg() != AVR::SP)) {
341 return false;
342 }
343
344 int CST = (int)BasePtr.getConstantOperandVal(1);
345 SDValue Chain = ST->getChain();
346 EVT VT = ST->getValue().getValueType();
347 SDLoc DL(N);
348 SDValue Offset = CurDAG->getTargetConstant(CST, DL, MVT::i16);
349 SDValue Ops[] = {BasePtr.getOperand(0), Offset, ST->getValue(), Chain};
350 unsigned Opc = (VT == MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr;
351
352 SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops);
353
354 // Transfer memory operands.
355 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {ST->getMemOperand()});
356
357 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
358 CurDAG->RemoveDeadNode(N);
359
360 return true;
361}
362
363template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) {
364 const LoadSDNode *LD = cast<LoadSDNode>(N);
366 // Check if the opcode can be converted into an indexed load.
367 return selectIndexedLoad(N);
368 }
369
370 if (!Subtarget->hasLPM())
371 report_fatal_error("cannot load from program memory on this mcu");
372
373 int ProgMemBank = AVR::getProgramMemoryBank(LD);
374 if (ProgMemBank < 0 || ProgMemBank > 5)
375 report_fatal_error("unexpected program memory bank");
376 if (ProgMemBank > 0 && !Subtarget->hasELPM())
377 report_fatal_error("unexpected program memory bank");
378
379 // This is a flash memory load, move the pointer into R31R30 and emit
380 // the lpm instruction.
381 MVT VT = LD->getMemoryVT().getSimpleVT();
382 SDValue Chain = LD->getChain();
383 SDValue Ptr = LD->getBasePtr();
384 SDNode *ResNode;
385 SDLoc DL(N);
386
387 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue());
388 Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16,
389 Chain.getValue(1));
390
391 // Check if the opcode can be converted into an indexed load.
392 if (unsigned LPMOpc = selectIndexedProgMemLoad(LD, VT, ProgMemBank)) {
393 // It is legal to fold the load into an indexed load.
394 if (ProgMemBank == 0) {
395 ResNode =
396 CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other, Ptr);
397 } else {
398 // Do not combine the LDI instruction into the ELPM pseudo instruction,
399 // since it may be reused by other ELPM pseudo instructions.
400 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
401 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
402 ResNode = CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other,
403 Ptr, SDValue(NP, 0));
404 }
405 } else {
406 // Selecting an indexed load is not legal, fallback to a normal load.
407 switch (VT.SimpleTy) {
408 case MVT::i8:
409 if (ProgMemBank == 0) {
410 unsigned Opc = Subtarget->hasLPMX() ? AVR::LPMRdZ : AVR::LPMBRdZ;
411 ResNode =
412 CurDAG->getMachineNode(Opc, DL, MVT::i8, MVT::Other, Ptr);
413 } else {
414 // Do not combine the LDI instruction into the ELPM pseudo instruction,
415 // since it may be reused by other ELPM pseudo instructions.
416 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
417 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
418 ResNode = CurDAG->getMachineNode(AVR::ELPMBRdZ, DL, MVT::i8, MVT::Other,
419 Ptr, SDValue(NP, 0));
420 }
421 break;
422 case MVT::i16:
423 if (ProgMemBank == 0) {
424 ResNode =
425 CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16, MVT::Other, Ptr);
426 } else {
427 // Do not combine the LDI instruction into the ELPM pseudo instruction,
428 // since LDI requires the destination register in range R16~R31.
429 SDValue NC = CurDAG->getTargetConstant(ProgMemBank, DL, MVT::i8);
430 auto *NP = CurDAG->getMachineNode(AVR::LDIRdK, DL, MVT::i8, NC);
431 ResNode = CurDAG->getMachineNode(AVR::ELPMWRdZ, DL, MVT::i16,
432 MVT::Other, Ptr, SDValue(NP, 0));
433 }
434 break;
435 default:
436 llvm_unreachable("Unsupported VT!");
437 }
438 }
439
440 // Transfer memory operands.
441 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()});
442
443 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
444 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
445 CurDAG->RemoveDeadNode(N);
446
447 return true;
448}
449
450template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
451 SDValue InGlue;
452 SDValue Chain = N->getOperand(0);
453 SDValue Callee = N->getOperand(1);
454 unsigned LastOpNum = N->getNumOperands() - 1;
455
456 // Direct calls are autogenerated.
457 unsigned Op = Callee.getOpcode();
459 return false;
460 }
461
462 // Skip the incoming flag if present
463 if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) {
464 --LastOpNum;
465 }
466
467 SDLoc DL(N);
468 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InGlue);
470 Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16));
471
472 // Map all operands into the new node.
473 for (unsigned i = 2, e = LastOpNum + 1; i != e; ++i) {
474 Ops.push_back(N->getOperand(i));
475 }
476
477 Ops.push_back(Chain);
478 Ops.push_back(Chain.getValue(1));
479
480 SDNode *ResNode = CurDAG->getMachineNode(
481 Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL, DL, MVT::Other,
482 MVT::Glue, Ops);
483
484 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
485 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));
486 CurDAG->RemoveDeadNode(N);
487
488 return true;
489}
490
491template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) {
492 SDValue Chain = N->getOperand(0);
493 SDValue JmpAddr = N->getOperand(1);
494
495 SDLoc DL(N);
496 // Move the destination address of the indirect branch into R31R30.
497 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, JmpAddr);
498 SDNode *ResNode = CurDAG->getMachineNode(AVR::IJMP, DL, MVT::Other, Chain);
499
500 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
501 CurDAG->RemoveDeadNode(N);
502
503 return true;
504}
505
506bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) {
507 SDLoc DL(N);
508 MVT Type = N->getSimpleValueType(0);
509
510 assert(Type == MVT::i8 && "unexpected value type");
511
512 bool isSigned = N->getOpcode() == ISD::SMUL_LOHI;
513 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr;
514
515 SDValue Lhs = N->getOperand(0);
516 SDValue Rhs = N->getOperand(1);
517 SDNode *Mul = CurDAG->getMachineNode(MachineOp, DL, MVT::Glue, Lhs, Rhs);
518 SDValue InChain = CurDAG->getEntryNode();
519 SDValue InGlue = SDValue(Mul, 0);
520
521 // Copy the low half of the result, if it is needed.
522 if (N->hasAnyUseOfValue(0)) {
523 SDValue CopyFromLo =
524 CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue);
525
526 ReplaceUses(SDValue(N, 0), CopyFromLo);
527
528 InChain = CopyFromLo.getValue(1);
529 InGlue = CopyFromLo.getValue(2);
530 }
531
532 // Copy the high half of the result, if it is needed.
533 if (N->hasAnyUseOfValue(1)) {
534 SDValue CopyFromHi =
535 CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue);
536
537 ReplaceUses(SDValue(N, 1), CopyFromHi);
538
539 InChain = CopyFromHi.getValue(1);
540 InGlue = CopyFromHi.getValue(2);
541 }
542
543 CurDAG->RemoveDeadNode(N);
544
545 // We need to clear R1. This is currently done (dirtily)
546 // using a custom inserter.
547
548 return true;
549}
550
551void AVRDAGToDAGISel::Select(SDNode *N) {
552 // If we have a custom node, we already have selected!
553 if (N->isMachineOpcode()) {
554 LLVM_DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n");
555 N->setNodeId(-1);
556 return;
557 }
558
559 // See if subclasses can handle this node.
560 if (trySelect(N))
561 return;
562
563 // Select the default instruction
564 SelectCode(N);
565}
566
567bool AVRDAGToDAGISel::trySelect(SDNode *N) {
568 unsigned Opcode = N->getOpcode();
569 SDLoc DL(N);
570
571 switch (Opcode) {
572 // Nodes we fully handle.
573 case ISD::FrameIndex:
575 case ISD::BRIND:
576 return select<ISD::BRIND>(N);
577 case ISD::UMUL_LOHI:
578 case ISD::SMUL_LOHI:
579 return selectMultiplication(N);
580
581 // Nodes we handle partially. Other cases are autogenerated
582 case ISD::STORE:
583 return select<ISD::STORE>(N);
584 case ISD::LOAD:
585 return select<ISD::LOAD>(N);
586 case AVRISD::CALL:
587 return select<AVRISD::CALL>(N);
588 default:
589 return false;
590 }
591}
592
594 CodeGenOptLevel OptLevel) {
595 return new AVRDAGToDAGISelLegacy(TM, OptLevel);
596}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
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(X)
Definition: Debug.h:101
static bool isSigned(unsigned int Opcode)
const char LLVMTargetMachineRef TM
#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:1090
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:311
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:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
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:1052
@ FrameIndex
Definition: ISDOpcodes.h:80
@ TargetExternalSymbol
Definition: ISDOpcodes.h:175
@ BRIND
BRIND - Indirect branch.
Definition: ISDOpcodes.h:1073
@ 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:1503
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:34