1 //===-- AVRISelDAGToDAG.cpp - A dag to dag inst selector for AVR ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an instruction selector for the AVR target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AVR.h" 15 #include "AVRTargetMachine.h" 16 #include "MCTargetDesc/AVRMCTargetDesc.h" 17 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 #include "llvm/CodeGen/SelectionDAGISel.h" 20 #include "llvm/Support/Debug.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 #define DEBUG_TYPE "avr-isel" 24 25 namespace llvm { 26 27 /// Lowers LLVM IR (in DAG form) to AVR MC instructions (in DAG form). 28 class AVRDAGToDAGISel : public SelectionDAGISel { 29 public: 30 AVRDAGToDAGISel(AVRTargetMachine &TM, CodeGenOpt::Level OptLevel) 31 : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {} 32 33 StringRef getPassName() const override { 34 return "AVR DAG->DAG Instruction Selection"; 35 } 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); 43 44 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode, 45 std::vector<SDValue> &OutOps) override; 46 47 // Include the pieces autogenerated from the target description. 48 #include "AVRGenDAGISel.inc" 49 50 private: 51 void Select(SDNode *N) override; 52 bool trySelect(SDNode *N); 53 54 template <unsigned NodeType> bool select(SDNode *N); 55 bool selectMultiplication(SDNode *N); 56 57 const AVRSubtarget *Subtarget; 58 }; 59 60 bool AVRDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 61 Subtarget = &MF.getSubtarget<AVRSubtarget>(); 62 return SelectionDAGISel::runOnMachineFunction(MF); 63 } 64 65 bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base, 66 SDValue &Disp) { 67 SDLoc dl(Op); 68 auto DL = CurDAG->getDataLayout(); 69 MVT PtrVT = getTargetLowering()->getPointerTy(DL); 70 71 // if the address is a frame index get the TargetFrameIndex. 72 if (const FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) { 73 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), PtrVT); 74 Disp = CurDAG->getTargetConstant(0, dl, MVT::i8); 75 76 return true; 77 } 78 79 // Match simple Reg + uimm6 operands. 80 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && 81 !CurDAG->isBaseWithConstantOffset(N)) { 82 return false; 83 } 84 85 if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 86 int RHSC = (int)RHS->getZExtValue(); 87 88 // Convert negative offsets into positives ones. 89 if (N.getOpcode() == ISD::SUB) { 90 RHSC = -RHSC; 91 } 92 93 // <#Frame index + const> 94 // Allow folding offsets bigger than 63 so the frame pointer can be used 95 // directly instead of copying it around by adjusting and restoring it for 96 // each access. 97 if (N.getOperand(0).getOpcode() == ISD::FrameIndex) { 98 int FI = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex(); 99 100 Base = CurDAG->getTargetFrameIndex(FI, PtrVT); 101 Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i16); 102 103 return true; 104 } 105 106 // The value type of the memory instruction determines what is the maximum 107 // offset allowed. 108 MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT(); 109 110 // We only accept offsets that fit in 6 bits (unsigned). 111 if (isUInt<6>(RHSC) && (VT == MVT::i8 || VT == MVT::i16)) { 112 Base = N.getOperand(0); 113 Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8); 114 115 return true; 116 } 117 } 118 119 return false; 120 } 121 122 bool AVRDAGToDAGISel::selectIndexedLoad(SDNode *N) { 123 const LoadSDNode *LD = cast<LoadSDNode>(N); 124 ISD::MemIndexedMode AM = LD->getAddressingMode(); 125 MVT VT = LD->getMemoryVT().getSimpleVT(); 126 auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); 127 128 // We only care if this load uses a POSTINC or PREDEC mode. 129 if ((LD->getExtensionType() != ISD::NON_EXTLOAD) || 130 (AM != ISD::POST_INC && AM != ISD::PRE_DEC)) { 131 132 return false; 133 } 134 135 unsigned Opcode = 0; 136 bool isPre = (AM == ISD::PRE_DEC); 137 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue(); 138 139 switch (VT.SimpleTy) { 140 case MVT::i8: { 141 if ((!isPre && Offs != 1) || (isPre && Offs != -1)) { 142 return false; 143 } 144 145 Opcode = (isPre) ? AVR::LDRdPtrPd : AVR::LDRdPtrPi; 146 break; 147 } 148 case MVT::i16: { 149 if ((!isPre && Offs != 2) || (isPre && Offs != -2)) { 150 return false; 151 } 152 153 Opcode = (isPre) ? AVR::LDWRdPtrPd : AVR::LDWRdPtrPi; 154 break; 155 } 156 default: 157 return false; 158 } 159 160 SDNode *ResNode = CurDAG->getMachineNode(Opcode, SDLoc(N), VT, 161 PtrVT, MVT::Other, 162 LD->getBasePtr(), LD->getChain()); 163 ReplaceUses(N, ResNode); 164 CurDAG->RemoveDeadNode(N); 165 166 return true; 167 } 168 169 unsigned AVRDAGToDAGISel::selectIndexedProgMemLoad(const LoadSDNode *LD, 170 MVT VT) { 171 ISD::MemIndexedMode AM = LD->getAddressingMode(); 172 173 // Progmem indexed loads only work in POSTINC mode. 174 if (LD->getExtensionType() != ISD::NON_EXTLOAD || AM != ISD::POST_INC) { 175 return 0; 176 } 177 178 unsigned Opcode = 0; 179 int Offs = cast<ConstantSDNode>(LD->getOffset())->getSExtValue(); 180 181 switch (VT.SimpleTy) { 182 case MVT::i8: { 183 if (Offs != 1) { 184 return 0; 185 } 186 Opcode = AVR::LPMRdZPi; 187 break; 188 } 189 case MVT::i16: { 190 if (Offs != 2) { 191 return 0; 192 } 193 Opcode = AVR::LPMWRdZPi; 194 break; 195 } 196 default: 197 return 0; 198 } 199 200 return Opcode; 201 } 202 203 bool AVRDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, 204 unsigned ConstraintCode, 205 std::vector<SDValue> &OutOps) { 206 assert((ConstraintCode == InlineAsm::Constraint_m || 207 ConstraintCode == InlineAsm::Constraint_Q) && 208 "Unexpected asm memory constraint"); 209 210 MachineRegisterInfo &RI = MF->getRegInfo(); 211 const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>(); 212 const TargetLowering &TL = *STI.getTargetLowering(); 213 SDLoc dl(Op); 214 auto DL = CurDAG->getDataLayout(); 215 216 const RegisterSDNode *RegNode = dyn_cast<RegisterSDNode>(Op); 217 218 // If address operand is of PTRDISPREGS class, all is OK, then. 219 if (RegNode && 220 RI.getRegClass(RegNode->getReg()) == &AVR::PTRDISPREGSRegClass) { 221 OutOps.push_back(Op); 222 return false; 223 } 224 225 if (Op->getOpcode() == ISD::FrameIndex) { 226 SDValue Base, Disp; 227 228 if (SelectAddr(Op.getNode(), Op, Base, Disp)) { 229 OutOps.push_back(Base); 230 OutOps.push_back(Disp); 231 232 return false; 233 } 234 235 return true; 236 } 237 238 // If Op is add 'register, immediate' and 239 // register is either virtual register or register of PTRDISPREGSRegClass 240 if (Op->getOpcode() == ISD::ADD || Op->getOpcode() == ISD::SUB) { 241 SDValue CopyFromRegOp = Op->getOperand(0); 242 SDValue ImmOp = Op->getOperand(1); 243 ConstantSDNode *ImmNode = dyn_cast<ConstantSDNode>(ImmOp); 244 245 unsigned Reg; 246 bool CanHandleRegImmOpt = true; 247 248 CanHandleRegImmOpt &= ImmNode != 0; 249 CanHandleRegImmOpt &= ImmNode->getAPIntValue().getZExtValue() < 64; 250 251 if (CopyFromRegOp->getOpcode() == ISD::CopyFromReg) { 252 RegisterSDNode *RegNode = 253 cast<RegisterSDNode>(CopyFromRegOp->getOperand(1)); 254 Reg = RegNode->getReg(); 255 CanHandleRegImmOpt &= (TargetRegisterInfo::isVirtualRegister(Reg) || 256 AVR::PTRDISPREGSRegClass.contains(Reg)); 257 } else { 258 CanHandleRegImmOpt = false; 259 } 260 261 // If we detect proper case - correct virtual register class 262 // if needed and go to another inlineasm operand. 263 if (CanHandleRegImmOpt) { 264 SDValue Base, Disp; 265 266 if (RI.getRegClass(Reg) != &AVR::PTRDISPREGSRegClass) { 267 SDLoc dl(CopyFromRegOp); 268 269 unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass); 270 271 SDValue CopyToReg = 272 CurDAG->getCopyToReg(CopyFromRegOp, dl, VReg, CopyFromRegOp); 273 274 SDValue NewCopyFromRegOp = 275 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL)); 276 277 Base = NewCopyFromRegOp; 278 } else { 279 Base = CopyFromRegOp; 280 } 281 282 if (ImmNode->getValueType(0) != MVT::i8) { 283 Disp = CurDAG->getTargetConstant(ImmNode->getAPIntValue().getZExtValue(), dl, MVT::i8); 284 } else { 285 Disp = ImmOp; 286 } 287 288 OutOps.push_back(Base); 289 OutOps.push_back(Disp); 290 291 return false; 292 } 293 } 294 295 // More generic case. 296 // Create chain that puts Op into pointer register 297 // and return that register. 298 unsigned VReg = RI.createVirtualRegister(&AVR::PTRDISPREGSRegClass); 299 300 SDValue CopyToReg = CurDAG->getCopyToReg(Op, dl, VReg, Op); 301 SDValue CopyFromReg = 302 CurDAG->getCopyFromReg(CopyToReg, dl, VReg, TL.getPointerTy(DL)); 303 304 OutOps.push_back(CopyFromReg); 305 306 return false; 307 } 308 309 template <> bool AVRDAGToDAGISel::select<ISD::FrameIndex>(SDNode *N) { 310 auto DL = CurDAG->getDataLayout(); 311 312 // Convert the frameindex into a temp instruction that will hold the 313 // effective address of the final stack slot. 314 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 315 SDValue TFI = 316 CurDAG->getTargetFrameIndex(FI, getTargetLowering()->getPointerTy(DL)); 317 318 CurDAG->SelectNodeTo(N, AVR::FRMIDX, 319 getTargetLowering()->getPointerTy(DL), TFI, 320 CurDAG->getTargetConstant(0, SDLoc(N), MVT::i16)); 321 return true; 322 } 323 324 template <> bool AVRDAGToDAGISel::select<ISD::STORE>(SDNode *N) { 325 // Use the STD{W}SPQRr pseudo instruction when passing arguments through 326 // the stack on function calls for further expansion during the PEI phase. 327 const StoreSDNode *ST = cast<StoreSDNode>(N); 328 SDValue BasePtr = ST->getBasePtr(); 329 330 // Early exit when the base pointer is a frame index node or a constant. 331 if (isa<FrameIndexSDNode>(BasePtr) || isa<ConstantSDNode>(BasePtr) || 332 BasePtr.isUndef()) { 333 return false; 334 } 335 336 const RegisterSDNode *RN = dyn_cast<RegisterSDNode>(BasePtr.getOperand(0)); 337 // Only stores where SP is the base pointer are valid. 338 if (!RN || (RN->getReg() != AVR::SP)) { 339 return false; 340 } 341 342 int CST = (int)cast<ConstantSDNode>(BasePtr.getOperand(1))->getZExtValue(); 343 SDValue Chain = ST->getChain(); 344 EVT VT = ST->getValue().getValueType(); 345 SDLoc DL(N); 346 SDValue Offset = CurDAG->getTargetConstant(CST, DL, MVT::i16); 347 SDValue Ops[] = {BasePtr.getOperand(0), Offset, ST->getValue(), Chain}; 348 unsigned Opc = (VT == MVT::i16) ? AVR::STDWSPQRr : AVR::STDSPQRr; 349 350 SDNode *ResNode = CurDAG->getMachineNode(Opc, DL, MVT::Other, Ops); 351 352 // Transfer memory operands. 353 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {ST->getMemOperand()}); 354 355 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 356 CurDAG->RemoveDeadNode(N); 357 358 return true; 359 } 360 361 template <> bool AVRDAGToDAGISel::select<ISD::LOAD>(SDNode *N) { 362 const LoadSDNode *LD = cast<LoadSDNode>(N); 363 if (!AVR::isProgramMemoryAccess(LD)) { 364 // Check if the opcode can be converted into an indexed load. 365 return selectIndexedLoad(N); 366 } 367 368 assert(Subtarget->hasLPM() && "cannot load from program memory on this mcu"); 369 370 // This is a flash memory load, move the pointer into R31R30 and emit 371 // the lpm instruction. 372 MVT VT = LD->getMemoryVT().getSimpleVT(); 373 SDValue Chain = LD->getChain(); 374 SDValue Ptr = LD->getBasePtr(); 375 SDNode *ResNode; 376 SDLoc DL(N); 377 378 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Ptr, SDValue()); 379 Ptr = CurDAG->getCopyFromReg(Chain, DL, AVR::R31R30, MVT::i16, 380 Chain.getValue(1)); 381 382 SDValue RegZ = CurDAG->getRegister(AVR::R31R30, MVT::i16); 383 384 // Check if the opcode can be converted into an indexed load. 385 if (unsigned LPMOpc = selectIndexedProgMemLoad(LD, VT)) { 386 // It is legal to fold the load into an indexed load. 387 ResNode = CurDAG->getMachineNode(LPMOpc, DL, VT, MVT::i16, MVT::Other, Ptr, 388 RegZ); 389 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1)); 390 } else { 391 // Selecting an indexed load is not legal, fallback to a normal load. 392 switch (VT.SimpleTy) { 393 case MVT::i8: 394 ResNode = CurDAG->getMachineNode(AVR::LPMRdZ, DL, MVT::i8, MVT::Other, 395 Ptr, RegZ); 396 break; 397 case MVT::i16: 398 ResNode = CurDAG->getMachineNode(AVR::LPMWRdZ, DL, MVT::i16, 399 MVT::Other, Ptr, RegZ); 400 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1)); 401 break; 402 default: 403 llvm_unreachable("Unsupported VT!"); 404 } 405 } 406 407 // Transfer memory operands. 408 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {LD->getMemOperand()}); 409 410 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 411 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1)); 412 CurDAG->RemoveDeadNode(N); 413 414 return true; 415 } 416 417 template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) { 418 SDValue InFlag; 419 SDValue Chain = N->getOperand(0); 420 SDValue Callee = N->getOperand(1); 421 unsigned LastOpNum = N->getNumOperands() - 1; 422 423 // Direct calls are autogenerated. 424 unsigned Op = Callee.getOpcode(); 425 if (Op == ISD::TargetGlobalAddress || Op == ISD::TargetExternalSymbol) { 426 return false; 427 } 428 429 // Skip the incoming flag if present 430 if (N->getOperand(LastOpNum).getValueType() == MVT::Glue) { 431 --LastOpNum; 432 } 433 434 SDLoc DL(N); 435 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, Callee, InFlag); 436 SmallVector<SDValue, 8> Ops; 437 Ops.push_back(CurDAG->getRegister(AVR::R31R30, MVT::i16)); 438 439 // Map all operands into the new node. 440 for (unsigned i = 2, e = LastOpNum + 1; i != e; ++i) { 441 Ops.push_back(N->getOperand(i)); 442 } 443 444 Ops.push_back(Chain); 445 Ops.push_back(Chain.getValue(1)); 446 447 SDNode *ResNode = 448 CurDAG->getMachineNode(AVR::ICALL, DL, MVT::Other, MVT::Glue, Ops); 449 450 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 451 ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1)); 452 CurDAG->RemoveDeadNode(N); 453 454 return true; 455 } 456 457 template <> bool AVRDAGToDAGISel::select<ISD::BRIND>(SDNode *N) { 458 SDValue Chain = N->getOperand(0); 459 SDValue JmpAddr = N->getOperand(1); 460 461 SDLoc DL(N); 462 // Move the destination address of the indirect branch into R31R30. 463 Chain = CurDAG->getCopyToReg(Chain, DL, AVR::R31R30, JmpAddr); 464 SDNode *ResNode = CurDAG->getMachineNode(AVR::IJMP, DL, MVT::Other, Chain); 465 466 ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); 467 CurDAG->RemoveDeadNode(N); 468 469 return true; 470 } 471 472 bool AVRDAGToDAGISel::selectMultiplication(llvm::SDNode *N) { 473 SDLoc DL(N); 474 MVT Type = N->getSimpleValueType(0); 475 476 assert(Type == MVT::i8 && "unexpected value type"); 477 478 bool isSigned = N->getOpcode() == ISD::SMUL_LOHI; 479 unsigned MachineOp = isSigned ? AVR::MULSRdRr : AVR::MULRdRr; 480 481 SDValue Lhs = N->getOperand(0); 482 SDValue Rhs = N->getOperand(1); 483 SDNode *Mul = CurDAG->getMachineNode(MachineOp, DL, MVT::Glue, Lhs, Rhs); 484 SDValue InChain = CurDAG->getEntryNode(); 485 SDValue InGlue = SDValue(Mul, 0); 486 487 // Copy the low half of the result, if it is needed. 488 if (N->hasAnyUseOfValue(0)) { 489 SDValue CopyFromLo = 490 CurDAG->getCopyFromReg(InChain, DL, AVR::R0, Type, InGlue); 491 492 ReplaceUses(SDValue(N, 0), CopyFromLo); 493 494 InChain = CopyFromLo.getValue(1); 495 InGlue = CopyFromLo.getValue(2); 496 } 497 498 // Copy the high half of the result, if it is needed. 499 if (N->hasAnyUseOfValue(1)) { 500 SDValue CopyFromHi = 501 CurDAG->getCopyFromReg(InChain, DL, AVR::R1, Type, InGlue); 502 503 ReplaceUses(SDValue(N, 1), CopyFromHi); 504 505 InChain = CopyFromHi.getValue(1); 506 InGlue = CopyFromHi.getValue(2); 507 } 508 509 CurDAG->RemoveDeadNode(N); 510 511 // We need to clear R1. This is currently done (dirtily) 512 // using a custom inserter. 513 514 return true; 515 } 516 517 void AVRDAGToDAGISel::Select(SDNode *N) { 518 // If we have a custom node, we already have selected! 519 if (N->isMachineOpcode()) { 520 LLVM_DEBUG(errs() << "== "; N->dump(CurDAG); errs() << "\n"); 521 N->setNodeId(-1); 522 return; 523 } 524 525 // See if subclasses can handle this node. 526 if (trySelect(N)) 527 return; 528 529 // Select the default instruction 530 SelectCode(N); 531 } 532 533 bool AVRDAGToDAGISel::trySelect(SDNode *N) { 534 unsigned Opcode = N->getOpcode(); 535 SDLoc DL(N); 536 537 switch (Opcode) { 538 // Nodes we fully handle. 539 case ISD::FrameIndex: return select<ISD::FrameIndex>(N); 540 case ISD::BRIND: return select<ISD::BRIND>(N); 541 case ISD::UMUL_LOHI: 542 case ISD::SMUL_LOHI: return selectMultiplication(N); 543 544 // Nodes we handle partially. Other cases are autogenerated 545 case ISD::STORE: return select<ISD::STORE>(N); 546 case ISD::LOAD: return select<ISD::LOAD>(N); 547 case AVRISD::CALL: return select<AVRISD::CALL>(N); 548 default: return false; 549 } 550 } 551 552 FunctionPass *createAVRISelDag(AVRTargetMachine &TM, 553 CodeGenOpt::Level OptLevel) { 554 return new AVRDAGToDAGISel(TM, OptLevel); 555 } 556 557 } // end of namespace llvm 558 559