xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AVR/AVRInstrInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- AVRInstrInfo.cpp - AVR Instruction Information --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the AVR implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "AVRInstrInfo.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
200b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
210b57cec5SDimitry Andric #include "llvm/IR/Function.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
23349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
240b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #include "AVR.h"
280b57cec5SDimitry Andric #include "AVRMachineFunctionInfo.h"
290b57cec5SDimitry Andric #include "AVRRegisterInfo.h"
300b57cec5SDimitry Andric #include "AVRTargetMachine.h"
310b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
340b57cec5SDimitry Andric #include "AVRGenInstrInfo.inc"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric namespace llvm {
370b57cec5SDimitry Andric 
3806c3fb27SDimitry Andric AVRInstrInfo::AVRInstrInfo(AVRSubtarget &STI)
3906c3fb27SDimitry Andric     : AVRGenInstrInfo(AVR::ADJCALLSTACKDOWN, AVR::ADJCALLSTACKUP), RI(),
4006c3fb27SDimitry Andric       STI(STI) {}
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric void AVRInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
430b57cec5SDimitry Andric                                MachineBasicBlock::iterator MI,
44480093f4SDimitry Andric                                const DebugLoc &DL, MCRegister DestReg,
45480093f4SDimitry Andric                                MCRegister SrcReg, bool KillSrc) const {
460b57cec5SDimitry Andric   const AVRRegisterInfo &TRI = *STI.getRegisterInfo();
470b57cec5SDimitry Andric   unsigned Opc;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   if (AVR::DREGSRegClass.contains(DestReg, SrcReg)) {
5081ad6265SDimitry Andric     // If our AVR has `movw`, let's emit that; otherwise let's emit two separate
5181ad6265SDimitry Andric     // `mov`s.
525ffd83dbSDimitry Andric     if (STI.hasMOVW() && AVR::DREGSMOVWRegClass.contains(DestReg, SrcReg)) {
530b57cec5SDimitry Andric       BuildMI(MBB, MI, DL, get(AVR::MOVWRdRr), DestReg)
540b57cec5SDimitry Andric           .addReg(SrcReg, getKillRegState(KillSrc));
550b57cec5SDimitry Andric     } else {
565ffd83dbSDimitry Andric       Register DestLo, DestHi, SrcLo, SrcHi;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric       TRI.splitReg(DestReg, DestLo, DestHi);
590b57cec5SDimitry Andric       TRI.splitReg(SrcReg, SrcLo, SrcHi);
600b57cec5SDimitry Andric 
6106c3fb27SDimitry Andric       // Emit the copies.
6206c3fb27SDimitry Andric       // The original instruction was for a register pair, of which only one
6306c3fb27SDimitry Andric       // register might have been live. Add 'undef' to satisfy the machine
6406c3fb27SDimitry Andric       // verifier, when subreg liveness is enabled.
6506c3fb27SDimitry Andric       // TODO: Eliminate these unnecessary copies.
6681ad6265SDimitry Andric       if (DestLo == SrcHi) {
6781ad6265SDimitry Andric         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
6806c3fb27SDimitry Andric             .addReg(SrcHi, getKillRegState(KillSrc) | RegState::Undef);
6981ad6265SDimitry Andric         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
7006c3fb27SDimitry Andric             .addReg(SrcLo, getKillRegState(KillSrc) | RegState::Undef);
7181ad6265SDimitry Andric       } else {
720b57cec5SDimitry Andric         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestLo)
7306c3fb27SDimitry Andric             .addReg(SrcLo, getKillRegState(KillSrc) | RegState::Undef);
740b57cec5SDimitry Andric         BuildMI(MBB, MI, DL, get(AVR::MOVRdRr), DestHi)
7506c3fb27SDimitry Andric             .addReg(SrcHi, getKillRegState(KillSrc) | RegState::Undef);
760b57cec5SDimitry Andric       }
7781ad6265SDimitry Andric     }
780b57cec5SDimitry Andric   } else {
790b57cec5SDimitry Andric     if (AVR::GPR8RegClass.contains(DestReg, SrcReg)) {
800b57cec5SDimitry Andric       Opc = AVR::MOVRdRr;
810b57cec5SDimitry Andric     } else if (SrcReg == AVR::SP && AVR::DREGSRegClass.contains(DestReg)) {
820b57cec5SDimitry Andric       Opc = AVR::SPREAD;
830b57cec5SDimitry Andric     } else if (DestReg == AVR::SP && AVR::DREGSRegClass.contains(SrcReg)) {
840b57cec5SDimitry Andric       Opc = AVR::SPWRITE;
850b57cec5SDimitry Andric     } else {
860b57cec5SDimitry Andric       llvm_unreachable("Impossible reg-to-reg copy");
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     BuildMI(MBB, MI, DL, get(Opc), DestReg)
900b57cec5SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc));
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
94*0fca6ea1SDimitry Andric Register AVRInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
950b57cec5SDimitry Andric                                            int &FrameIndex) const {
960b57cec5SDimitry Andric   switch (MI.getOpcode()) {
970b57cec5SDimitry Andric   case AVR::LDDRdPtrQ:
980b57cec5SDimitry Andric   case AVR::LDDWRdYQ: { //: FIXME: remove this once PR13375 gets fixed
990b57cec5SDimitry Andric     if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
1000b57cec5SDimitry Andric         MI.getOperand(2).getImm() == 0) {
1010b57cec5SDimitry Andric       FrameIndex = MI.getOperand(1).getIndex();
1020b57cec5SDimitry Andric       return MI.getOperand(0).getReg();
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric     break;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   default:
1070b57cec5SDimitry Andric     break;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   return 0;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
113*0fca6ea1SDimitry Andric Register AVRInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
1140b57cec5SDimitry Andric                                           int &FrameIndex) const {
1150b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1160b57cec5SDimitry Andric   case AVR::STDPtrQRr:
1170b57cec5SDimitry Andric   case AVR::STDWPtrQRr: {
1180b57cec5SDimitry Andric     if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
1190b57cec5SDimitry Andric         MI.getOperand(1).getImm() == 0) {
1200b57cec5SDimitry Andric       FrameIndex = MI.getOperand(0).getIndex();
1210b57cec5SDimitry Andric       return MI.getOperand(2).getReg();
1220b57cec5SDimitry Andric     }
1230b57cec5SDimitry Andric     break;
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric   default:
1260b57cec5SDimitry Andric     break;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   return 0;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
132bdd1243dSDimitry Andric void AVRInstrInfo::storeRegToStackSlot(
133bdd1243dSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
134bdd1243dSDimitry Andric     bool isKill, int FrameIndex, const TargetRegisterClass *RC,
135bdd1243dSDimitry Andric     const TargetRegisterInfo *TRI, Register VReg) const {
1360b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
1370b57cec5SDimitry Andric   AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   AFI->setHasSpills(true);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   MachineMemOperand *MMO = MF.getMachineMemOperand(
1440b57cec5SDimitry Andric       MachinePointerInfo::getFixedStack(MF, FrameIndex),
1450b57cec5SDimitry Andric       MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
1465ffd83dbSDimitry Andric       MFI.getObjectAlign(FrameIndex));
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   unsigned Opcode = 0;
1490b57cec5SDimitry Andric   if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
1500b57cec5SDimitry Andric     Opcode = AVR::STDPtrQRr;
1510b57cec5SDimitry Andric   } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
1520b57cec5SDimitry Andric     Opcode = AVR::STDWPtrQRr;
1530b57cec5SDimitry Andric   } else {
1540b57cec5SDimitry Andric     llvm_unreachable("Cannot store this register into a stack slot!");
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric 
157bdd1243dSDimitry Andric   BuildMI(MBB, MI, DebugLoc(), get(Opcode))
1580b57cec5SDimitry Andric       .addFrameIndex(FrameIndex)
1590b57cec5SDimitry Andric       .addImm(0)
1600b57cec5SDimitry Andric       .addReg(SrcReg, getKillRegState(isKill))
1610b57cec5SDimitry Andric       .addMemOperand(MMO);
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric void AVRInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
1650b57cec5SDimitry Andric                                         MachineBasicBlock::iterator MI,
1665ffd83dbSDimitry Andric                                         Register DestReg, int FrameIndex,
1670b57cec5SDimitry Andric                                         const TargetRegisterClass *RC,
168bdd1243dSDimitry Andric                                         const TargetRegisterInfo *TRI,
169bdd1243dSDimitry Andric                                         Register VReg) const {
1700b57cec5SDimitry Andric   MachineFunction &MF = *MBB.getParent();
1710b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   MachineMemOperand *MMO = MF.getMachineMemOperand(
1740b57cec5SDimitry Andric       MachinePointerInfo::getFixedStack(MF, FrameIndex),
1750b57cec5SDimitry Andric       MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
1765ffd83dbSDimitry Andric       MFI.getObjectAlign(FrameIndex));
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   unsigned Opcode = 0;
1790b57cec5SDimitry Andric   if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
1800b57cec5SDimitry Andric     Opcode = AVR::LDDRdPtrQ;
1810b57cec5SDimitry Andric   } else if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
1820b57cec5SDimitry Andric     // Opcode = AVR::LDDWRdPtrQ;
1830b57cec5SDimitry Andric     //: FIXME: remove this once PR13375 gets fixed
1840b57cec5SDimitry Andric     Opcode = AVR::LDDWRdYQ;
1850b57cec5SDimitry Andric   } else {
1860b57cec5SDimitry Andric     llvm_unreachable("Cannot load this register from a stack slot!");
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric 
189bdd1243dSDimitry Andric   BuildMI(MBB, MI, DebugLoc(), get(Opcode), DestReg)
1900b57cec5SDimitry Andric       .addFrameIndex(FrameIndex)
1910b57cec5SDimitry Andric       .addImm(0)
1920b57cec5SDimitry Andric       .addMemOperand(MMO);
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric const MCInstrDesc &AVRInstrInfo::getBrCond(AVRCC::CondCodes CC) const {
1960b57cec5SDimitry Andric   switch (CC) {
1970b57cec5SDimitry Andric   default:
1980b57cec5SDimitry Andric     llvm_unreachable("Unknown condition code!");
1990b57cec5SDimitry Andric   case AVRCC::COND_EQ:
2000b57cec5SDimitry Andric     return get(AVR::BREQk);
2010b57cec5SDimitry Andric   case AVRCC::COND_NE:
2020b57cec5SDimitry Andric     return get(AVR::BRNEk);
2030b57cec5SDimitry Andric   case AVRCC::COND_GE:
2040b57cec5SDimitry Andric     return get(AVR::BRGEk);
2050b57cec5SDimitry Andric   case AVRCC::COND_LT:
2060b57cec5SDimitry Andric     return get(AVR::BRLTk);
2070b57cec5SDimitry Andric   case AVRCC::COND_SH:
2080b57cec5SDimitry Andric     return get(AVR::BRSHk);
2090b57cec5SDimitry Andric   case AVRCC::COND_LO:
2100b57cec5SDimitry Andric     return get(AVR::BRLOk);
2110b57cec5SDimitry Andric   case AVRCC::COND_MI:
2120b57cec5SDimitry Andric     return get(AVR::BRMIk);
2130b57cec5SDimitry Andric   case AVRCC::COND_PL:
2140b57cec5SDimitry Andric     return get(AVR::BRPLk);
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric AVRCC::CondCodes AVRInstrInfo::getCondFromBranchOpc(unsigned Opc) const {
2190b57cec5SDimitry Andric   switch (Opc) {
2200b57cec5SDimitry Andric   default:
2210b57cec5SDimitry Andric     return AVRCC::COND_INVALID;
2220b57cec5SDimitry Andric   case AVR::BREQk:
2230b57cec5SDimitry Andric     return AVRCC::COND_EQ;
2240b57cec5SDimitry Andric   case AVR::BRNEk:
2250b57cec5SDimitry Andric     return AVRCC::COND_NE;
2260b57cec5SDimitry Andric   case AVR::BRSHk:
2270b57cec5SDimitry Andric     return AVRCC::COND_SH;
2280b57cec5SDimitry Andric   case AVR::BRLOk:
2290b57cec5SDimitry Andric     return AVRCC::COND_LO;
2300b57cec5SDimitry Andric   case AVR::BRMIk:
2310b57cec5SDimitry Andric     return AVRCC::COND_MI;
2320b57cec5SDimitry Andric   case AVR::BRPLk:
2330b57cec5SDimitry Andric     return AVRCC::COND_PL;
2340b57cec5SDimitry Andric   case AVR::BRGEk:
2350b57cec5SDimitry Andric     return AVRCC::COND_GE;
2360b57cec5SDimitry Andric   case AVR::BRLTk:
2370b57cec5SDimitry Andric     return AVRCC::COND_LT;
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric AVRCC::CondCodes AVRInstrInfo::getOppositeCondition(AVRCC::CondCodes CC) const {
2420b57cec5SDimitry Andric   switch (CC) {
2430b57cec5SDimitry Andric   default:
2440b57cec5SDimitry Andric     llvm_unreachable("Invalid condition!");
2450b57cec5SDimitry Andric   case AVRCC::COND_EQ:
2460b57cec5SDimitry Andric     return AVRCC::COND_NE;
2470b57cec5SDimitry Andric   case AVRCC::COND_NE:
2480b57cec5SDimitry Andric     return AVRCC::COND_EQ;
2490b57cec5SDimitry Andric   case AVRCC::COND_SH:
2500b57cec5SDimitry Andric     return AVRCC::COND_LO;
2510b57cec5SDimitry Andric   case AVRCC::COND_LO:
2520b57cec5SDimitry Andric     return AVRCC::COND_SH;
2530b57cec5SDimitry Andric   case AVRCC::COND_GE:
2540b57cec5SDimitry Andric     return AVRCC::COND_LT;
2550b57cec5SDimitry Andric   case AVRCC::COND_LT:
2560b57cec5SDimitry Andric     return AVRCC::COND_GE;
2570b57cec5SDimitry Andric   case AVRCC::COND_MI:
2580b57cec5SDimitry Andric     return AVRCC::COND_PL;
2590b57cec5SDimitry Andric   case AVRCC::COND_PL:
2600b57cec5SDimitry Andric     return AVRCC::COND_MI;
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric bool AVRInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
2650b57cec5SDimitry Andric                                  MachineBasicBlock *&TBB,
2660b57cec5SDimitry Andric                                  MachineBasicBlock *&FBB,
2670b57cec5SDimitry Andric                                  SmallVectorImpl<MachineOperand> &Cond,
2680b57cec5SDimitry Andric                                  bool AllowModify) const {
2690b57cec5SDimitry Andric   // Start from the bottom of the block and work up, examining the
2700b57cec5SDimitry Andric   // terminator instructions.
2710b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
2720b57cec5SDimitry Andric   MachineBasicBlock::iterator UnCondBrIter = MBB.end();
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   while (I != MBB.begin()) {
2750b57cec5SDimitry Andric     --I;
2760b57cec5SDimitry Andric     if (I->isDebugInstr()) {
2770b57cec5SDimitry Andric       continue;
2780b57cec5SDimitry Andric     }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric     // Working from the bottom, when we see a non-terminator
2810b57cec5SDimitry Andric     // instruction, we're done.
2820b57cec5SDimitry Andric     if (!isUnpredicatedTerminator(*I)) {
2830b57cec5SDimitry Andric       break;
2840b57cec5SDimitry Andric     }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     // A terminator that isn't a branch can't easily be handled
2870b57cec5SDimitry Andric     // by this analysis.
2880b57cec5SDimitry Andric     if (!I->getDesc().isBranch()) {
2890b57cec5SDimitry Andric       return true;
2900b57cec5SDimitry Andric     }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric     // Handle unconditional branches.
2930b57cec5SDimitry Andric     //: TODO: add here jmp
2940b57cec5SDimitry Andric     if (I->getOpcode() == AVR::RJMPk) {
2950b57cec5SDimitry Andric       UnCondBrIter = I;
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric       if (!AllowModify) {
2980b57cec5SDimitry Andric         TBB = I->getOperand(0).getMBB();
2990b57cec5SDimitry Andric         continue;
3000b57cec5SDimitry Andric       }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric       // If the block has any instructions after a JMP, delete them.
30381ad6265SDimitry Andric       MBB.erase(std::next(I), MBB.end());
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric       Cond.clear();
30604eeddc0SDimitry Andric       FBB = nullptr;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric       // Delete the JMP if it's equivalent to a fall-through.
3090b57cec5SDimitry Andric       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
31004eeddc0SDimitry Andric         TBB = nullptr;
3110b57cec5SDimitry Andric         I->eraseFromParent();
3120b57cec5SDimitry Andric         I = MBB.end();
3130b57cec5SDimitry Andric         UnCondBrIter = MBB.end();
3140b57cec5SDimitry Andric         continue;
3150b57cec5SDimitry Andric       }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric       // TBB is used to indicate the unconditinal destination.
3180b57cec5SDimitry Andric       TBB = I->getOperand(0).getMBB();
3190b57cec5SDimitry Andric       continue;
3200b57cec5SDimitry Andric     }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric     // Handle conditional branches.
3230b57cec5SDimitry Andric     AVRCC::CondCodes BranchCode = getCondFromBranchOpc(I->getOpcode());
3240b57cec5SDimitry Andric     if (BranchCode == AVRCC::COND_INVALID) {
3250b57cec5SDimitry Andric       return true; // Can't handle indirect branch.
3260b57cec5SDimitry Andric     }
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric     // Working from the bottom, handle the first conditional branch.
3290b57cec5SDimitry Andric     if (Cond.empty()) {
3300b57cec5SDimitry Andric       MachineBasicBlock *TargetBB = I->getOperand(0).getMBB();
3310b57cec5SDimitry Andric       if (AllowModify && UnCondBrIter != MBB.end() &&
3320b57cec5SDimitry Andric           MBB.isLayoutSuccessor(TargetBB)) {
3330b57cec5SDimitry Andric         // If we can modify the code and it ends in something like:
3340b57cec5SDimitry Andric         //
3350b57cec5SDimitry Andric         //     jCC L1
3360b57cec5SDimitry Andric         //     jmp L2
3370b57cec5SDimitry Andric         //   L1:
3380b57cec5SDimitry Andric         //     ...
3390b57cec5SDimitry Andric         //   L2:
3400b57cec5SDimitry Andric         //
3410b57cec5SDimitry Andric         // Then we can change this to:
3420b57cec5SDimitry Andric         //
3430b57cec5SDimitry Andric         //     jnCC L2
3440b57cec5SDimitry Andric         //   L1:
3450b57cec5SDimitry Andric         //     ...
3460b57cec5SDimitry Andric         //   L2:
3470b57cec5SDimitry Andric         //
3480b57cec5SDimitry Andric         // Which is a bit more efficient.
3490b57cec5SDimitry Andric         // We conditionally jump to the fall-through block.
3500b57cec5SDimitry Andric         BranchCode = getOppositeCondition(BranchCode);
3510b57cec5SDimitry Andric         unsigned JNCC = getBrCond(BranchCode).getOpcode();
3520b57cec5SDimitry Andric         MachineBasicBlock::iterator OldInst = I;
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(JNCC))
3550b57cec5SDimitry Andric             .addMBB(UnCondBrIter->getOperand(0).getMBB());
3560b57cec5SDimitry Andric         BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(AVR::RJMPk))
3570b57cec5SDimitry Andric             .addMBB(TargetBB);
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric         OldInst->eraseFromParent();
3600b57cec5SDimitry Andric         UnCondBrIter->eraseFromParent();
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric         // Restart the analysis.
3630b57cec5SDimitry Andric         UnCondBrIter = MBB.end();
3640b57cec5SDimitry Andric         I = MBB.end();
3650b57cec5SDimitry Andric         continue;
3660b57cec5SDimitry Andric       }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric       FBB = TBB;
3690b57cec5SDimitry Andric       TBB = I->getOperand(0).getMBB();
3700b57cec5SDimitry Andric       Cond.push_back(MachineOperand::CreateImm(BranchCode));
3710b57cec5SDimitry Andric       continue;
3720b57cec5SDimitry Andric     }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric     // Handle subsequent conditional branches. Only handle the case where all
3750b57cec5SDimitry Andric     // conditional branches branch to the same destination.
3760b57cec5SDimitry Andric     assert(Cond.size() == 1);
3770b57cec5SDimitry Andric     assert(TBB);
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric     // Only handle the case where all conditional branches branch to
3800b57cec5SDimitry Andric     // the same destination.
3810b57cec5SDimitry Andric     if (TBB != I->getOperand(0).getMBB()) {
3820b57cec5SDimitry Andric       return true;
3830b57cec5SDimitry Andric     }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     AVRCC::CondCodes OldBranchCode = (AVRCC::CondCodes)Cond[0].getImm();
3860b57cec5SDimitry Andric     // If the conditions are the same, we can leave them alone.
3870b57cec5SDimitry Andric     if (OldBranchCode == BranchCode) {
3880b57cec5SDimitry Andric       continue;
3890b57cec5SDimitry Andric     }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric     return true;
3920b57cec5SDimitry Andric   }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   return false;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric unsigned AVRInstrInfo::insertBranch(MachineBasicBlock &MBB,
3980b57cec5SDimitry Andric                                     MachineBasicBlock *TBB,
3990b57cec5SDimitry Andric                                     MachineBasicBlock *FBB,
4000b57cec5SDimitry Andric                                     ArrayRef<MachineOperand> Cond,
401349cc55cSDimitry Andric                                     const DebugLoc &DL, int *BytesAdded) const {
402349cc55cSDimitry Andric   if (BytesAdded)
403349cc55cSDimitry Andric     *BytesAdded = 0;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   // Shouldn't be a fall through.
4060b57cec5SDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
4070b57cec5SDimitry Andric   assert((Cond.size() == 1 || Cond.size() == 0) &&
4080b57cec5SDimitry Andric          "AVR branch conditions have one component!");
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   if (Cond.empty()) {
4110b57cec5SDimitry Andric     assert(!FBB && "Unconditional branch with multiple successors!");
4120b57cec5SDimitry Andric     auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(TBB);
4130b57cec5SDimitry Andric     if (BytesAdded)
4140b57cec5SDimitry Andric       *BytesAdded += getInstSizeInBytes(MI);
4150b57cec5SDimitry Andric     return 1;
4160b57cec5SDimitry Andric   }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   // Conditional branch.
4190b57cec5SDimitry Andric   unsigned Count = 0;
4200b57cec5SDimitry Andric   AVRCC::CondCodes CC = (AVRCC::CondCodes)Cond[0].getImm();
4210b57cec5SDimitry Andric   auto &CondMI = *BuildMI(&MBB, DL, getBrCond(CC)).addMBB(TBB);
4220b57cec5SDimitry Andric 
423349cc55cSDimitry Andric   if (BytesAdded)
424349cc55cSDimitry Andric     *BytesAdded += getInstSizeInBytes(CondMI);
4250b57cec5SDimitry Andric   ++Count;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   if (FBB) {
4280b57cec5SDimitry Andric     // Two-way Conditional branch. Insert the second branch.
4290b57cec5SDimitry Andric     auto &MI = *BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(FBB);
430349cc55cSDimitry Andric     if (BytesAdded)
431349cc55cSDimitry Andric       *BytesAdded += getInstSizeInBytes(MI);
4320b57cec5SDimitry Andric     ++Count;
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   return Count;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric unsigned AVRInstrInfo::removeBranch(MachineBasicBlock &MBB,
4390b57cec5SDimitry Andric                                     int *BytesRemoved) const {
440349cc55cSDimitry Andric   if (BytesRemoved)
441349cc55cSDimitry Andric     *BytesRemoved = 0;
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
4440b57cec5SDimitry Andric   unsigned Count = 0;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   while (I != MBB.begin()) {
4470b57cec5SDimitry Andric     --I;
4480b57cec5SDimitry Andric     if (I->isDebugInstr()) {
4490b57cec5SDimitry Andric       continue;
4500b57cec5SDimitry Andric     }
4510b57cec5SDimitry Andric     //: TODO: add here the missing jmp instructions once they are implemented
4520b57cec5SDimitry Andric     // like jmp, {e}ijmp, and other cond branches, ...
4530b57cec5SDimitry Andric     if (I->getOpcode() != AVR::RJMPk &&
4540b57cec5SDimitry Andric         getCondFromBranchOpc(I->getOpcode()) == AVRCC::COND_INVALID) {
4550b57cec5SDimitry Andric       break;
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric     // Remove the branch.
459349cc55cSDimitry Andric     if (BytesRemoved)
460349cc55cSDimitry Andric       *BytesRemoved += getInstSizeInBytes(*I);
4610b57cec5SDimitry Andric     I->eraseFromParent();
4620b57cec5SDimitry Andric     I = MBB.end();
4630b57cec5SDimitry Andric     ++Count;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   return Count;
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric bool AVRInstrInfo::reverseBranchCondition(
4700b57cec5SDimitry Andric     SmallVectorImpl<MachineOperand> &Cond) const {
4710b57cec5SDimitry Andric   assert(Cond.size() == 1 && "Invalid AVR branch condition!");
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric   AVRCC::CondCodes CC = static_cast<AVRCC::CondCodes>(Cond[0].getImm());
4740b57cec5SDimitry Andric   Cond[0].setImm(getOppositeCondition(CC));
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   return false;
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric unsigned AVRInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
4800b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   switch (Opcode) {
4830b57cec5SDimitry Andric   // A regular instruction
4840b57cec5SDimitry Andric   default: {
4850b57cec5SDimitry Andric     const MCInstrDesc &Desc = get(Opcode);
4860b57cec5SDimitry Andric     return Desc.getSize();
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric   case TargetOpcode::EH_LABEL:
4890b57cec5SDimitry Andric   case TargetOpcode::IMPLICIT_DEF:
4900b57cec5SDimitry Andric   case TargetOpcode::KILL:
4910b57cec5SDimitry Andric   case TargetOpcode::DBG_VALUE:
4920b57cec5SDimitry Andric     return 0;
4930b57cec5SDimitry Andric   case TargetOpcode::INLINEASM:
4940b57cec5SDimitry Andric   case TargetOpcode::INLINEASM_BR: {
4950b57cec5SDimitry Andric     const MachineFunction &MF = *MI.getParent()->getParent();
496349cc55cSDimitry Andric     const AVRTargetMachine &TM =
497349cc55cSDimitry Andric         static_cast<const AVRTargetMachine &>(MF.getTarget());
4980b57cec5SDimitry Andric     const TargetInstrInfo &TII = *STI.getInstrInfo();
4990b57cec5SDimitry Andric     return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
5000b57cec5SDimitry Andric                                   *TM.getMCAsmInfo());
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric   }
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric MachineBasicBlock *
5060b57cec5SDimitry Andric AVRInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
5070b57cec5SDimitry Andric   switch (MI.getOpcode()) {
5080b57cec5SDimitry Andric   default:
5090b57cec5SDimitry Andric     llvm_unreachable("unexpected opcode!");
5100b57cec5SDimitry Andric   case AVR::JMPk:
5110b57cec5SDimitry Andric   case AVR::CALLk:
5120b57cec5SDimitry Andric   case AVR::RCALLk:
5130b57cec5SDimitry Andric   case AVR::RJMPk:
5140b57cec5SDimitry Andric   case AVR::BREQk:
5150b57cec5SDimitry Andric   case AVR::BRNEk:
5160b57cec5SDimitry Andric   case AVR::BRSHk:
5170b57cec5SDimitry Andric   case AVR::BRLOk:
5180b57cec5SDimitry Andric   case AVR::BRMIk:
5190b57cec5SDimitry Andric   case AVR::BRPLk:
5200b57cec5SDimitry Andric   case AVR::BRGEk:
5210b57cec5SDimitry Andric   case AVR::BRLTk:
5220b57cec5SDimitry Andric     return MI.getOperand(0).getMBB();
5230b57cec5SDimitry Andric   case AVR::BRBSsk:
5240b57cec5SDimitry Andric   case AVR::BRBCsk:
5250b57cec5SDimitry Andric     return MI.getOperand(1).getMBB();
5260b57cec5SDimitry Andric   case AVR::SBRCRrB:
5270b57cec5SDimitry Andric   case AVR::SBRSRrB:
5280b57cec5SDimitry Andric   case AVR::SBICAb:
5290b57cec5SDimitry Andric   case AVR::SBISAb:
5300b57cec5SDimitry Andric     llvm_unreachable("unimplemented branch instructions");
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric bool AVRInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
5350b57cec5SDimitry Andric                                          int64_t BrOffset) const {
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   switch (BranchOp) {
5380b57cec5SDimitry Andric   default:
5390b57cec5SDimitry Andric     llvm_unreachable("unexpected opcode!");
5400b57cec5SDimitry Andric   case AVR::JMPk:
5410b57cec5SDimitry Andric   case AVR::CALLk:
5425f757f3fSDimitry Andric     return STI.hasJMPCALL();
5430b57cec5SDimitry Andric   case AVR::RCALLk:
5440b57cec5SDimitry Andric   case AVR::RJMPk:
5450b57cec5SDimitry Andric     return isIntN(13, BrOffset);
5460b57cec5SDimitry Andric   case AVR::BRBSsk:
5470b57cec5SDimitry Andric   case AVR::BRBCsk:
5480b57cec5SDimitry Andric   case AVR::BREQk:
5490b57cec5SDimitry Andric   case AVR::BRNEk:
5500b57cec5SDimitry Andric   case AVR::BRSHk:
5510b57cec5SDimitry Andric   case AVR::BRLOk:
5520b57cec5SDimitry Andric   case AVR::BRMIk:
5530b57cec5SDimitry Andric   case AVR::BRPLk:
5540b57cec5SDimitry Andric   case AVR::BRGEk:
5550b57cec5SDimitry Andric   case AVR::BRLTk:
5560b57cec5SDimitry Andric     return isIntN(7, BrOffset);
5570b57cec5SDimitry Andric   }
5580b57cec5SDimitry Andric }
5590b57cec5SDimitry Andric 
560349cc55cSDimitry Andric void AVRInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
5610b57cec5SDimitry Andric                                         MachineBasicBlock &NewDestBB,
562349cc55cSDimitry Andric                                         MachineBasicBlock &RestoreBB,
563349cc55cSDimitry Andric                                         const DebugLoc &DL, int64_t BrOffset,
5640b57cec5SDimitry Andric                                         RegScavenger *RS) const {
5650b57cec5SDimitry Andric   // This method inserts a *direct* branch (JMP), despite its name.
5660b57cec5SDimitry Andric   // LLVM calls this method to fixup unconditional branches; it never calls
5670b57cec5SDimitry Andric   // insertBranch or some hypothetical "insertDirectBranch".
5680b57cec5SDimitry Andric   // See lib/CodeGen/RegisterRelaxation.cpp for details.
5690b57cec5SDimitry Andric   // We end up here when a jump is too long for a RJMP instruction.
57006c3fb27SDimitry Andric   if (STI.hasJMPCALL())
571349cc55cSDimitry Andric     BuildMI(&MBB, DL, get(AVR::JMPk)).addMBB(&NewDestBB);
57206c3fb27SDimitry Andric   else
5735f757f3fSDimitry Andric     // The RJMP may jump to a far place beyond its legal range. We let the
5745f757f3fSDimitry Andric     // linker to report 'out of range' rather than crash, or silently emit
5755f757f3fSDimitry Andric     // incorrect assembly code.
5765f757f3fSDimitry Andric     BuildMI(&MBB, DL, get(AVR::RJMPk)).addMBB(&NewDestBB);
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric } // end of namespace llvm
580