xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/AVRRegisterInfo.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- AVRRegisterInfo.cpp - AVR Register 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 TargetRegisterInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "AVRRegisterInfo.h"
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
21349cc55cSDimitry Andric #include "llvm/IR/Function.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "AVR.h"
240b57cec5SDimitry Andric #include "AVRInstrInfo.h"
255ffd83dbSDimitry Andric #include "AVRMachineFunctionInfo.h"
260b57cec5SDimitry Andric #include "AVRTargetMachine.h"
270b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
300b57cec5SDimitry Andric #include "AVRGenRegisterInfo.inc"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric namespace llvm {
330b57cec5SDimitry Andric 
AVRRegisterInfo()340b57cec5SDimitry Andric AVRRegisterInfo::AVRRegisterInfo() : AVRGenRegisterInfo(0) {}
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric const uint16_t *
getCalleeSavedRegs(const MachineFunction * MF) const370b57cec5SDimitry Andric AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
385ffd83dbSDimitry Andric   const AVRMachineFunctionInfo *AFI = MF->getInfo<AVRMachineFunctionInfo>();
3981ad6265SDimitry Andric   const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
4081ad6265SDimitry Andric   if (STI.hasTinyEncoding())
4181ad6265SDimitry Andric     return AFI->isInterruptOrSignalHandler() ? CSR_InterruptsTiny_SaveList
4281ad6265SDimitry Andric                                              : CSR_NormalTiny_SaveList;
4381ad6265SDimitry Andric   else
44349cc55cSDimitry Andric     return AFI->isInterruptOrSignalHandler() ? CSR_Interrupts_SaveList
455ffd83dbSDimitry Andric                                              : CSR_Normal_SaveList;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const490b57cec5SDimitry Andric AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
500b57cec5SDimitry Andric                                       CallingConv::ID CC) const {
5181ad6265SDimitry Andric   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
5281ad6265SDimitry Andric   return STI.hasTinyEncoding() ? CSR_NormalTiny_RegMask : CSR_Normal_RegMask;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
getReservedRegs(const MachineFunction & MF) const550b57cec5SDimitry Andric BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
560b57cec5SDimitry Andric   BitVector Reserved(getNumRegs());
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   // Reserve the intermediate result registers r1 and r2
590b57cec5SDimitry Andric   // The result of instructions like 'mul' is always stored here.
6081ad6265SDimitry Andric   // R0/R1/R1R0 are always reserved on both avr and avrtiny.
610b57cec5SDimitry Andric   Reserved.set(AVR::R0);
620b57cec5SDimitry Andric   Reserved.set(AVR::R1);
630b57cec5SDimitry Andric   Reserved.set(AVR::R1R0);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   // Reserve the stack pointer.
660b57cec5SDimitry Andric   Reserved.set(AVR::SPL);
670b57cec5SDimitry Andric   Reserved.set(AVR::SPH);
680b57cec5SDimitry Andric   Reserved.set(AVR::SP);
690b57cec5SDimitry Andric 
7081ad6265SDimitry Andric   // Reserve R2~R17 only on avrtiny.
7181ad6265SDimitry Andric   if (MF.getSubtarget<AVRSubtarget>().hasTinyEncoding()) {
7281ad6265SDimitry Andric     // Reserve 8-bit registers R2~R15, Rtmp(R16) and Zero(R17).
7381ad6265SDimitry Andric     for (unsigned Reg = AVR::R2; Reg <= AVR::R17; Reg++)
7481ad6265SDimitry Andric       Reserved.set(Reg);
7581ad6265SDimitry Andric     // Reserve 16-bit registers R3R2~R18R17.
7681ad6265SDimitry Andric     for (unsigned Reg = AVR::R3R2; Reg <= AVR::R18R17; Reg++)
7781ad6265SDimitry Andric       Reserved.set(Reg);
7881ad6265SDimitry Andric   }
7981ad6265SDimitry Andric 
800b57cec5SDimitry Andric   // We tenatively reserve the frame pointer register r29:r28 because the
810b57cec5SDimitry Andric   // function may require one, but we cannot tell until register allocation
820b57cec5SDimitry Andric   // is complete, which can be too late.
830b57cec5SDimitry Andric   //
840b57cec5SDimitry Andric   // Instead we just unconditionally reserve the Y register.
850b57cec5SDimitry Andric   //
860b57cec5SDimitry Andric   // TODO: Write a pass to enumerate functions which reserved the Y register
870b57cec5SDimitry Andric   //       but didn't end up needing a frame pointer. In these, we can
880b57cec5SDimitry Andric   //       convert one or two of the spills inside to use the Y register.
890b57cec5SDimitry Andric   Reserved.set(AVR::R28);
900b57cec5SDimitry Andric   Reserved.set(AVR::R29);
910b57cec5SDimitry Andric   Reserved.set(AVR::R29R28);
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   return Reserved;
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric const TargetRegisterClass *
getLargestLegalSuperClass(const TargetRegisterClass * RC,const MachineFunction & MF) const970b57cec5SDimitry Andric AVRRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
980b57cec5SDimitry Andric                                            const MachineFunction &MF) const {
990b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1000b57cec5SDimitry Andric   if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {
1010b57cec5SDimitry Andric     return &AVR::DREGSRegClass;
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {
1050b57cec5SDimitry Andric     return &AVR::GPR8RegClass;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   llvm_unreachable("Invalid register size");
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric /// Fold a frame offset shared between two add instructions into a single one.
foldFrameOffset(MachineBasicBlock::iterator & II,int & Offset,Register DstReg)1125ffd83dbSDimitry Andric static void foldFrameOffset(MachineBasicBlock::iterator &II, int &Offset,
1135ffd83dbSDimitry Andric                             Register DstReg) {
1140b57cec5SDimitry Andric   MachineInstr &MI = *II;
1150b57cec5SDimitry Andric   int Opcode = MI.getOpcode();
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   // Don't bother trying if the next instruction is not an add or a sub.
1180b57cec5SDimitry Andric   if ((Opcode != AVR::SUBIWRdK) && (Opcode != AVR::ADIWRdK)) {
1190b57cec5SDimitry Andric     return;
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // Check that DstReg matches with next instruction, otherwise the instruction
1230b57cec5SDimitry Andric   // is not related to stack address manipulation.
1240b57cec5SDimitry Andric   if (DstReg != MI.getOperand(0).getReg()) {
1250b57cec5SDimitry Andric     return;
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   // Add the offset in the next instruction to our offset.
1290b57cec5SDimitry Andric   switch (Opcode) {
1300b57cec5SDimitry Andric   case AVR::SUBIWRdK:
1310b57cec5SDimitry Andric     Offset += -MI.getOperand(2).getImm();
1320b57cec5SDimitry Andric     break;
1330b57cec5SDimitry Andric   case AVR::ADIWRdK:
1340b57cec5SDimitry Andric     Offset += MI.getOperand(2).getImm();
1350b57cec5SDimitry Andric     break;
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   // Finally remove the instruction.
1390b57cec5SDimitry Andric   II++;
1400b57cec5SDimitry Andric   MI.eraseFromParent();
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const143*bdd1243dSDimitry Andric bool AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
1440b57cec5SDimitry Andric                                           int SPAdj, unsigned FIOperandNum,
1450b57cec5SDimitry Andric                                           RegScavenger *RS) const {
1460b57cec5SDimitry Andric   assert(SPAdj == 0 && "Unexpected SPAdj value");
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   MachineInstr &MI = *II;
1490b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
1500b57cec5SDimitry Andric   MachineBasicBlock &MBB = *MI.getParent();
1510b57cec5SDimitry Andric   const MachineFunction &MF = *MBB.getParent();
1520b57cec5SDimitry Andric   const AVRTargetMachine &TM = (const AVRTargetMachine &)MF.getTarget();
1530b57cec5SDimitry Andric   const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo();
1540b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1550b57cec5SDimitry Andric   const TargetFrameLowering *TFI = TM.getSubtargetImpl()->getFrameLowering();
15681ad6265SDimitry Andric   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
1570b57cec5SDimitry Andric   int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
1580b57cec5SDimitry Andric   int Offset = MFI.getObjectOffset(FrameIndex);
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   // Add one to the offset because SP points to an empty slot.
1610b57cec5SDimitry Andric   Offset += MFI.getStackSize() - TFI->getOffsetOfLocalArea() + 1;
1620b57cec5SDimitry Andric   // Fold incoming offset.
1630b57cec5SDimitry Andric   Offset += MI.getOperand(FIOperandNum + 1).getImm();
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   // This is actually "load effective address" of the stack slot
1660b57cec5SDimitry Andric   // instruction. We have only two-address instructions, thus we need to
1670b57cec5SDimitry Andric   // expand it into move + add.
1680b57cec5SDimitry Andric   if (MI.getOpcode() == AVR::FRMIDX) {
169*bdd1243dSDimitry Andric     Register DstReg = MI.getOperand(0).getReg();
170*bdd1243dSDimitry Andric     assert(DstReg != AVR::R29R28 && "Dest reg cannot be the frame pointer");
171*bdd1243dSDimitry Andric 
172*bdd1243dSDimitry Andric     // Copy the frame pointer.
173*bdd1243dSDimitry Andric     if (STI.hasMOVW()) {
174*bdd1243dSDimitry Andric       BuildMI(MBB, MI, dl, TII.get(AVR::MOVWRdRr), DstReg)
175*bdd1243dSDimitry Andric           .addReg(AVR::R29R28);
176*bdd1243dSDimitry Andric     } else {
177*bdd1243dSDimitry Andric       Register DstLoReg, DstHiReg;
178*bdd1243dSDimitry Andric       splitReg(DstReg, DstLoReg, DstHiReg);
179*bdd1243dSDimitry Andric       BuildMI(MBB, MI, dl, TII.get(AVR::MOVRdRr), DstLoReg)
180*bdd1243dSDimitry Andric           .addReg(AVR::R28);
181*bdd1243dSDimitry Andric       BuildMI(MBB, MI, dl, TII.get(AVR::MOVRdRr), DstHiReg)
182*bdd1243dSDimitry Andric           .addReg(AVR::R29);
183*bdd1243dSDimitry Andric     }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     assert(Offset > 0 && "Invalid offset");
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     // We need to materialize the offset via an add instruction.
1880b57cec5SDimitry Andric     unsigned Opcode;
1890b57cec5SDimitry Andric 
190*bdd1243dSDimitry Andric     II++; // Skip over the FRMIDX instruction.
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     // Generally, to load a frame address two add instructions are emitted that
1930b57cec5SDimitry Andric     // could get folded into a single one:
1940b57cec5SDimitry Andric     //  movw    r31:r30, r29:r28
1950b57cec5SDimitry Andric     //  adiw    r31:r30, 29
1960b57cec5SDimitry Andric     //  adiw    r31:r30, 16
1970b57cec5SDimitry Andric     // to:
1980b57cec5SDimitry Andric     //  movw    r31:r30, r29:r28
1990b57cec5SDimitry Andric     //  adiw    r31:r30, 45
2000b57cec5SDimitry Andric     if (II != MBB.end())
2010b57cec5SDimitry Andric       foldFrameOffset(II, Offset, DstReg);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     // Select the best opcode based on DstReg and the offset size.
2040b57cec5SDimitry Andric     switch (DstReg) {
2050b57cec5SDimitry Andric     case AVR::R25R24:
2060b57cec5SDimitry Andric     case AVR::R27R26:
2070b57cec5SDimitry Andric     case AVR::R31R30: {
208*bdd1243dSDimitry Andric       if (isUInt<6>(Offset) && STI.hasADDSUBIW()) {
2090b57cec5SDimitry Andric         Opcode = AVR::ADIWRdK;
2100b57cec5SDimitry Andric         break;
2110b57cec5SDimitry Andric       }
212*bdd1243dSDimitry Andric       [[fallthrough]];
2130b57cec5SDimitry Andric     }
2140b57cec5SDimitry Andric     default: {
2150b57cec5SDimitry Andric       // This opcode will get expanded into a pair of subi/sbci.
2160b57cec5SDimitry Andric       Opcode = AVR::SUBIWRdK;
2170b57cec5SDimitry Andric       Offset = -Offset;
2180b57cec5SDimitry Andric       break;
2190b57cec5SDimitry Andric     }
2200b57cec5SDimitry Andric     }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric     MachineInstr *New = BuildMI(MBB, II, dl, TII.get(Opcode), DstReg)
2230b57cec5SDimitry Andric                             .addReg(DstReg, RegState::Kill)
2240b57cec5SDimitry Andric                             .addImm(Offset);
2250b57cec5SDimitry Andric     New->getOperand(3).setIsDead();
2260b57cec5SDimitry Andric 
227*bdd1243dSDimitry Andric     MI.eraseFromParent(); // remove FRMIDX
228*bdd1243dSDimitry Andric 
229*bdd1243dSDimitry Andric     return false;
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric 
232*bdd1243dSDimitry Andric   // On most AVRs, we can use an offset up to 62 for load/store with
233*bdd1243dSDimitry Andric   // displacement (63 for byte values, 62 for word values). However, the
234*bdd1243dSDimitry Andric   // "reduced tiny" cores don't support load/store with displacement. So for
235*bdd1243dSDimitry Andric   // them, we force an offset of 0 meaning that any positive offset will require
236*bdd1243dSDimitry Andric   // adjusting the frame pointer.
237*bdd1243dSDimitry Andric   int MaxOffset = STI.hasTinyEncoding() ? 0 : 62;
238*bdd1243dSDimitry Andric 
2390b57cec5SDimitry Andric   // If the offset is too big we have to adjust and restore the frame pointer
2400b57cec5SDimitry Andric   // to materialize a valid load/store with displacement.
241349cc55cSDimitry Andric   //: TODO: consider using only one adiw/sbiw chain for more than one frame
242349cc55cSDimitry Andric   //: index
243*bdd1243dSDimitry Andric   if (Offset > MaxOffset) {
2440b57cec5SDimitry Andric     unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;
245*bdd1243dSDimitry Andric     int AddOffset = Offset - MaxOffset;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     // For huge offsets where adiw/sbiw cannot be used use a pair of subi/sbci.
248*bdd1243dSDimitry Andric     if ((Offset - MaxOffset) > 63 || !STI.hasADDSUBIW()) {
2490b57cec5SDimitry Andric       AddOpc = AVR::SUBIWRdK;
2500b57cec5SDimitry Andric       SubOpc = AVR::SUBIWRdK;
2510b57cec5SDimitry Andric       AddOffset = -AddOffset;
2520b57cec5SDimitry Andric     }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric     // It is possible that the spiller places this frame instruction in between
2550b57cec5SDimitry Andric     // a compare and branch, invalidating the contents of SREG set by the
2560b57cec5SDimitry Andric     // compare instruction because of the add/sub pairs. Conservatively save and
2570b57cec5SDimitry Andric     // restore SREG before and after each add/sub pair.
258*bdd1243dSDimitry Andric     BuildMI(MBB, II, dl, TII.get(AVR::INRdA), STI.getTmpRegister())
25981ad6265SDimitry Andric         .addImm(STI.getIORegSREG());
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric     MachineInstr *New = BuildMI(MBB, II, dl, TII.get(AddOpc), AVR::R29R28)
2620b57cec5SDimitry Andric                             .addReg(AVR::R29R28, RegState::Kill)
2630b57cec5SDimitry Andric                             .addImm(AddOffset);
2640b57cec5SDimitry Andric     New->getOperand(3).setIsDead();
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric     // Restore SREG.
2670b57cec5SDimitry Andric     BuildMI(MBB, std::next(II), dl, TII.get(AVR::OUTARr))
26881ad6265SDimitry Andric         .addImm(STI.getIORegSREG())
269*bdd1243dSDimitry Andric         .addReg(STI.getTmpRegister(), RegState::Kill);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric     // No need to set SREG as dead here otherwise if the next instruction is a
2720b57cec5SDimitry Andric     // cond branch it will be using a dead register.
2730b57cec5SDimitry Andric     BuildMI(MBB, std::next(II), dl, TII.get(SubOpc), AVR::R29R28)
2740b57cec5SDimitry Andric         .addReg(AVR::R29R28, RegState::Kill)
275*bdd1243dSDimitry Andric         .addImm(Offset - MaxOffset);
2760b57cec5SDimitry Andric 
277*bdd1243dSDimitry Andric     Offset = MaxOffset;
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   MI.getOperand(FIOperandNum).ChangeToRegister(AVR::R29R28, false);
2810b57cec5SDimitry Andric   assert(isUInt<6>(Offset) && "Offset is out of range");
2820b57cec5SDimitry Andric   MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
283*bdd1243dSDimitry Andric   return false;
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
getFrameRegister(const MachineFunction & MF) const2860b57cec5SDimitry Andric Register AVRRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
2870b57cec5SDimitry Andric   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
2880b57cec5SDimitry Andric   if (TFI->hasFP(MF)) {
2890b57cec5SDimitry Andric     // The Y pointer register
2900b57cec5SDimitry Andric     return AVR::R28;
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   return AVR::SP;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const2970b57cec5SDimitry Andric AVRRegisterInfo::getPointerRegClass(const MachineFunction &MF,
2980b57cec5SDimitry Andric                                     unsigned Kind) const {
2990b57cec5SDimitry Andric   // FIXME: Currently we're using avr-gcc as reference, so we restrict
3000b57cec5SDimitry Andric   // ptrs to Y and Z regs. Though avr-gcc has buggy implementation
3010b57cec5SDimitry Andric   // of memory constraint, so we can fix it and bit avr-gcc here ;-)
3020b57cec5SDimitry Andric   return &AVR::PTRDISPREGSRegClass;
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric 
splitReg(Register Reg,Register & LoReg,Register & HiReg) const3055ffd83dbSDimitry Andric void AVRRegisterInfo::splitReg(Register Reg, Register &LoReg,
3065ffd83dbSDimitry Andric                                Register &HiReg) const {
3070b57cec5SDimitry Andric   assert(AVR::DREGSRegClass.contains(Reg) && "can only split 16-bit registers");
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   LoReg = getSubReg(Reg, AVR::sub_lo);
3100b57cec5SDimitry Andric   HiReg = getSubReg(Reg, AVR::sub_hi);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
shouldCoalesce(MachineInstr * MI,const TargetRegisterClass * SrcRC,unsigned SubReg,const TargetRegisterClass * DstRC,unsigned DstSubReg,const TargetRegisterClass * NewRC,LiveIntervals & LIS) const313349cc55cSDimitry Andric bool AVRRegisterInfo::shouldCoalesce(
314349cc55cSDimitry Andric     MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg,
315349cc55cSDimitry Andric     const TargetRegisterClass *DstRC, unsigned DstSubReg,
316349cc55cSDimitry Andric     const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
3170b57cec5SDimitry Andric   if (this->getRegClass(AVR::PTRDISPREGSRegClassID)->hasSubClassEq(NewRC)) {
3180b57cec5SDimitry Andric     return false;
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric 
321349cc55cSDimitry Andric   return TargetRegisterInfo::shouldCoalesce(MI, SrcRC, SubReg, DstRC, DstSubReg,
322349cc55cSDimitry Andric                                             NewRC, LIS);
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric } // end of namespace llvm
326