Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/AVRInstrInfo.cpp
35294 views
//===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the AVR implementation of the TargetInstrInfo class.9//10//===----------------------------------------------------------------------===//1112#include "AVRInstrInfo.h"1314#include "llvm/ADT/STLExtras.h"15#include "llvm/CodeGen/MachineConstantPool.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineInstrBuilder.h"18#include "llvm/CodeGen/MachineMemOperand.h"19#include "llvm/IR/Constants.h"20#include "llvm/IR/Function.h"21#include "llvm/MC/MCContext.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/Debug.h"24#include "llvm/Support/ErrorHandling.h"2526#include "AVR.h"27#include "AVRMachineFunctionInfo.h"28#include "AVRRegisterInfo.h"29#include "AVRTargetMachine.h"30#include "MCTargetDesc/AVRMCTargetDesc.h"3132#define GET_INSTRINFO_CTOR_DTOR33#include "AVRGenInstrInfo.inc"3435namespace llvm {3637AVRInstrInfo::AVRInstrInfo(AVRSubtarget &STI)38: AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI(),39STI(STI) {}4041void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,42MachineBasicBlock::iterator MI,43const DebugLoc &DL, MCRegister DestReg,44MCRegister SrcReg, bool KillSrc) const {45const AVRRegisterInfo &TRI = *STI.getRegisterInfo();46unsigned Opc;4748if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {49// If our AVR has `movw`, let's emit that; otherwise let's emit two separate50// `mov`s.51if (STI.hasMOVW() && AVR::DREGSMOVWRegClass.contains(DestReg, SrcReg)) {52BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)53.addReg(SrcReg, getKillRegState(KillSrc));54} else {55Register DestLo, DestHi, SrcLo, SrcHi;5657TRI.splitReg(DestReg, DestLo, DestHi);58TRI.splitReg(SrcReg, SrcLo, SrcHi);5960// Emit the copies.61// The original instruction was for a register pair, of which only one62// register might have been live. Add 'undef' to satisfy the machine63// verifier, when subreg liveness is enabled.64// TODO: Eliminate these unnecessary copies.65if (DestLo == SrcHi) {66BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)67.addReg(SrcHi, getKillRegState(KillSrc) | RegState::Undef);68BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)69.addReg(SrcLo, getKillRegState(KillSrc) | RegState::Undef);70} else {71BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)72.addReg(SrcLo, getKillRegState(KillSrc) | RegState::Undef);73BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)74.addReg(SrcHi, getKillRegState(KillSrc) | RegState::Undef);75}76}77} else {78if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {79Opc = AVR::MOVRdRr;80} else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {81Opc = AVR::SPREAD;82} else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {83Opc = AVR::SPWRITE;84} else {85llvm_unreachable("Impossible reg-to-reg copy");86}8788BuildMI(MBB, MI, DL, get(Opc), DestReg)89.addReg(SrcReg, getKillRegState(KillSrc));90}91}9293Register AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,94int &FrameIndex) const {95switch (MI.getOpcode()) {96case AVR::LDDRdPtrQ:97case AVR::LDDWRdYQ: { //: FIXME: remove this once PR13375 gets fixed98if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&99MI.getOperand(2).getImm() == 0) {100FrameIndex = MI.getOperand(1).getIndex();101return MI.getOperand(0).getReg();102}103break;104}105default:106break;107}108109return 0;110}111112Register AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,113int &FrameIndex) const {114switch (MI.getOpcode()) {115case AVR::STDPtrQRr:116case AVR::STDWPtrQRr: {117if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&118MI.getOperand(1).getImm() == 0) {119FrameIndex = MI.getOperand(0).getIndex();120return MI.getOperand(2).getReg();121}122break;123}124default:125break;126}127128return 0;129}130131void AVRInstrInfo::storeRegToStackSlot(132MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,133bool isKill, int FrameIndex, const TargetRegisterClass *RC,134const TargetRegisterInfo *TRI, Register VReg) const {135MachineFunction &MF = *MBB.getParent();136AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();137138AFI->setHasSpills(true);139140const MachineFrameInfo &MFI = MF.getFrameInfo();141142MachineMemOperand *MMO = MF.getMachineMemOperand(143MachinePointerInfo::getFixedStack(MF, FrameIndex),144MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),145MFI.getObjectAlign(FrameIndex));146147unsigned Opcode = 0;148if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {149Opcode = AVR::STDPtrQRr;150} else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {151Opcode = AVR::STDWPtrQRr;152} else {153llvm_unreachable("Cannot store this register into a stack slot!");154}155156BuildMI(MBB, MI, DebugLoc(), get(Opcode))157.addFrameIndex(FrameIndex)158.addImm(0)159.addReg(SrcReg, getKillRegState(isKill))160.addMemOperand(MMO);161}162163void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,164MachineBasicBlock::iterator MI,165Register DestReg, int FrameIndex,166const TargetRegisterClass *RC,167const TargetRegisterInfo *TRI,168Register VReg) const {169MachineFunction &MF = *MBB.getParent();170const MachineFrameInfo &MFI = MF.getFrameInfo();171172MachineMemOperand *MMO = MF.getMachineMemOperand(173MachinePointerInfo::getFixedStack(MF, FrameIndex),174MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),175MFI.getObjectAlign(FrameIndex));176177unsigned Opcode = 0;178if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {179Opcode = AVR::LDDRdPtrQ;180} else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {181// Opcode = AVR::LDDWRdPtrQ;182//: FIXME: remove this once PR13375 gets fixed183Opcode = AVR::LDDWRdYQ;184} else {185llvm_unreachable("Cannot load this register from a stack slot!");186}187188BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)189.addFrameIndex(FrameIndex)190.addImm(0)191.addMemOperand(MMO);192}193194const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {195switch (CC) {196default:197llvm_unreachable("Unknown condition code!");198case AVRCC::COND_EQ:199return get(AVR::BREQk);200case AVRCC::COND_NE:201return get(AVR::BRNEk);202case AVRCC::COND_GE:203return get(AVR::BRGEk);204case AVRCC::COND_LT:205return get(AVR::BRLTk);206case AVRCC::COND_SH:207return get(AVR::BRSHk);208case AVRCC::COND_LO:209return get(AVR::BRLOk);210case AVRCC::COND_MI:211return get(AVR::BRMIk);212case AVRCC::COND_PL:213return get(AVR::BRPLk);214}215}216217AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {218switch (Opc) {219default:220return AVRCC::COND_INVALID;221case AVR::BREQk:222return AVRCC::COND_EQ;223case AVR::BRNEk:224return AVRCC::COND_NE;225case AVR::BRSHk:226return AVRCC::COND_SH;227case AVR::BRLOk:228return AVRCC::COND_LO;229case AVR::BRMIk:230return AVRCC::COND_MI;231case AVR::BRPLk:232return AVRCC::COND_PL;233case AVR::BRGEk:234return AVRCC::COND_GE;235case AVR::BRLTk:236return AVRCC::COND_LT;237}238}239240AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {241switch (CC) {242default:243llvm_unreachable("Invalid condition!");244case AVRCC::COND_EQ:245return AVRCC::COND_NE;246case AVRCC::COND_NE:247return AVRCC::COND_EQ;248case AVRCC::COND_SH:249return AVRCC::COND_LO;250case AVRCC::COND_LO:251return AVRCC::COND_SH;252case AVRCC::COND_GE:253return AVRCC::COND_LT;254case AVRCC::COND_LT:255return AVRCC::COND_GE;256case AVRCC::COND_MI:257return AVRCC::COND_PL;258case AVRCC::COND_PL:259return AVRCC::COND_MI;260}261}262263bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,264MachineBasicBlock *&TBB,265MachineBasicBlock *&FBB,266SmallVectorImpl<MachineOperand> &Cond,267bool AllowModify) const {268// Start from the bottom of the block and work up, examining the269// terminator instructions.270MachineBasicBlock::iterator I = MBB.end();271MachineBasicBlock::iterator UnCondBrIter = MBB.end();272273while (I != MBB.begin()) {274--I;275if (I->isDebugInstr()) {276continue;277}278279// Working from the bottom, when we see a non-terminator280// instruction, we're done.281if (!isUnpredicatedTerminator(*I)) {282break;283}284285// A terminator that isn't a branch can't easily be handled286// by this analysis.287if (!I->getDesc().isBranch()) {288return true;289}290291// Handle unconditional branches.292//: TODO: add here jmp293if (I->getOpcode() == AVR::RJMPk) {294UnCondBrIter = I;295296if (!AllowModify) {297TBB = I->getOperand(0).getMBB();298continue;299}300301// If the block has any instructions after a JMP, delete them.302MBB.erase(std::next(I), MBB.end());303304Cond.clear();305FBB = nullptr;306307// Delete the JMP if it's equivalent to a fall-through.308if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {309TBB = nullptr;310I->eraseFromParent();311I = MBB.end();312UnCondBrIter = MBB.end();313continue;314}315316// TBB is used to indicate the unconditinal destination.317TBB = I->getOperand(0).getMBB();318continue;319}320321// Handle conditional branches.322AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());323if (BranchCode == AVRCC::COND_INVALID) {324return true; // Can't handle indirect branch.325}326327// Working from the bottom, handle the first conditional branch.328if (Cond.empty()) {329MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();330if (AllowModify && UnCondBrIter != MBB.end() &&331MBB.isLayoutSuccessor(TargetBB)) {332// If we can modify the code and it ends in something like:333//334// jCC L1335// jmp L2336// L1:337// ...338// L2:339//340// Then we can change this to:341//342// jnCC L2343// L1:344// ...345// L2:346//347// Which is a bit more efficient.348// We conditionally jump to the fall-through block.349BranchCode = getOppositeCondition(BranchCode);350unsigned JNCC = getBrCond(BranchCode).getOpcode();351MachineBasicBlock::iterator OldInst = I;352353BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))354.addMBB(UnCondBrIter->getOperand(0).getMBB());355BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))356.addMBB(TargetBB);357358OldInst->eraseFromParent();359UnCondBrIter->eraseFromParent();360361// Restart the analysis.362UnCondBrIter = MBB.end();363I = MBB.end();364continue;365}366367FBB = TBB;368TBB = I->getOperand(0).getMBB();369Cond.push_back(MachineOperand::CreateImm(BranchCode));370continue;371}372373// Handle subsequent conditional branches. Only handle the case where all374// conditional branches branch to the same destination.375assert(Cond.size() == 1);376assert(TBB);377378// Only handle the case where all conditional branches branch to379// the same destination.380if (TBB != I->getOperand(0).getMBB()) {381return true;382}383384AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();385// If the conditions are the same, we can leave them alone.386if (OldBranchCode == BranchCode) {387continue;388}389390return true;391}392393return false;394}395396unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,397MachineBasicBlock *TBB,398MachineBasicBlock *FBB,399ArrayRef<MachineOperand> Cond,400const DebugLoc &DL, int *BytesAdded) const {401if (BytesAdded)402*BytesAdded = 0;403404// Shouldn't be a fall through.405assert(TBB && "insertBranch must not be told to insert a fallthrough");406assert((Cond.size() == 1 || Cond.size() == 0) &&407"AVR branch conditions have one component!");408409if (Cond.empty()) {410assert(!FBB && "Unconditional branch with multiple successors!");411auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);412if (BytesAdded)413*BytesAdded += getInstSizeInBytes(MI);414return 1;415}416417// Conditional branch.418unsigned Count = 0;419AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();420auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);421422if (BytesAdded)423*BytesAdded += getInstSizeInBytes(CondMI);424++Count;425426if (FBB) {427// Two-way Conditional branch. Insert the second branch.428auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);429if (BytesAdded)430*BytesAdded += getInstSizeInBytes(MI);431++Count;432}433434return Count;435}436437unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,438int *BytesRemoved) const {439if (BytesRemoved)440*BytesRemoved = 0;441442MachineBasicBlock::iterator I = MBB.end();443unsigned Count = 0;444445while (I != MBB.begin()) {446--I;447if (I->isDebugInstr()) {448continue;449}450//: TODO: add here the missing jmp instructions once they are implemented451// like jmp, {e}ijmp, and other cond branches, ...452if (I->getOpcode() != AVR::RJMPk &&453getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {454break;455}456457// Remove the branch.458if (BytesRemoved)459*BytesRemoved += getInstSizeInBytes(*I);460I->eraseFromParent();461I = MBB.end();462++Count;463}464465return Count;466}467468bool AVRInstrInfo::reverseBranchCondition(469SmallVectorImpl<MachineOperand> &Cond) const {470assert(Cond.size() == 1 && "Invalid AVR branch condition!");471472AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());473Cond[0].setImm(getOppositeCondition(CC));474475return false;476}477478unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {479unsigned Opcode = MI.getOpcode();480481switch (Opcode) {482// A regular instruction483default: {484const MCInstrDesc &Desc = get(Opcode);485return Desc.getSize();486}487case TargetOpcode::EH_LABEL:488case TargetOpcode::IMPLICIT_DEF:489case TargetOpcode::KILL:490case TargetOpcode::DBG_VALUE:491return 0;492case TargetOpcode::INLINEASM:493case TargetOpcode::INLINEASM_BR: {494const MachineFunction &MF = *MI.getParent()->getParent();495const AVRTargetMachine &TM =496static_cast<const AVRTargetMachine &>(MF.getTarget());497const TargetInstrInfo &TII = *STI.getInstrInfo();498return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),499*TM.getMCAsmInfo());500}501}502}503504MachineBasicBlock *505AVRInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {506switch (MI.getOpcode()) {507default:508llvm_unreachable("unexpected opcode!");509case AVR::JMPk:510case AVR::CALLk:511case AVR::RCALLk:512case AVR::RJMPk:513case AVR::BREQk:514case AVR::BRNEk:515case AVR::BRSHk:516case AVR::BRLOk:517case AVR::BRMIk:518case AVR::BRPLk:519case AVR::BRGEk:520case AVR::BRLTk:521return MI.getOperand(0).getMBB();522case AVR::BRBSsk:523case AVR::BRBCsk:524return MI.getOperand(1).getMBB();525case AVR::SBRCRrB:526case AVR::SBRSRrB:527case AVR::SBICAb:528case AVR::SBISAb:529llvm_unreachable("unimplemented branch instructions");530}531}532533bool AVRInstrInfo::isBranchOffsetInRange(unsigned BranchOp,534int64_t BrOffset) const {535536switch (BranchOp) {537default:538llvm_unreachable("unexpected opcode!");539case AVR::JMPk:540case AVR::CALLk:541return STI.hasJMPCALL();542case AVR::RCALLk:543case AVR::RJMPk:544return isIntN(13, BrOffset);545case AVR::BRBSsk:546case AVR::BRBCsk:547case AVR::BREQk:548case AVR::BRNEk:549case AVR::BRSHk:550case AVR::BRLOk:551case AVR::BRMIk:552case AVR::BRPLk:553case AVR::BRGEk:554case AVR::BRLTk:555return isIntN(7, BrOffset);556}557}558559void AVRInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,560MachineBasicBlock &NewDestBB,561MachineBasicBlock &RestoreBB,562const DebugLoc &DL, int64_t BrOffset,563RegScavenger *RS) const {564// This method inserts a *direct* branch (JMP), despite its name.565// LLVM calls this method to fixup unconditional branches; it never calls566// insertBranch or some hypothetical "insertDirectBranch".567// See lib/CodeGen/RegisterRelaxation.cpp for details.568// We end up here when a jump is too long for a RJMP instruction.569if (STI.hasJMPCALL())570BuildMI(&MBB, DL, get(AVR::JMPk)).addMBB(&NewDestBB);571else572// The RJMP may jump to a far place beyond its legal range. We let the573// linker to report 'out of range' rather than crash, or silently emit574// incorrect assembly code.575BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(&NewDestBB);576}577578} // end of namespace llvm579580581