16d8078f9SDylan McKay //===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//
26d8078f9SDylan McKay //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66d8078f9SDylan McKay //
76d8078f9SDylan McKay //===----------------------------------------------------------------------===//
86d8078f9SDylan McKay //
96d8078f9SDylan McKay // This file contains the AVR implementation of the TargetInstrInfo class.
106d8078f9SDylan McKay //
116d8078f9SDylan McKay //===----------------------------------------------------------------------===//
126d8078f9SDylan McKay 
136d8078f9SDylan McKay #include "AVRInstrInfo.h"
146d8078f9SDylan McKay 
156d8078f9SDylan McKay #include "llvm/ADT/STLExtras.h"
166d8078f9SDylan McKay #include "llvm/CodeGen/MachineConstantPool.h"
176d8078f9SDylan McKay #include "llvm/CodeGen/MachineFrameInfo.h"
186d8078f9SDylan McKay #include "llvm/CodeGen/MachineInstrBuilder.h"
196d8078f9SDylan McKay #include "llvm/CodeGen/MachineMemOperand.h"
206d8078f9SDylan McKay #include "llvm/IR/Constants.h"
216d8078f9SDylan McKay #include "llvm/IR/Function.h"
226d8078f9SDylan McKay #include "llvm/MC/MCContext.h"
2389b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
246d8078f9SDylan McKay #include "llvm/Support/Debug.h"
256d8078f9SDylan McKay #include "llvm/Support/ErrorHandling.h"
266d8078f9SDylan McKay 
276d8078f9SDylan McKay #include "AVR.h"
286d8078f9SDylan McKay #include "AVRMachineFunctionInfo.h"
29afff169fSDylan McKay #include "AVRRegisterInfo.h"
306d8078f9SDylan McKay #include "AVRTargetMachine.h"
316d8078f9SDylan McKay #include "MCTargetDesc/AVRMCTargetDesc.h"
326d8078f9SDylan McKay 
336d8078f9SDylan McKay #define GET_INSTRINFO_CTOR_DTOR
346d8078f9SDylan McKay #include "AVRGenInstrInfo.inc"
356d8078f9SDylan McKay 
366d8078f9SDylan McKay namespace llvm {
376d8078f9SDylan McKay 
AVRInstrInfo()386d8078f9SDylan McKay AVRInstrInfo::AVRInstrInfo()
396d8078f9SDylan McKay     : AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI() {}
406d8078f9SDylan McKay 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const416d8078f9SDylan McKay void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
42bdc4956bSBenjamin Kramer                                MachineBasicBlock::iterator MI,
43e6c9a9afSMatt Arsenault                                const DebugLoc &DL, MCRegister DestReg,
44e6c9a9afSMatt Arsenault                                MCRegister SrcReg, bool KillSrc) const {
45afff169fSDylan McKay   const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
46afff169fSDylan McKay   const AVRRegisterInfo &TRI = *STI.getRegisterInfo();
476d8078f9SDylan McKay   unsigned Opc;
486d8078f9SDylan McKay 
49afff169fSDylan McKay   if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
50*5650688eSPatryk Wychowaniec     // If our AVR has `movw`, let's emit that; otherwise let's emit two separate
51*5650688eSPatryk Wychowaniec     // `mov`s.
52b9c26a9cSDylan McKay     if (STI.hasMOVW() && AVR::DREGSMOVWRegClass.contains(DestReg, SrcReg)) {
53afff169fSDylan McKay       BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)
54afff169fSDylan McKay           .addReg(SrcReg, getKillRegState(KillSrc));
55afff169fSDylan McKay     } else {
56ea6eb813SJim Lin       Register DestLo, DestHi, SrcLo, SrcHi;
57afff169fSDylan McKay 
58afff169fSDylan McKay       TRI.splitReg(DestReg, DestLo, DestHi);
59afff169fSDylan McKay       TRI.splitReg(SrcReg, SrcLo, SrcHi);
60afff169fSDylan McKay 
61*5650688eSPatryk Wychowaniec       if (DestLo == SrcHi) {
62*5650688eSPatryk Wychowaniec         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
63*5650688eSPatryk Wychowaniec             .addReg(SrcHi, getKillRegState(KillSrc));
64*5650688eSPatryk Wychowaniec         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
65*5650688eSPatryk Wychowaniec             .addReg(SrcLo, getKillRegState(KillSrc));
66*5650688eSPatryk Wychowaniec       } else {
67afff169fSDylan McKay         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
68afff169fSDylan McKay             .addReg(SrcLo, getKillRegState(KillSrc));
69afff169fSDylan McKay         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
70afff169fSDylan McKay             .addReg(SrcHi, getKillRegState(KillSrc));
71afff169fSDylan McKay       }
72*5650688eSPatryk Wychowaniec     }
73afff169fSDylan McKay   } else {
746d8078f9SDylan McKay     if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
756d8078f9SDylan McKay       Opc = AVR::MOVRdRr;
766d8078f9SDylan McKay     } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
776d8078f9SDylan McKay       Opc = AVR::SPREAD;
786d8078f9SDylan McKay     } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
796d8078f9SDylan McKay       Opc = AVR::SPWRITE;
806d8078f9SDylan McKay     } else {
816d8078f9SDylan McKay       llvm_unreachable("Impossible reg-to-reg copy");
826d8078f9SDylan McKay     }
836d8078f9SDylan McKay 
846d8078f9SDylan McKay     BuildMI(MBB, MI, DL, get(Opc), DestReg)
856d8078f9SDylan McKay         .addReg(SrcReg, getKillRegState(KillSrc));
866d8078f9SDylan McKay   }
87afff169fSDylan McKay }
886d8078f9SDylan McKay 
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const899cfc75c2SDuncan P. N. Exon Smith unsigned AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
906d8078f9SDylan McKay                                            int &FrameIndex) const {
919cfc75c2SDuncan P. N. Exon Smith   switch (MI.getOpcode()) {
926d8078f9SDylan McKay   case AVR::LDDRdPtrQ:
936d8078f9SDylan McKay   case AVR::LDDWRdYQ: { //: FIXME: remove this once PR13375 gets fixed
949cfc75c2SDuncan P. N. Exon Smith     if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
959cfc75c2SDuncan P. N. Exon Smith         MI.getOperand(2).getImm() == 0) {
969cfc75c2SDuncan P. N. Exon Smith       FrameIndex = MI.getOperand(1).getIndex();
979cfc75c2SDuncan P. N. Exon Smith       return MI.getOperand(0).getReg();
986d8078f9SDylan McKay     }
996d8078f9SDylan McKay     break;
1006d8078f9SDylan McKay   }
1016d8078f9SDylan McKay   default:
1026d8078f9SDylan McKay     break;
1036d8078f9SDylan McKay   }
1046d8078f9SDylan McKay 
1056d8078f9SDylan McKay   return 0;
1066d8078f9SDylan McKay }
1076d8078f9SDylan McKay 
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const1089cfc75c2SDuncan P. N. Exon Smith unsigned AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
1096d8078f9SDylan McKay                                           int &FrameIndex) const {
1109cfc75c2SDuncan P. N. Exon Smith   switch (MI.getOpcode()) {
1116d8078f9SDylan McKay   case AVR::STDPtrQRr:
1126d8078f9SDylan McKay   case AVR::STDWPtrQRr: {
1139cfc75c2SDuncan P. N. Exon Smith     if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
1149cfc75c2SDuncan P. N. Exon Smith         MI.getOperand(1).getImm() == 0) {
1159cfc75c2SDuncan P. N. Exon Smith       FrameIndex = MI.getOperand(0).getIndex();
1169cfc75c2SDuncan P. N. Exon Smith       return MI.getOperand(2).getReg();
1176d8078f9SDylan McKay     }
1186d8078f9SDylan McKay     break;
1196d8078f9SDylan McKay   }
1206d8078f9SDylan McKay   default:
1216d8078f9SDylan McKay     break;
1226d8078f9SDylan McKay   }
1236d8078f9SDylan McKay 
1246d8078f9SDylan McKay   return 0;
1256d8078f9SDylan McKay }
1266d8078f9SDylan McKay 
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,Register SrcReg,bool isKill,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const1276d8078f9SDylan McKay void AVRInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
1286d8078f9SDylan McKay                                        MachineBasicBlock::iterator MI,
1295c8ba508SSimon Moll                                        Register SrcReg, bool isKill,
1306d8078f9SDylan McKay                                        int FrameIndex,
1316d8078f9SDylan McKay                                        const TargetRegisterClass *RC,
1326d8078f9SDylan McKay                                        const TargetRegisterInfo *TRI) const {
1336d8078f9SDylan McKay   MachineFunction &MF = *MBB.getParent();
134afff169fSDylan McKay   AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
135afff169fSDylan McKay 
136afff169fSDylan McKay   AFI->setHasSpills(true);
1376d8078f9SDylan McKay 
1386d8078f9SDylan McKay   DebugLoc DL;
1396d8078f9SDylan McKay   if (MI != MBB.end()) {
1406d8078f9SDylan McKay     DL = MI->getDebugLoc();
1416d8078f9SDylan McKay   }
1426d8078f9SDylan McKay 
143941a705bSMatthias Braun   const MachineFrameInfo &MFI = MF.getFrameInfo();
1446d8078f9SDylan McKay 
1456d8078f9SDylan McKay   MachineMemOperand *MMO = MF.getMachineMemOperand(
1466d8078f9SDylan McKay       MachinePointerInfo::getFixedStack(MF, FrameIndex),
1476d8078f9SDylan McKay       MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
148c9d5c195SGuillaume Chatelet       MFI.getObjectAlign(FrameIndex));
1496d8078f9SDylan McKay 
1506d8078f9SDylan McKay   unsigned Opcode = 0;
151c8e8e2a0SKrzysztof Parzyszek   if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
1526d8078f9SDylan McKay     Opcode = AVR::STDPtrQRr;
153c8e8e2a0SKrzysztof Parzyszek   } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
1546d8078f9SDylan McKay     Opcode = AVR::STDWPtrQRr;
1556d8078f9SDylan McKay   } else {
1566d8078f9SDylan McKay     llvm_unreachable("Cannot store this register into a stack slot!");
1576d8078f9SDylan McKay   }
1586d8078f9SDylan McKay 
1596d8078f9SDylan McKay   BuildMI(MBB, MI, DL, get(Opcode))
1606d8078f9SDylan McKay       .addFrameIndex(FrameIndex)
1616d8078f9SDylan McKay       .addImm(0)
1626d8078f9SDylan McKay       .addReg(SrcReg, getKillRegState(isKill))
1636d8078f9SDylan McKay       .addMemOperand(MMO);
1646d8078f9SDylan McKay }
1656d8078f9SDylan McKay 
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,Register DestReg,int FrameIndex,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const1666d8078f9SDylan McKay void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
1676d8078f9SDylan McKay                                         MachineBasicBlock::iterator MI,
1685c8ba508SSimon Moll                                         Register DestReg, int FrameIndex,
1696d8078f9SDylan McKay                                         const TargetRegisterClass *RC,
1706d8078f9SDylan McKay                                         const TargetRegisterInfo *TRI) const {
1716d8078f9SDylan McKay   DebugLoc DL;
1726d8078f9SDylan McKay   if (MI != MBB.end()) {
1736d8078f9SDylan McKay     DL = MI->getDebugLoc();
1746d8078f9SDylan McKay   }
1756d8078f9SDylan McKay 
1766d8078f9SDylan McKay   MachineFunction &MF = *MBB.getParent();
177941a705bSMatthias Braun   const MachineFrameInfo &MFI = MF.getFrameInfo();
1786d8078f9SDylan McKay 
1796d8078f9SDylan McKay   MachineMemOperand *MMO = MF.getMachineMemOperand(
1806d8078f9SDylan McKay       MachinePointerInfo::getFixedStack(MF, FrameIndex),
1816d8078f9SDylan McKay       MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
182c9d5c195SGuillaume Chatelet       MFI.getObjectAlign(FrameIndex));
1836d8078f9SDylan McKay 
1846d8078f9SDylan McKay   unsigned Opcode = 0;
185c8e8e2a0SKrzysztof Parzyszek   if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
1866d8078f9SDylan McKay     Opcode = AVR::LDDRdPtrQ;
187c8e8e2a0SKrzysztof Parzyszek   } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
1886d8078f9SDylan McKay     // Opcode = AVR::LDDWRdPtrQ;
1896d8078f9SDylan McKay     //: FIXME: remove this once PR13375 gets fixed
1906d8078f9SDylan McKay     Opcode = AVR::LDDWRdYQ;
1916d8078f9SDylan McKay   } else {
1926d8078f9SDylan McKay     llvm_unreachable("Cannot load this register from a stack slot!");
1936d8078f9SDylan McKay   }
1946d8078f9SDylan McKay 
1956d8078f9SDylan McKay   BuildMI(MBB, MI, DL, get(Opcode), DestReg)
1966d8078f9SDylan McKay       .addFrameIndex(FrameIndex)
1976d8078f9SDylan McKay       .addImm(0)
1986d8078f9SDylan McKay       .addMemOperand(MMO);
1996d8078f9SDylan McKay }
2006d8078f9SDylan McKay 
getBrCond(AVRCC::CondCodes CC) const2016d8078f9SDylan McKay const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {
2026d8078f9SDylan McKay   switch (CC) {
2036d8078f9SDylan McKay   default:
2046d8078f9SDylan McKay     llvm_unreachable("Unknown condition code!");
2056d8078f9SDylan McKay   case AVRCC::COND_EQ:
2066d8078f9SDylan McKay     return get(AVR::BREQk);
2076d8078f9SDylan McKay   case AVRCC::COND_NE:
2086d8078f9SDylan McKay     return get(AVR::BRNEk);
2096d8078f9SDylan McKay   case AVRCC::COND_GE:
2106d8078f9SDylan McKay     return get(AVR::BRGEk);
2116d8078f9SDylan McKay   case AVRCC::COND_LT:
2126d8078f9SDylan McKay     return get(AVR::BRLTk);
2136d8078f9SDylan McKay   case AVRCC::COND_SH:
2146d8078f9SDylan McKay     return get(AVR::BRSHk);
2156d8078f9SDylan McKay   case AVRCC::COND_LO:
2166d8078f9SDylan McKay     return get(AVR::BRLOk);
2176d8078f9SDylan McKay   case AVRCC::COND_MI:
2186d8078f9SDylan McKay     return get(AVR::BRMIk);
2196d8078f9SDylan McKay   case AVRCC::COND_PL:
2206d8078f9SDylan McKay     return get(AVR::BRPLk);
2216d8078f9SDylan McKay   }
2226d8078f9SDylan McKay }
2236d8078f9SDylan McKay 
getCondFromBranchOpc(unsigned Opc) const2246d8078f9SDylan McKay AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
2256d8078f9SDylan McKay   switch (Opc) {
2266d8078f9SDylan McKay   default:
2276d8078f9SDylan McKay     return AVRCC::COND_INVALID;
2286d8078f9SDylan McKay   case AVR::BREQk:
2296d8078f9SDylan McKay     return AVRCC::COND_EQ;
2306d8078f9SDylan McKay   case AVR::BRNEk:
2316d8078f9SDylan McKay     return AVRCC::COND_NE;
2326d8078f9SDylan McKay   case AVR::BRSHk:
2336d8078f9SDylan McKay     return AVRCC::COND_SH;
2346d8078f9SDylan McKay   case AVR::BRLOk:
2356d8078f9SDylan McKay     return AVRCC::COND_LO;
2366d8078f9SDylan McKay   case AVR::BRMIk:
2376d8078f9SDylan McKay     return AVRCC::COND_MI;
2386d8078f9SDylan McKay   case AVR::BRPLk:
2396d8078f9SDylan McKay     return AVRCC::COND_PL;
2406d8078f9SDylan McKay   case AVR::BRGEk:
2416d8078f9SDylan McKay     return AVRCC::COND_GE;
2426d8078f9SDylan McKay   case AVR::BRLTk:
2436d8078f9SDylan McKay     return AVRCC::COND_LT;
2446d8078f9SDylan McKay   }
2456d8078f9SDylan McKay }
2466d8078f9SDylan McKay 
getOppositeCondition(AVRCC::CondCodes CC) const2476d8078f9SDylan McKay AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {
2486d8078f9SDylan McKay   switch (CC) {
2496d8078f9SDylan McKay   default:
2506d8078f9SDylan McKay     llvm_unreachable("Invalid condition!");
2516d8078f9SDylan McKay   case AVRCC::COND_EQ:
2526d8078f9SDylan McKay     return AVRCC::COND_NE;
2536d8078f9SDylan McKay   case AVRCC::COND_NE:
2546d8078f9SDylan McKay     return AVRCC::COND_EQ;
2556d8078f9SDylan McKay   case AVRCC::COND_SH:
2566d8078f9SDylan McKay     return AVRCC::COND_LO;
2576d8078f9SDylan McKay   case AVRCC::COND_LO:
2586d8078f9SDylan McKay     return AVRCC::COND_SH;
2596d8078f9SDylan McKay   case AVRCC::COND_GE:
2606d8078f9SDylan McKay     return AVRCC::COND_LT;
2616d8078f9SDylan McKay   case AVRCC::COND_LT:
2626d8078f9SDylan McKay     return AVRCC::COND_GE;
2636d8078f9SDylan McKay   case AVRCC::COND_MI:
2646d8078f9SDylan McKay     return AVRCC::COND_PL;
2656d8078f9SDylan McKay   case AVRCC::COND_PL:
2666d8078f9SDylan McKay     return AVRCC::COND_MI;
2676d8078f9SDylan McKay   }
2686d8078f9SDylan McKay }
2696d8078f9SDylan McKay 
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const27071c30a14SJacques Pienaar bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
2716d8078f9SDylan McKay                                  MachineBasicBlock *&TBB,
2726d8078f9SDylan McKay                                  MachineBasicBlock *&FBB,
2736d8078f9SDylan McKay                                  SmallVectorImpl<MachineOperand> &Cond,
2746d8078f9SDylan McKay                                  bool AllowModify) const {
2756d8078f9SDylan McKay   // Start from the bottom of the block and work up, examining the
2766d8078f9SDylan McKay   // terminator instructions.
2776d8078f9SDylan McKay   MachineBasicBlock::iterator I = MBB.end();
2786d8078f9SDylan McKay   MachineBasicBlock::iterator UnCondBrIter = MBB.end();
2796d8078f9SDylan McKay 
2806d8078f9SDylan McKay   while (I != MBB.begin()) {
2816d8078f9SDylan McKay     --I;
282801bf7ebSShiva Chen     if (I->isDebugInstr()) {
2836d8078f9SDylan McKay       continue;
2846d8078f9SDylan McKay     }
2856d8078f9SDylan McKay 
2866d8078f9SDylan McKay     // Working from the bottom, when we see a non-terminator
2876d8078f9SDylan McKay     // instruction, we're done.
2886d8078f9SDylan McKay     if (!isUnpredicatedTerminator(*I)) {
2896d8078f9SDylan McKay       break;
2906d8078f9SDylan McKay     }
2916d8078f9SDylan McKay 
2926d8078f9SDylan McKay     // A terminator that isn't a branch can't easily be handled
2936d8078f9SDylan McKay     // by this analysis.
2946d8078f9SDylan McKay     if (!I->getDesc().isBranch()) {
2956d8078f9SDylan McKay       return true;
2966d8078f9SDylan McKay     }
2976d8078f9SDylan McKay 
2986d8078f9SDylan McKay     // Handle unconditional branches.
2996d8078f9SDylan McKay     //: TODO: add here jmp
3006d8078f9SDylan McKay     if (I->getOpcode() == AVR::RJMPk) {
3016d8078f9SDylan McKay       UnCondBrIter = I;
3026d8078f9SDylan McKay 
3036d8078f9SDylan McKay       if (!AllowModify) {
3046d8078f9SDylan McKay         TBB = I->getOperand(0).getMBB();
3056d8078f9SDylan McKay         continue;
3066d8078f9SDylan McKay       }
3076d8078f9SDylan McKay 
3086d8078f9SDylan McKay       // If the block has any instructions after a JMP, delete them.
3099a8e65deSKazu Hirata       MBB.erase(std::next(I), MBB.end());
3106d8078f9SDylan McKay 
3116d8078f9SDylan McKay       Cond.clear();
3125a667c0eSKazu Hirata       FBB = nullptr;
3136d8078f9SDylan McKay 
3146d8078f9SDylan McKay       // Delete the JMP if it's equivalent to a fall-through.
3156d8078f9SDylan McKay       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
3165a667c0eSKazu Hirata         TBB = nullptr;
3176d8078f9SDylan McKay         I->eraseFromParent();
3186d8078f9SDylan McKay         I = MBB.end();
3196d8078f9SDylan McKay         UnCondBrIter = MBB.end();
3206d8078f9SDylan McKay         continue;
3216d8078f9SDylan McKay       }
3226d8078f9SDylan McKay 
3236d8078f9SDylan McKay       // TBB is used to indicate the unconditinal destination.
3246d8078f9SDylan McKay       TBB = I->getOperand(0).getMBB();
3256d8078f9SDylan McKay       continue;
3266d8078f9SDylan McKay     }
3276d8078f9SDylan McKay 
3286d8078f9SDylan McKay     // Handle conditional branches.
3296d8078f9SDylan McKay     AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
3306d8078f9SDylan McKay     if (BranchCode == AVRCC::COND_INVALID) {
3316d8078f9SDylan McKay       return true; // Can't handle indirect branch.
3326d8078f9SDylan McKay     }
3336d8078f9SDylan McKay 
3346d8078f9SDylan McKay     // Working from the bottom, handle the first conditional branch.
3356d8078f9SDylan McKay     if (Cond.empty()) {
3366d8078f9SDylan McKay       MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
3376d8078f9SDylan McKay       if (AllowModify && UnCondBrIter != MBB.end() &&
3386d8078f9SDylan McKay           MBB.isLayoutSuccessor(TargetBB)) {
3396d8078f9SDylan McKay         // If we can modify the code and it ends in something like:
3406d8078f9SDylan McKay         //
3416d8078f9SDylan McKay         //     jCC L1
3426d8078f9SDylan McKay         //     jmp L2
3436d8078f9SDylan McKay         //   L1:
3446d8078f9SDylan McKay         //     ...
3456d8078f9SDylan McKay         //   L2:
3466d8078f9SDylan McKay         //
3476d8078f9SDylan McKay         // Then we can change this to:
3486d8078f9SDylan McKay         //
3496d8078f9SDylan McKay         //     jnCC L2
3506d8078f9SDylan McKay         //   L1:
3516d8078f9SDylan McKay         //     ...
3526d8078f9SDylan McKay         //   L2:
3536d8078f9SDylan McKay         //
3546d8078f9SDylan McKay         // Which is a bit more efficient.
3556d8078f9SDylan McKay         // We conditionally jump to the fall-through block.
3566d8078f9SDylan McKay         BranchCode = getOppositeCondition(BranchCode);
3576d8078f9SDylan McKay         unsigned JNCC = getBrCond(BranchCode).getOpcode();
3586d8078f9SDylan McKay         MachineBasicBlock::iterator OldInst = I;
3596d8078f9SDylan McKay 
3606d8078f9SDylan McKay         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
3616d8078f9SDylan McKay             .addMBB(UnCondBrIter->getOperand(0).getMBB());
3626d8078f9SDylan McKay         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))
3636d8078f9SDylan McKay             .addMBB(TargetBB);
3646d8078f9SDylan McKay 
3656d8078f9SDylan McKay         OldInst->eraseFromParent();
3666d8078f9SDylan McKay         UnCondBrIter->eraseFromParent();
3676d8078f9SDylan McKay 
3686d8078f9SDylan McKay         // Restart the analysis.
3696d8078f9SDylan McKay         UnCondBrIter = MBB.end();
3706d8078f9SDylan McKay         I = MBB.end();
3716d8078f9SDylan McKay         continue;
3726d8078f9SDylan McKay       }
3736d8078f9SDylan McKay 
3746d8078f9SDylan McKay       FBB = TBB;
3756d8078f9SDylan McKay       TBB = I->getOperand(0).getMBB();
3766d8078f9SDylan McKay       Cond.push_back(MachineOperand::CreateImm(BranchCode));
3776d8078f9SDylan McKay       continue;
3786d8078f9SDylan McKay     }
3796d8078f9SDylan McKay 
3806d8078f9SDylan McKay     // Handle subsequent conditional branches. Only handle the case where all
3816d8078f9SDylan McKay     // conditional branches branch to the same destination.
3826d8078f9SDylan McKay     assert(Cond.size() == 1);
3836d8078f9SDylan McKay     assert(TBB);
3846d8078f9SDylan McKay 
3856d8078f9SDylan McKay     // Only handle the case where all conditional branches branch to
3866d8078f9SDylan McKay     // the same destination.
3876d8078f9SDylan McKay     if (TBB != I->getOperand(0).getMBB()) {
3886d8078f9SDylan McKay       return true;
3896d8078f9SDylan McKay     }
3906d8078f9SDylan McKay 
3916d8078f9SDylan McKay     AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();
3926d8078f9SDylan McKay     // If the conditions are the same, we can leave them alone.
3936d8078f9SDylan McKay     if (OldBranchCode == BranchCode) {
3946d8078f9SDylan McKay       continue;
3956d8078f9SDylan McKay     }
3966d8078f9SDylan McKay 
3976d8078f9SDylan McKay     return true;
3986d8078f9SDylan McKay   }
3996d8078f9SDylan McKay 
4006d8078f9SDylan McKay   return false;
4016d8078f9SDylan McKay }
4026d8078f9SDylan McKay 
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const403e8e0f5caSMatt Arsenault unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
4046d8078f9SDylan McKay                                     MachineBasicBlock *TBB,
4056d8078f9SDylan McKay                                     MachineBasicBlock *FBB,
4066d8078f9SDylan McKay                                     ArrayRef<MachineOperand> Cond,
4075449d2daSShivam Gupta                                     const DebugLoc &DL, int *BytesAdded) const {
4085449d2daSShivam Gupta   if (BytesAdded)
4095449d2daSShivam Gupta     *BytesAdded = 0;
410a2b036e8SMatt Arsenault 
4116d8078f9SDylan McKay   // Shouldn't be a fall through.
412e8e0f5caSMatt Arsenault   assert(TBB && "insertBranch must not be told to insert a fallthrough");
4136d8078f9SDylan McKay   assert((Cond.size() == 1 || Cond.size() == 0) &&
4146d8078f9SDylan McKay          "AVR branch conditions have one component!");
4156d8078f9SDylan McKay 
4166d8078f9SDylan McKay   if (Cond.empty()) {
4176d8078f9SDylan McKay     assert(!FBB && "Unconditional branch with multiple successors!");
4189cf1dc1eSDylan McKay     auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
4199cf1dc1eSDylan McKay     if (BytesAdded)
4209cf1dc1eSDylan McKay       *BytesAdded += getInstSizeInBytes(MI);
4216d8078f9SDylan McKay     return 1;
4226d8078f9SDylan McKay   }
4236d8078f9SDylan McKay 
4246d8078f9SDylan McKay   // Conditional branch.
4256d8078f9SDylan McKay   unsigned Count = 0;
4266d8078f9SDylan McKay   AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();
4279cf1dc1eSDylan McKay   auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
4289cf1dc1eSDylan McKay 
4295449d2daSShivam Gupta   if (BytesAdded)
4305449d2daSShivam Gupta     *BytesAdded += getInstSizeInBytes(CondMI);
4316d8078f9SDylan McKay   ++Count;
4326d8078f9SDylan McKay 
4336d8078f9SDylan McKay   if (FBB) {
4346d8078f9SDylan McKay     // Two-way Conditional branch. Insert the second branch.
4359cf1dc1eSDylan McKay     auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
4365449d2daSShivam Gupta     if (BytesAdded)
4375449d2daSShivam Gupta       *BytesAdded += getInstSizeInBytes(MI);
4386d8078f9SDylan McKay     ++Count;
4396d8078f9SDylan McKay   }
4406d8078f9SDylan McKay 
4416d8078f9SDylan McKay   return Count;
4426d8078f9SDylan McKay }
4436d8078f9SDylan McKay 
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const4441b9fc8edSMatt Arsenault unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,
445a2b036e8SMatt Arsenault                                     int *BytesRemoved) const {
4465449d2daSShivam Gupta   if (BytesRemoved)
4475449d2daSShivam Gupta     *BytesRemoved = 0;
448a2b036e8SMatt Arsenault 
4496d8078f9SDylan McKay   MachineBasicBlock::iterator I = MBB.end();
4506d8078f9SDylan McKay   unsigned Count = 0;
4516d8078f9SDylan McKay 
4526d8078f9SDylan McKay   while (I != MBB.begin()) {
4536d8078f9SDylan McKay     --I;
454801bf7ebSShiva Chen     if (I->isDebugInstr()) {
4556d8078f9SDylan McKay       continue;
4566d8078f9SDylan McKay     }
4576d8078f9SDylan McKay     //: TODO: add here the missing jmp instructions once they are implemented
4586d8078f9SDylan McKay     // like jmp, {e}ijmp, and other cond branches, ...
4596d8078f9SDylan McKay     if (I->getOpcode() != AVR::RJMPk &&
4606d8078f9SDylan McKay         getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {
4616d8078f9SDylan McKay       break;
4626d8078f9SDylan McKay     }
4636d8078f9SDylan McKay 
4646d8078f9SDylan McKay     // Remove the branch.
4655449d2daSShivam Gupta     if (BytesRemoved)
4665449d2daSShivam Gupta       *BytesRemoved += getInstSizeInBytes(*I);
4676d8078f9SDylan McKay     I->eraseFromParent();
4686d8078f9SDylan McKay     I = MBB.end();
4696d8078f9SDylan McKay     ++Count;
4706d8078f9SDylan McKay   }
4716d8078f9SDylan McKay 
4726d8078f9SDylan McKay   return Count;
4736d8078f9SDylan McKay }
4746d8078f9SDylan McKay 
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const4751b9fc8edSMatt Arsenault bool AVRInstrInfo::reverseBranchCondition(
4766d8078f9SDylan McKay     SmallVectorImpl<MachineOperand> &Cond) const {
4776d8078f9SDylan McKay   assert(Cond.size() == 1 && "Invalid AVR branch condition!");
4786d8078f9SDylan McKay 
4796d8078f9SDylan McKay   AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());
4806d8078f9SDylan McKay   Cond[0].setImm(getOppositeCondition(CC));
4816d8078f9SDylan McKay 
4826d8078f9SDylan McKay   return false;
4836d8078f9SDylan McKay }
4846d8078f9SDylan McKay 
getInstSizeInBytes(const MachineInstr & MI) const4856cd8c9a9SJob Noorman unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
4866cd8c9a9SJob Noorman   unsigned Opcode = MI.getOpcode();
4876d8078f9SDylan McKay 
4886d8078f9SDylan McKay   switch (Opcode) {
4896d8078f9SDylan McKay   // A regular instruction
4906d8078f9SDylan McKay   default: {
4916d8078f9SDylan McKay     const MCInstrDesc &Desc = get(Opcode);
4926d8078f9SDylan McKay     return Desc.getSize();
4936d8078f9SDylan McKay   }
4946d8078f9SDylan McKay   case TargetOpcode::EH_LABEL:
4956d8078f9SDylan McKay   case TargetOpcode::IMPLICIT_DEF:
4966d8078f9SDylan McKay   case TargetOpcode::KILL:
4976d8078f9SDylan McKay   case TargetOpcode::DBG_VALUE:
4986d8078f9SDylan McKay     return 0;
499784929d0SCraig Topper   case TargetOpcode::INLINEASM:
500784929d0SCraig Topper   case TargetOpcode::INLINEASM_BR: {
501afff169fSDylan McKay     const MachineFunction &MF = *MI.getParent()->getParent();
5025449d2daSShivam Gupta     const AVRTargetMachine &TM =
5035449d2daSShivam Gupta         static_cast<const AVRTargetMachine &>(MF.getTarget());
504afff169fSDylan McKay     const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
505afff169fSDylan McKay     const TargetInstrInfo &TII = *STI.getInstrInfo();
506afff169fSDylan McKay 
5076cd8c9a9SJob Noorman     return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
5086d8078f9SDylan McKay                                   *TM.getMCAsmInfo());
5096d8078f9SDylan McKay   }
5106d8078f9SDylan McKay   }
5116d8078f9SDylan McKay }
5126d8078f9SDylan McKay 
5139cf1dc1eSDylan McKay MachineBasicBlock *
getBranchDestBlock(const MachineInstr & MI) const5149cf1dc1eSDylan McKay AVRInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
5159cf1dc1eSDylan McKay   switch (MI.getOpcode()) {
5169cf1dc1eSDylan McKay   default:
5179cf1dc1eSDylan McKay     llvm_unreachable("unexpected opcode!");
5189cf1dc1eSDylan McKay   case AVR::JMPk:
5199cf1dc1eSDylan McKay   case AVR::CALLk:
5209cf1dc1eSDylan McKay   case AVR::RCALLk:
5219cf1dc1eSDylan McKay   case AVR::RJMPk:
5229cf1dc1eSDylan McKay   case AVR::BREQk:
5239cf1dc1eSDylan McKay   case AVR::BRNEk:
5249cf1dc1eSDylan McKay   case AVR::BRSHk:
5259cf1dc1eSDylan McKay   case AVR::BRLOk:
5269cf1dc1eSDylan McKay   case AVR::BRMIk:
5279cf1dc1eSDylan McKay   case AVR::BRPLk:
5289cf1dc1eSDylan McKay   case AVR::BRGEk:
5299cf1dc1eSDylan McKay   case AVR::BRLTk:
5309cf1dc1eSDylan McKay     return MI.getOperand(0).getMBB();
5319cf1dc1eSDylan McKay   case AVR::BRBSsk:
5329cf1dc1eSDylan McKay   case AVR::BRBCsk:
5339cf1dc1eSDylan McKay     return MI.getOperand(1).getMBB();
5349cf1dc1eSDylan McKay   case AVR::SBRCRrB:
5359cf1dc1eSDylan McKay   case AVR::SBRSRrB:
5369cf1dc1eSDylan McKay   case AVR::SBICAb:
5379cf1dc1eSDylan McKay   case AVR::SBISAb:
5389cf1dc1eSDylan McKay     llvm_unreachable("unimplemented branch instructions");
5399cf1dc1eSDylan McKay   }
5409cf1dc1eSDylan McKay }
5419cf1dc1eSDylan McKay 
isBranchOffsetInRange(unsigned BranchOp,int64_t BrOffset) const5429cf1dc1eSDylan McKay bool AVRInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
5439cf1dc1eSDylan McKay                                          int64_t BrOffset) const {
5449cf1dc1eSDylan McKay 
5459cf1dc1eSDylan McKay   switch (BranchOp) {
5469cf1dc1eSDylan McKay   default:
5479cf1dc1eSDylan McKay     llvm_unreachable("unexpected opcode!");
5489cf1dc1eSDylan McKay   case AVR::JMPk:
5499cf1dc1eSDylan McKay   case AVR::CALLk:
55039069208SDylan McKay     return true;
5519cf1dc1eSDylan McKay   case AVR::RCALLk:
5529cf1dc1eSDylan McKay   case AVR::RJMPk:
5539cf1dc1eSDylan McKay     return isIntN(13, BrOffset);
5549cf1dc1eSDylan McKay   case AVR::BRBSsk:
5559cf1dc1eSDylan McKay   case AVR::BRBCsk:
5569cf1dc1eSDylan McKay   case AVR::BREQk:
5579cf1dc1eSDylan McKay   case AVR::BRNEk:
5589cf1dc1eSDylan McKay   case AVR::BRSHk:
5599cf1dc1eSDylan McKay   case AVR::BRLOk:
5609cf1dc1eSDylan McKay   case AVR::BRMIk:
5619cf1dc1eSDylan McKay   case AVR::BRPLk:
5629cf1dc1eSDylan McKay   case AVR::BRGEk:
5639cf1dc1eSDylan McKay   case AVR::BRLTk:
5649cf1dc1eSDylan McKay     return isIntN(7, BrOffset);
5659cf1dc1eSDylan McKay   }
5669cf1dc1eSDylan McKay }
5679cf1dc1eSDylan McKay 
insertIndirectBranch(MachineBasicBlock & MBB,MachineBasicBlock & NewDestBB,MachineBasicBlock & RestoreBB,const DebugLoc & DL,int64_t BrOffset,RegScavenger * RS) const568e6a4ba3aSMichael Liao void AVRInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
56939069208SDylan McKay                                         MachineBasicBlock &NewDestBB,
570e6a4ba3aSMichael Liao                                         MachineBasicBlock &RestoreBB,
571e6a4ba3aSMichael Liao                                         const DebugLoc &DL, int64_t BrOffset,
57239069208SDylan McKay                                         RegScavenger *RS) const {
57339069208SDylan McKay   // This method inserts a *direct* branch (JMP), despite its name.
57439069208SDylan McKay   // LLVM calls this method to fixup unconditional branches; it never calls
57539069208SDylan McKay   // insertBranch or some hypothetical "insertDirectBranch".
57639069208SDylan McKay   // See lib/CodeGen/RegisterRelaxation.cpp for details.
57739069208SDylan McKay   // We end up here when a jump is too long for a RJMP instruction.
578e6a4ba3aSMichael Liao   BuildMI(&MBB, DL, get(AVR::JMPk)).addMBB(&NewDestBB);
57939069208SDylan McKay }
58039069208SDylan McKay 
5816d8078f9SDylan McKay } // end of namespace llvm
582