575 lines · cpp
1//===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the AVR implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "AVRInstrInfo.h"14 15#include "llvm/CodeGen/MachineFrameInfo.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineMemOperand.h"18#include "llvm/MC/MCContext.h"19#include "llvm/Support/ErrorHandling.h"20 21#include "AVR.h"22#include "AVRMachineFunctionInfo.h"23#include "AVRRegisterInfo.h"24#include "AVRTargetMachine.h"25#include "MCTargetDesc/AVRMCTargetDesc.h"26 27#define GET_INSTRINFO_CTOR_DTOR28#include "AVRGenInstrInfo.inc"29 30namespace llvm {31 32AVRInstrInfo::AVRInstrInfo(const AVRSubtarget &STI)33 : AVRGenInstrInfo(STI, RI, AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP),34 RI(), STI(STI) {}35 36void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,37 MachineBasicBlock::iterator MI,38 const DebugLoc &DL, Register DestReg,39 Register SrcReg, bool KillSrc,40 bool RenamableDest, bool RenamableSrc) const {41 const AVRRegisterInfo &TRI = *STI.getRegisterInfo();42 unsigned Opc;43 44 if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {45 // If our AVR has `movw`, let's emit that; otherwise let's emit two separate46 // `mov`s.47 if (STI.hasMOVW() && AVR::DREGSMOVWRegClass.contains(DestReg, SrcReg)) {48 BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)49 .addReg(SrcReg, getKillRegState(KillSrc));50 } else {51 Register DestLo, DestHi, SrcLo, SrcHi;52 53 TRI.splitReg(DestReg, DestLo, DestHi);54 TRI.splitReg(SrcReg, SrcLo, SrcHi);55 56 // Emit the copies.57 // The original instruction was for a register pair, of which only one58 // register might have been live. Add 'undef' to satisfy the machine59 // verifier, when subreg liveness is enabled.60 // TODO: Eliminate these unnecessary copies.61 if (DestLo == SrcHi) {62 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)63 .addReg(SrcHi, getKillRegState(KillSrc) | RegState::Undef);64 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)65 .addReg(SrcLo, getKillRegState(KillSrc) | RegState::Undef);66 } else {67 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)68 .addReg(SrcLo, getKillRegState(KillSrc) | RegState::Undef);69 BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)70 .addReg(SrcHi, getKillRegState(KillSrc) | RegState::Undef);71 }72 }73 } else {74 if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {75 Opc = AVR::MOVRdRr;76 } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {77 Opc = AVR::SPREAD;78 } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {79 Opc = AVR::SPWRITE;80 } else {81 llvm_unreachable("Impossible reg-to-reg copy");82 }83 84 BuildMI(MBB, MI, DL, get(Opc), DestReg)85 .addReg(SrcReg, getKillRegState(KillSrc));86 }87}88 89Register AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,90 int &FrameIndex) const {91 switch (MI.getOpcode()) {92 case AVR::LDDRdPtrQ:93 case AVR::LDDWRdYQ: { //: FIXME: remove this once PR13375 gets fixed94 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&95 MI.getOperand(2).getImm() == 0) {96 FrameIndex = MI.getOperand(1).getIndex();97 return MI.getOperand(0).getReg();98 }99 break;100 }101 default:102 break;103 }104 105 return 0;106}107 108Register AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,109 int &FrameIndex) const {110 switch (MI.getOpcode()) {111 case AVR::STDPtrQRr:112 case AVR::STDWPtrQRr: {113 if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&114 MI.getOperand(1).getImm() == 0) {115 FrameIndex = MI.getOperand(0).getIndex();116 return MI.getOperand(2).getReg();117 }118 break;119 }120 default:121 break;122 }123 124 return 0;125}126 127void AVRInstrInfo::storeRegToStackSlot(128 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,129 bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,130 MachineInstr::MIFlag Flags) const {131 MachineFunction &MF = *MBB.getParent();132 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();133 134 AFI->setHasSpills(true);135 136 const MachineFrameInfo &MFI = MF.getFrameInfo();137 138 MachineMemOperand *MMO = MF.getMachineMemOperand(139 MachinePointerInfo::getFixedStack(MF, FrameIndex),140 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),141 MFI.getObjectAlign(FrameIndex));142 143 unsigned Opcode = 0;144 if (RI.isTypeLegalForClass(*RC, MVT::i8)) {145 Opcode = AVR::STDPtrQRr;146 } else if (RI.isTypeLegalForClass(*RC, MVT::i16)) {147 Opcode = AVR::STDWPtrQRr;148 } else {149 llvm_unreachable("Cannot store this register into a stack slot!");150 }151 152 BuildMI(MBB, MI, DebugLoc(), get(Opcode))153 .addFrameIndex(FrameIndex)154 .addImm(0)155 .addReg(SrcReg, getKillRegState(isKill))156 .addMemOperand(MMO);157}158 159void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,160 MachineBasicBlock::iterator MI,161 Register DestReg, int FrameIndex,162 const TargetRegisterClass *RC,163 Register VReg,164 MachineInstr::MIFlag Flags) const {165 MachineFunction &MF = *MBB.getParent();166 const MachineFrameInfo &MFI = MF.getFrameInfo();167 168 MachineMemOperand *MMO = MF.getMachineMemOperand(169 MachinePointerInfo::getFixedStack(MF, FrameIndex),170 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),171 MFI.getObjectAlign(FrameIndex));172 173 unsigned Opcode = 0;174 if (TRI.isTypeLegalForClass(*RC, MVT::i8)) {175 Opcode = AVR::LDDRdPtrQ;176 } else if (TRI.isTypeLegalForClass(*RC, MVT::i16)) {177 // Opcode = AVR::LDDWRdPtrQ;178 //: FIXME: remove this once PR13375 gets fixed179 Opcode = AVR::LDDWRdYQ;180 } else {181 llvm_unreachable("Cannot load this register from a stack slot!");182 }183 184 BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)185 .addFrameIndex(FrameIndex)186 .addImm(0)187 .addMemOperand(MMO);188}189 190const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {191 switch (CC) {192 default:193 llvm_unreachable("Unknown condition code!");194 case AVRCC::COND_EQ:195 return get(AVR::BREQk);196 case AVRCC::COND_NE:197 return get(AVR::BRNEk);198 case AVRCC::COND_GE:199 return get(AVR::BRGEk);200 case AVRCC::COND_LT:201 return get(AVR::BRLTk);202 case AVRCC::COND_SH:203 return get(AVR::BRSHk);204 case AVRCC::COND_LO:205 return get(AVR::BRLOk);206 case AVRCC::COND_MI:207 return get(AVR::BRMIk);208 case AVRCC::COND_PL:209 return get(AVR::BRPLk);210 }211}212 213AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {214 switch (Opc) {215 default:216 return AVRCC::COND_INVALID;217 case AVR::BREQk:218 return AVRCC::COND_EQ;219 case AVR::BRNEk:220 return AVRCC::COND_NE;221 case AVR::BRSHk:222 return AVRCC::COND_SH;223 case AVR::BRLOk:224 return AVRCC::COND_LO;225 case AVR::BRMIk:226 return AVRCC::COND_MI;227 case AVR::BRPLk:228 return AVRCC::COND_PL;229 case AVR::BRGEk:230 return AVRCC::COND_GE;231 case AVR::BRLTk:232 return AVRCC::COND_LT;233 }234}235 236AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {237 switch (CC) {238 default:239 llvm_unreachable("Invalid condition!");240 case AVRCC::COND_EQ:241 return AVRCC::COND_NE;242 case AVRCC::COND_NE:243 return AVRCC::COND_EQ;244 case AVRCC::COND_SH:245 return AVRCC::COND_LO;246 case AVRCC::COND_LO:247 return AVRCC::COND_SH;248 case AVRCC::COND_GE:249 return AVRCC::COND_LT;250 case AVRCC::COND_LT:251 return AVRCC::COND_GE;252 case AVRCC::COND_MI:253 return AVRCC::COND_PL;254 case AVRCC::COND_PL:255 return AVRCC::COND_MI;256 }257}258 259bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,260 MachineBasicBlock *&TBB,261 MachineBasicBlock *&FBB,262 SmallVectorImpl<MachineOperand> &Cond,263 bool AllowModify) const {264 // Start from the bottom of the block and work up, examining the265 // terminator instructions.266 MachineBasicBlock::iterator I = MBB.end();267 MachineBasicBlock::iterator UnCondBrIter = MBB.end();268 269 while (I != MBB.begin()) {270 --I;271 if (I->isDebugInstr()) {272 continue;273 }274 275 // Working from the bottom, when we see a non-terminator276 // instruction, we're done.277 if (!isUnpredicatedTerminator(*I)) {278 break;279 }280 281 // A terminator that isn't a branch can't easily be handled282 // by this analysis.283 if (!I->getDesc().isBranch()) {284 return true;285 }286 287 // Handle unconditional branches.288 //: TODO: add here jmp289 if (I->getOpcode() == AVR::RJMPk) {290 UnCondBrIter = I;291 292 if (!AllowModify) {293 TBB = I->getOperand(0).getMBB();294 continue;295 }296 297 // If the block has any instructions after a JMP, delete them.298 MBB.erase(std::next(I), MBB.end());299 300 Cond.clear();301 FBB = nullptr;302 303 // Delete the JMP if it's equivalent to a fall-through.304 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {305 TBB = nullptr;306 I->eraseFromParent();307 I = MBB.end();308 UnCondBrIter = MBB.end();309 continue;310 }311 312 // TBB is used to indicate the unconditinal destination.313 TBB = I->getOperand(0).getMBB();314 continue;315 }316 317 // Handle conditional branches.318 AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());319 if (BranchCode == AVRCC::COND_INVALID) {320 return true; // Can't handle indirect branch.321 }322 323 // Working from the bottom, handle the first conditional branch.324 if (Cond.empty()) {325 MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();326 if (AllowModify && UnCondBrIter != MBB.end() &&327 MBB.isLayoutSuccessor(TargetBB)) {328 // If we can modify the code and it ends in something like:329 //330 // jCC L1331 // jmp L2332 // L1:333 // ...334 // L2:335 //336 // Then we can change this to:337 //338 // jnCC L2339 // L1:340 // ...341 // L2:342 //343 // Which is a bit more efficient.344 // We conditionally jump to the fall-through block.345 BranchCode = getOppositeCondition(BranchCode);346 unsigned JNCC = getBrCond(BranchCode).getOpcode();347 MachineBasicBlock::iterator OldInst = I;348 349 BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))350 .addMBB(UnCondBrIter->getOperand(0).getMBB());351 BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))352 .addMBB(TargetBB);353 354 OldInst->eraseFromParent();355 UnCondBrIter->eraseFromParent();356 357 // Restart the analysis.358 UnCondBrIter = MBB.end();359 I = MBB.end();360 continue;361 }362 363 FBB = TBB;364 TBB = I->getOperand(0).getMBB();365 Cond.push_back(MachineOperand::CreateImm(BranchCode));366 continue;367 }368 369 // Handle subsequent conditional branches. Only handle the case where all370 // conditional branches branch to the same destination.371 assert(Cond.size() == 1);372 assert(TBB);373 374 // Only handle the case where all conditional branches branch to375 // the same destination.376 if (TBB != I->getOperand(0).getMBB()) {377 return true;378 }379 380 AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();381 // If the conditions are the same, we can leave them alone.382 if (OldBranchCode == BranchCode) {383 continue;384 }385 386 return true;387 }388 389 return false;390}391 392unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,393 MachineBasicBlock *TBB,394 MachineBasicBlock *FBB,395 ArrayRef<MachineOperand> Cond,396 const DebugLoc &DL, int *BytesAdded) const {397 if (BytesAdded)398 *BytesAdded = 0;399 400 // Shouldn't be a fall through.401 assert(TBB && "insertBranch must not be told to insert a fallthrough");402 assert((Cond.size() == 1 || Cond.size() == 0) &&403 "AVR branch conditions have one component!");404 405 if (Cond.empty()) {406 assert(!FBB && "Unconditional branch with multiple successors!");407 auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);408 if (BytesAdded)409 *BytesAdded += getInstSizeInBytes(MI);410 return 1;411 }412 413 // Conditional branch.414 unsigned Count = 0;415 AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();416 auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);417 418 if (BytesAdded)419 *BytesAdded += getInstSizeInBytes(CondMI);420 ++Count;421 422 if (FBB) {423 // Two-way Conditional branch. Insert the second branch.424 auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);425 if (BytesAdded)426 *BytesAdded += getInstSizeInBytes(MI);427 ++Count;428 }429 430 return Count;431}432 433unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,434 int *BytesRemoved) const {435 if (BytesRemoved)436 *BytesRemoved = 0;437 438 MachineBasicBlock::iterator I = MBB.end();439 unsigned Count = 0;440 441 while (I != MBB.begin()) {442 --I;443 if (I->isDebugInstr()) {444 continue;445 }446 //: TODO: add here the missing jmp instructions once they are implemented447 // like jmp, {e}ijmp, and other cond branches, ...448 if (I->getOpcode() != AVR::RJMPk &&449 getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {450 break;451 }452 453 // Remove the branch.454 if (BytesRemoved)455 *BytesRemoved += getInstSizeInBytes(*I);456 I->eraseFromParent();457 I = MBB.end();458 ++Count;459 }460 461 return Count;462}463 464bool AVRInstrInfo::reverseBranchCondition(465 SmallVectorImpl<MachineOperand> &Cond) const {466 assert(Cond.size() == 1 && "Invalid AVR branch condition!");467 468 AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());469 Cond[0].setImm(getOppositeCondition(CC));470 471 return false;472}473 474unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {475 unsigned Opcode = MI.getOpcode();476 477 switch (Opcode) {478 // A regular instruction479 default: {480 const MCInstrDesc &Desc = get(Opcode);481 return Desc.getSize();482 }483 case TargetOpcode::EH_LABEL:484 case TargetOpcode::IMPLICIT_DEF:485 case TargetOpcode::KILL:486 case TargetOpcode::DBG_VALUE:487 return 0;488 case TargetOpcode::INLINEASM:489 case TargetOpcode::INLINEASM_BR: {490 const MachineFunction &MF = *MI.getParent()->getParent();491 const AVRTargetMachine &TM =492 static_cast<const AVRTargetMachine &>(MF.getTarget());493 const TargetInstrInfo &TII = *STI.getInstrInfo();494 return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),495 *TM.getMCAsmInfo());496 }497 }498}499 500MachineBasicBlock *501AVRInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {502 switch (MI.getOpcode()) {503 default:504 llvm_unreachable("unexpected opcode!");505 case AVR::JMPk:506 case AVR::CALLk:507 case AVR::RCALLk:508 case AVR::RJMPk:509 case AVR::BREQk:510 case AVR::BRNEk:511 case AVR::BRSHk:512 case AVR::BRLOk:513 case AVR::BRMIk:514 case AVR::BRPLk:515 case AVR::BRGEk:516 case AVR::BRLTk:517 return MI.getOperand(0).getMBB();518 case AVR::BRBSsk:519 case AVR::BRBCsk:520 return MI.getOperand(1).getMBB();521 case AVR::SBRCRrB:522 case AVR::SBRSRrB:523 case AVR::SBICAb:524 case AVR::SBISAb:525 llvm_unreachable("unimplemented branch instructions");526 }527}528 529bool AVRInstrInfo::isBranchOffsetInRange(unsigned BranchOp,530 int64_t BrOffset) const {531 532 switch (BranchOp) {533 default:534 llvm_unreachable("unexpected opcode!");535 case AVR::JMPk:536 case AVR::CALLk:537 return STI.hasJMPCALL();538 case AVR::RCALLk:539 case AVR::RJMPk:540 return isIntN(13, BrOffset);541 case AVR::BRBSsk:542 case AVR::BRBCsk:543 case AVR::BREQk:544 case AVR::BRNEk:545 case AVR::BRSHk:546 case AVR::BRLOk:547 case AVR::BRMIk:548 case AVR::BRPLk:549 case AVR::BRGEk:550 case AVR::BRLTk:551 return isIntN(7, BrOffset);552 }553}554 555void AVRInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,556 MachineBasicBlock &NewDestBB,557 MachineBasicBlock &RestoreBB,558 const DebugLoc &DL, int64_t BrOffset,559 RegScavenger *RS) const {560 // This method inserts a *direct* branch (JMP), despite its name.561 // LLVM calls this method to fixup unconditional branches; it never calls562 // insertBranch or some hypothetical "insertDirectBranch".563 // See lib/CodeGen/RegisterRelaxation.cpp for details.564 // We end up here when a jump is too long for a RJMP instruction.565 if (STI.hasJMPCALL())566 BuildMI(&MBB, DL, get(AVR::JMPk)).addMBB(&NewDestBB);567 else568 // The RJMP may jump to a far place beyond its legal range. We let the569 // linker to report 'out of range' rather than crash, or silently emit570 // incorrect assembly code.571 BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(&NewDestBB);572}573 574} // end of namespace llvm575