320 lines · cpp
1//===-- AVRRegisterInfo.cpp - AVR Register Information --------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the AVR implementation of the TargetRegisterInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "AVRRegisterInfo.h"14 15#include "llvm/ADT/BitVector.h"16#include "llvm/CodeGen/MachineFrameInfo.h"17#include "llvm/CodeGen/MachineFunction.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/TargetFrameLowering.h"20 21#include "AVR.h"22#include "AVRInstrInfo.h"23#include "AVRMachineFunctionInfo.h"24#include "AVRTargetMachine.h"25#include "MCTargetDesc/AVRMCTargetDesc.h"26 27#define GET_REGINFO_TARGET_DESC28#include "AVRGenRegisterInfo.inc"29 30namespace llvm {31 32AVRRegisterInfo::AVRRegisterInfo() : AVRGenRegisterInfo(0) {}33 34const uint16_t *35AVRRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {36 const AVRMachineFunctionInfo *AFI = MF->getInfo<AVRMachineFunctionInfo>();37 const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();38 if (STI.hasTinyEncoding())39 return AFI->isInterruptOrSignalHandler() ? CSR_InterruptsTiny_SaveList40 : CSR_NormalTiny_SaveList;41 else42 return AFI->isInterruptOrSignalHandler() ? CSR_Interrupts_SaveList43 : CSR_Normal_SaveList;44}45 46const uint32_t *47AVRRegisterInfo::getCallPreservedMask(const MachineFunction &MF,48 CallingConv::ID CC) const {49 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();50 return STI.hasTinyEncoding() ? CSR_NormalTiny_RegMask : CSR_Normal_RegMask;51}52 53BitVector AVRRegisterInfo::getReservedRegs(const MachineFunction &MF) const {54 BitVector Reserved(getNumRegs());55 56 // Reserve the intermediate result registers r1 and r257 // The result of instructions like 'mul' is always stored here.58 // R0/R1/R1R0 are always reserved on both avr and avrtiny.59 Reserved.set(AVR::R0);60 Reserved.set(AVR::R1);61 Reserved.set(AVR::R1R0);62 63 // Reserve the stack pointer.64 Reserved.set(AVR::SPL);65 Reserved.set(AVR::SPH);66 Reserved.set(AVR::SP);67 68 // Reserve R2~R17 only on avrtiny.69 if (MF.getSubtarget<AVRSubtarget>().hasTinyEncoding()) {70 // Reserve 8-bit registers R2~R15, Rtmp(R16) and Zero(R17).71 for (unsigned Reg = AVR::R2; Reg <= AVR::R17; Reg++)72 Reserved.set(Reg);73 // Reserve 16-bit registers R3R2~R18R17.74 for (unsigned Reg = AVR::R3R2; Reg <= AVR::R18R17; Reg++)75 Reserved.set(Reg);76 }77 78 // We tenatively reserve the frame pointer register r29:r28 because the79 // function may require one, but we cannot tell until register allocation80 // is complete, which can be too late.81 //82 // Instead we just unconditionally reserve the Y register.83 //84 // TODO: Write a pass to enumerate functions which reserved the Y register85 // but didn't end up needing a frame pointer. In these, we can86 // convert one or two of the spills inside to use the Y register.87 Reserved.set(AVR::R28);88 Reserved.set(AVR::R29);89 Reserved.set(AVR::R29R28);90 91 return Reserved;92}93 94const TargetRegisterClass *95AVRRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,96 const MachineFunction &MF) const {97 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();98 if (TRI->isTypeLegalForClass(*RC, MVT::i16)) {99 return &AVR::DREGSRegClass;100 }101 102 if (TRI->isTypeLegalForClass(*RC, MVT::i8)) {103 return &AVR::GPR8RegClass;104 }105 106 llvm_unreachable("Invalid register size");107}108 109/// Fold a frame offset shared between two add instructions into a single one.110static void foldFrameOffset(MachineBasicBlock::iterator &II, int &Offset,111 Register DstReg) {112 MachineInstr &MI = *II;113 int Opcode = MI.getOpcode();114 115 // Don't bother trying if the next instruction is not an add or a sub.116 if ((Opcode != AVR::SUBIWRdK) && (Opcode != AVR::ADIWRdK)) {117 return;118 }119 120 // Check that DstReg matches with next instruction, otherwise the instruction121 // is not related to stack address manipulation.122 if (DstReg != MI.getOperand(0).getReg()) {123 return;124 }125 126 // Add the offset in the next instruction to our offset.127 switch (Opcode) {128 case AVR::SUBIWRdK:129 Offset += -MI.getOperand(2).getImm();130 break;131 case AVR::ADIWRdK:132 Offset += MI.getOperand(2).getImm();133 break;134 }135 136 // Finally remove the instruction.137 II++;138 MI.eraseFromParent();139}140 141bool AVRRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,142 int SPAdj, unsigned FIOperandNum,143 RegScavenger *RS) const {144 assert(SPAdj == 0 && "Unexpected SPAdj value");145 146 MachineInstr &MI = *II;147 DebugLoc dl = MI.getDebugLoc();148 MachineBasicBlock &MBB = *MI.getParent();149 const MachineFunction &MF = *MBB.getParent();150 const AVRTargetMachine &TM = (const AVRTargetMachine &)MF.getTarget();151 const TargetInstrInfo &TII = *TM.getSubtargetImpl()->getInstrInfo();152 const MachineFrameInfo &MFI = MF.getFrameInfo();153 const TargetFrameLowering *TFI = TM.getSubtargetImpl()->getFrameLowering();154 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();155 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();156 int Offset = MFI.getObjectOffset(FrameIndex);157 158 // Add one to the offset because SP points to an empty slot.159 Offset += MFI.getStackSize() - TFI->getOffsetOfLocalArea() + 1;160 // Fold incoming offset.161 Offset += MI.getOperand(FIOperandNum + 1).getImm();162 163 // This is actually "load effective address" of the stack slot164 // instruction. We have only two-address instructions, thus we need to165 // expand it into move + add.166 if (MI.getOpcode() == AVR::FRMIDX) {167 Register DstReg = MI.getOperand(0).getReg();168 assert(DstReg != AVR::R29R28 && "Dest reg cannot be the frame pointer");169 170 // Copy the frame pointer.171 if (STI.hasMOVW()) {172 BuildMI(MBB, MI, dl, TII.get(AVR::MOVWRdRr), DstReg).addReg(AVR::R29R28);173 } else {174 Register DstLoReg, DstHiReg;175 splitReg(DstReg, DstLoReg, DstHiReg);176 BuildMI(MBB, MI, dl, TII.get(AVR::MOVRdRr), DstLoReg).addReg(AVR::R28);177 BuildMI(MBB, MI, dl, TII.get(AVR::MOVRdRr), DstHiReg).addReg(AVR::R29);178 }179 180 assert(Offset > 0 && "Invalid offset");181 182 // We need to materialize the offset via an add instruction.183 unsigned Opcode;184 185 II++; // Skip over the FRMIDX instruction.186 187 // Generally, to load a frame address two add instructions are emitted that188 // could get folded into a single one:189 // movw r31:r30, r29:r28190 // adiw r31:r30, 29191 // adiw r31:r30, 16192 // to:193 // movw r31:r30, r29:r28194 // adiw r31:r30, 45195 if (II != MBB.end())196 foldFrameOffset(II, Offset, DstReg);197 198 // Select the best opcode based on DstReg and the offset size.199 switch (DstReg) {200 case AVR::R25R24:201 case AVR::R27R26:202 case AVR::R31R30: {203 if (isUInt<6>(Offset) && STI.hasADDSUBIW()) {204 Opcode = AVR::ADIWRdK;205 break;206 }207 [[fallthrough]];208 }209 default: {210 // This opcode will get expanded into a pair of subi/sbci.211 Opcode = AVR::SUBIWRdK;212 Offset = -Offset;213 break;214 }215 }216 217 MachineInstr *New = BuildMI(MBB, II, dl, TII.get(Opcode), DstReg)218 .addReg(DstReg, RegState::Kill)219 .addImm(Offset);220 New->getOperand(3).setIsDead();221 222 MI.eraseFromParent(); // remove FRMIDX223 224 return false;225 }226 227 // On most AVRs, we can use an offset up to 62 for load/store with228 // displacement (63 for byte values, 62 for word values). However, the229 // "reduced tiny" cores don't support load/store with displacement. So for230 // them, we force an offset of 0 meaning that any positive offset will require231 // adjusting the frame pointer.232 int MaxOffset = STI.hasTinyEncoding() ? 0 : 62;233 234 // If the offset is too big we have to adjust and restore the frame pointer235 // to materialize a valid load/store with displacement.236 //: TODO: consider using only one adiw/sbiw chain for more than one frame237 //: index238 if (Offset > MaxOffset) {239 unsigned AddOpc = AVR::ADIWRdK, SubOpc = AVR::SBIWRdK;240 int AddOffset = Offset - MaxOffset;241 242 // For huge offsets where adiw/sbiw cannot be used use a pair of subi/sbci.243 if ((Offset - MaxOffset) > 63 || !STI.hasADDSUBIW()) {244 AddOpc = AVR::SUBIWRdK;245 SubOpc = AVR::SUBIWRdK;246 AddOffset = -AddOffset;247 }248 249 // It is possible that the spiller places this frame instruction in between250 // a compare and branch, invalidating the contents of SREG set by the251 // compare instruction because of the add/sub pairs. Conservatively save and252 // restore SREG before and after each add/sub pair.253 BuildMI(MBB, II, dl, TII.get(AVR::INRdA), STI.getTmpRegister())254 .addImm(STI.getIORegSREG());255 256 MachineInstr *New = BuildMI(MBB, II, dl, TII.get(AddOpc), AVR::R29R28)257 .addReg(AVR::R29R28, RegState::Kill)258 .addImm(AddOffset);259 New->getOperand(3).setIsDead();260 261 // Restore SREG.262 BuildMI(MBB, std::next(II), dl, TII.get(AVR::OUTARr))263 .addImm(STI.getIORegSREG())264 .addReg(STI.getTmpRegister(), RegState::Kill);265 266 // No need to set SREG as dead here otherwise if the next instruction is a267 // cond branch it will be using a dead register.268 BuildMI(MBB, std::next(II), dl, TII.get(SubOpc), AVR::R29R28)269 .addReg(AVR::R29R28, RegState::Kill)270 .addImm(Offset - MaxOffset);271 272 Offset = MaxOffset;273 }274 275 MI.getOperand(FIOperandNum).ChangeToRegister(AVR::R29R28, false);276 assert(isUInt<6>(Offset) && "Offset is out of range");277 MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);278 return false;279}280 281Register AVRRegisterInfo::getFrameRegister(const MachineFunction &MF) const {282 const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();283 if (TFI->hasFP(MF)) {284 // The Y pointer register285 return AVR::R28;286 }287 288 return AVR::SP;289}290 291const TargetRegisterClass *292AVRRegisterInfo::getPointerRegClass(unsigned Kind) const {293 // FIXME: Currently we're using avr-gcc as reference, so we restrict294 // ptrs to Y and Z regs. Though avr-gcc has buggy implementation295 // of memory constraint, so we can fix it and bit avr-gcc here ;-)296 return &AVR::PTRDISPREGSRegClass;297}298 299void AVRRegisterInfo::splitReg(Register Reg, Register &LoReg,300 Register &HiReg) const {301 assert(AVR::DREGSRegClass.contains(Reg) && "can only split 16-bit registers");302 303 LoReg = getSubReg(Reg, AVR::sub_lo);304 HiReg = getSubReg(Reg, AVR::sub_hi);305}306 307bool AVRRegisterInfo::shouldCoalesce(308 MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg,309 const TargetRegisterClass *DstRC, unsigned DstSubReg,310 const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {311 if (this->getRegClass(AVR::PTRDISPREGSRegClassID)->hasSubClassEq(NewRC)) {312 return false;313 }314 315 return TargetRegisterInfo::shouldCoalesce(MI, SrcRC, SubReg, DstRC, DstSubReg,316 NewRC, LIS);317}318 319} // end of namespace llvm320