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" 15 #include "MCTargetDesc/AVRMCTargetDesc.h" 16 17 #include "llvm/CodeGen/MachineRegisterInfo.h" 18 #include "llvm/CodeGen/SelectionDAGISel.h" 19 #include "llvm/Support/Debug.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 #define DEBUG_TYPE "avr-isel" 23 #define PASS_NAME "AVR DAG->DAG Instruction Selection" 24 25 using namespace llvm; 26 27 namespace { 28 29 /// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form). 30 class AVRDAGToDAGISel : public SelectionDAGISel { 31 public: 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 51 private: 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 61 class AVRDAGToDAGISelLegacy : public SelectionDAGISelLegacy { 62 public: 63 static char ID; 64 AVRDAGToDAGISelLegacy(AVRTargetMachine &TM, CodeGenOptLevel OptLevel) 65 : SelectionDAGISelLegacy( 66 ID, std::make_unique<AVRDAGToDAGISel>(TM, OptLevel)) {} 67 }; 68 69 } // namespace 70 71 char AVRDAGToDAGISelLegacy::ID = 0; 72 73 INITIALIZE_PASS(AVRDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false) 74 75 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 76 Subtarget = &MF.getSubtarget<AVRSubtarget>(); 77 return SelectionDAGISel::runOnMachineFunction(MF); 78 } 79 80 bool 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 142 bool 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 189 unsigned 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 214 bool 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 279 SDValue CopyToReg = 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); 309 SDValue CopyFromReg = 310 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL)); 311 312 OutOps.push_back(CopyFromReg); 313 314 return false; 315 } 316 317 template <> 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 331 template <> 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 368 template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) { 369 const LoadSDNode *LD = cast<LoadSDNode>(N); 370 if (!AVR::isProgramMemoryAccess(LD)) { 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 455 template <> 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(); 463 if (Op == ISD::TargetGlobalAddress || Op == ISD::TargetExternalSymbol) { 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); 474 SmallVector<SDValue, 8> Ops; 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 496 template <> 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 511 bool 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 556 void 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 572 bool 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: 579 return select<ISD::FrameIndex>(N); 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 598 FunctionPass *llvm::createAVRISelDag(AVRTargetMachine &TM, 599 CodeGenOptLevel OptLevel) { 600 return new AVRDAGToDAGISelLegacy(TM, OptLevel); 601 } 602