Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
35267 views
//===-- AVRExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a pass that expands pseudo instructions into target9// instructions. This pass should be run after register allocation but before10// the post-regalloc scheduling pass.11//12//===----------------------------------------------------------------------===//1314#include "AVR.h"15#include "AVRInstrInfo.h"16#include "AVRTargetMachine.h"17#include "MCTargetDesc/AVRMCTargetDesc.h"1819#include "llvm/CodeGen/MachineFunctionPass.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineRegisterInfo.h"22#include "llvm/CodeGen/TargetRegisterInfo.h"2324using namespace llvm;2526#define AVR_EXPAND_PSEUDO_NAME "AVR pseudo instruction expansion pass"2728namespace {2930/// Expands "placeholder" instructions marked as pseudo into31/// actual AVR instructions.32class AVRExpandPseudo : public MachineFunctionPass {33public:34static char ID;3536AVRExpandPseudo() : MachineFunctionPass(ID) {37initializeAVRExpandPseudoPass(*PassRegistry::getPassRegistry());38}3940bool runOnMachineFunction(MachineFunction &MF) override;4142StringRef getPassName() const override { return AVR_EXPAND_PSEUDO_NAME; }4344private:45typedef MachineBasicBlock Block;46typedef Block::iterator BlockIt;4748const AVRRegisterInfo *TRI;49const TargetInstrInfo *TII;5051bool expandMBB(Block &MBB);52bool expandMI(Block &MBB, BlockIt MBBI);53template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);5455MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {56return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));57}5859MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode,60Register DstReg) {61return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode), DstReg);62}6364MachineRegisterInfo &getRegInfo(Block &MBB) {65return MBB.getParent()->getRegInfo();66}6768bool expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI);69bool expandLogic(unsigned Op, Block &MBB, BlockIt MBBI);70bool expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI);71bool isLogicImmOpRedundant(unsigned Op, unsigned ImmVal) const;72bool isLogicRegOpUndef(unsigned Op, unsigned ImmVal) const;7374template <typename Func> bool expandAtomic(Block &MBB, BlockIt MBBI, Func f);7576template <typename Func>77bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI, Func f);7879bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI);8081/// Specific shift implementation for int8.82bool expandLSLB7Rd(Block &MBB, BlockIt MBBI);83bool expandLSRB7Rd(Block &MBB, BlockIt MBBI);84bool expandASRB6Rd(Block &MBB, BlockIt MBBI);85bool expandASRB7Rd(Block &MBB, BlockIt MBBI);8687/// Specific shift implementation for int16.88bool expandLSLW4Rd(Block &MBB, BlockIt MBBI);89bool expandLSRW4Rd(Block &MBB, BlockIt MBBI);90bool expandASRW7Rd(Block &MBB, BlockIt MBBI);91bool expandLSLW8Rd(Block &MBB, BlockIt MBBI);92bool expandLSRW8Rd(Block &MBB, BlockIt MBBI);93bool expandASRW8Rd(Block &MBB, BlockIt MBBI);94bool expandLSLW12Rd(Block &MBB, BlockIt MBBI);95bool expandLSRW12Rd(Block &MBB, BlockIt MBBI);96bool expandASRW14Rd(Block &MBB, BlockIt MBBI);97bool expandASRW15Rd(Block &MBB, BlockIt MBBI);9899// Common implementation of LPMWRdZ and ELPMWRdZ.100bool expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsELPM);101// Common implementation of LPMBRdZ and ELPMBRdZ.102bool expandLPMBELPMB(Block &MBB, BlockIt MBBI, bool IsELPM);103// Common implementation of ROLBRdR1 and ROLBRdR17.104bool expandROLBRd(Block &MBB, BlockIt MBBI);105};106107char AVRExpandPseudo::ID = 0;108109bool AVRExpandPseudo::expandMBB(MachineBasicBlock &MBB) {110bool Modified = false;111112BlockIt MBBI = MBB.begin(), E = MBB.end();113while (MBBI != E) {114BlockIt NMBBI = std::next(MBBI);115Modified |= expandMI(MBB, MBBI);116MBBI = NMBBI;117}118119return Modified;120}121122bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {123bool Modified = false;124125const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();126TRI = STI.getRegisterInfo();127TII = STI.getInstrInfo();128129for (Block &MBB : MF) {130bool ContinueExpanding = true;131unsigned ExpandCount = 0;132133// Continue expanding the block until all pseudos are expanded.134do {135assert(ExpandCount < 10 && "pseudo expand limit reached");136(void)ExpandCount;137138bool BlockModified = expandMBB(MBB);139Modified |= BlockModified;140ExpandCount++;141142ContinueExpanding = BlockModified;143} while (ContinueExpanding);144}145146return Modified;147}148149bool AVRExpandPseudo::expandArith(unsigned OpLo, unsigned OpHi, Block &MBB,150BlockIt MBBI) {151MachineInstr &MI = *MBBI;152Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;153Register DstReg = MI.getOperand(0).getReg();154Register SrcReg = MI.getOperand(2).getReg();155bool DstIsDead = MI.getOperand(0).isDead();156bool DstIsKill = MI.getOperand(1).isKill();157bool SrcIsKill = MI.getOperand(2).isKill();158bool ImpIsDead = MI.getOperand(3).isDead();159TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);160TRI->splitReg(DstReg, DstLoReg, DstHiReg);161162buildMI(MBB, MBBI, OpLo)163.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))164.addReg(DstLoReg, getKillRegState(DstIsKill))165.addReg(SrcLoReg, getKillRegState(SrcIsKill));166167auto MIBHI =168buildMI(MBB, MBBI, OpHi)169.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))170.addReg(DstHiReg, getKillRegState(DstIsKill))171.addReg(SrcHiReg, getKillRegState(SrcIsKill));172173if (ImpIsDead)174MIBHI->getOperand(3).setIsDead();175176// SREG is always implicitly killed177MIBHI->getOperand(4).setIsKill();178179MI.eraseFromParent();180return true;181}182183bool AVRExpandPseudo::expandLogic(unsigned Op, Block &MBB, BlockIt MBBI) {184MachineInstr &MI = *MBBI;185Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;186Register DstReg = MI.getOperand(0).getReg();187Register SrcReg = MI.getOperand(2).getReg();188bool DstIsDead = MI.getOperand(0).isDead();189bool DstIsKill = MI.getOperand(1).isKill();190bool SrcIsKill = MI.getOperand(2).isKill();191bool ImpIsDead = MI.getOperand(3).isDead();192TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);193TRI->splitReg(DstReg, DstLoReg, DstHiReg);194195auto MIBLO =196buildMI(MBB, MBBI, Op)197.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))198.addReg(DstLoReg, getKillRegState(DstIsKill))199.addReg(SrcLoReg, getKillRegState(SrcIsKill));200201// SREG is always implicitly dead202MIBLO->getOperand(3).setIsDead();203204auto MIBHI =205buildMI(MBB, MBBI, Op)206.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))207.addReg(DstHiReg, getKillRegState(DstIsKill))208.addReg(SrcHiReg, getKillRegState(SrcIsKill));209210if (ImpIsDead)211MIBHI->getOperand(3).setIsDead();212213MI.eraseFromParent();214return true;215}216217bool AVRExpandPseudo::isLogicImmOpRedundant(unsigned Op,218unsigned ImmVal) const {219220// ANDI Rd, 0xff is redundant.221if (Op == AVR::ANDIRdK && ImmVal == 0xff)222return true;223224// ORI Rd, 0x0 is redundant.225if (Op == AVR::ORIRdK && ImmVal == 0x0)226return true;227228return false;229}230231bool AVRExpandPseudo::isLogicRegOpUndef(unsigned Op, unsigned ImmVal) const {232// ANDI Rd, 0x00 clears all input bits.233if (Op == AVR::ANDIRdK && ImmVal == 0x00)234return true;235236// ORI Rd, 0xff sets all input bits.237if (Op == AVR::ORIRdK && ImmVal == 0xff)238return true;239240return false;241}242243bool AVRExpandPseudo::expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI) {244MachineInstr &MI = *MBBI;245Register DstLoReg, DstHiReg;246Register DstReg = MI.getOperand(0).getReg();247bool DstIsDead = MI.getOperand(0).isDead();248bool SrcIsKill = MI.getOperand(1).isKill();249bool ImpIsDead = MI.getOperand(3).isDead();250unsigned Imm = MI.getOperand(2).getImm();251unsigned Lo8 = Imm & 0xff;252unsigned Hi8 = (Imm >> 8) & 0xff;253TRI->splitReg(DstReg, DstLoReg, DstHiReg);254255if (!isLogicImmOpRedundant(Op, Lo8)) {256auto MIBLO =257buildMI(MBB, MBBI, Op)258.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))259.addReg(DstLoReg, getKillRegState(SrcIsKill))260.addImm(Lo8);261262// SREG is always implicitly dead263MIBLO->getOperand(3).setIsDead();264265if (isLogicRegOpUndef(Op, Lo8))266MIBLO->getOperand(1).setIsUndef(true);267}268269if (!isLogicImmOpRedundant(Op, Hi8)) {270auto MIBHI =271buildMI(MBB, MBBI, Op)272.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))273.addReg(DstHiReg, getKillRegState(SrcIsKill))274.addImm(Hi8);275276if (ImpIsDead)277MIBHI->getOperand(3).setIsDead();278279if (isLogicRegOpUndef(Op, Hi8))280MIBHI->getOperand(1).setIsUndef(true);281}282283MI.eraseFromParent();284return true;285}286287template <>288bool AVRExpandPseudo::expand<AVR::ADDWRdRr>(Block &MBB, BlockIt MBBI) {289return expandArith(AVR::ADDRdRr, AVR::ADCRdRr, MBB, MBBI);290}291292template <>293bool AVRExpandPseudo::expand<AVR::ADCWRdRr>(Block &MBB, BlockIt MBBI) {294return expandArith(AVR::ADCRdRr, AVR::ADCRdRr, MBB, MBBI);295}296297template <>298bool AVRExpandPseudo::expand<AVR::SUBWRdRr>(Block &MBB, BlockIt MBBI) {299return expandArith(AVR::SUBRdRr, AVR::SBCRdRr, MBB, MBBI);300}301302template <>303bool AVRExpandPseudo::expand<AVR::SUBIWRdK>(Block &MBB, BlockIt MBBI) {304MachineInstr &MI = *MBBI;305Register DstLoReg, DstHiReg;306Register DstReg = MI.getOperand(0).getReg();307bool DstIsDead = MI.getOperand(0).isDead();308bool SrcIsKill = MI.getOperand(1).isKill();309bool ImpIsDead = MI.getOperand(3).isDead();310TRI->splitReg(DstReg, DstLoReg, DstHiReg);311312auto MIBLO =313buildMI(MBB, MBBI, AVR::SUBIRdK)314.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))315.addReg(DstLoReg, getKillRegState(SrcIsKill));316317auto MIBHI =318buildMI(MBB, MBBI, AVR::SBCIRdK)319.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))320.addReg(DstHiReg, getKillRegState(SrcIsKill));321322switch (MI.getOperand(2).getType()) {323case MachineOperand::MO_GlobalAddress: {324const GlobalValue *GV = MI.getOperand(2).getGlobal();325int64_t Offs = MI.getOperand(2).getOffset();326unsigned TF = MI.getOperand(2).getTargetFlags();327MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_LO);328MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_HI);329break;330}331case MachineOperand::MO_Immediate: {332unsigned Imm = MI.getOperand(2).getImm();333MIBLO.addImm(Imm & 0xff);334MIBHI.addImm((Imm >> 8) & 0xff);335break;336}337default:338llvm_unreachable("Unknown operand type!");339}340341if (ImpIsDead)342MIBHI->getOperand(3).setIsDead();343344// SREG is always implicitly killed345MIBHI->getOperand(4).setIsKill();346347MI.eraseFromParent();348return true;349}350351template <>352bool AVRExpandPseudo::expand<AVR::SBCWRdRr>(Block &MBB, BlockIt MBBI) {353return expandArith(AVR::SBCRdRr, AVR::SBCRdRr, MBB, MBBI);354}355356template <>357bool AVRExpandPseudo::expand<AVR::SBCIWRdK>(Block &MBB, BlockIt MBBI) {358MachineInstr &MI = *MBBI;359Register DstLoReg, DstHiReg;360Register DstReg = MI.getOperand(0).getReg();361bool DstIsDead = MI.getOperand(0).isDead();362bool SrcIsKill = MI.getOperand(1).isKill();363bool ImpIsDead = MI.getOperand(3).isDead();364unsigned Imm = MI.getOperand(2).getImm();365unsigned Lo8 = Imm & 0xff;366unsigned Hi8 = (Imm >> 8) & 0xff;367unsigned OpLo = AVR::SBCIRdK;368unsigned OpHi = AVR::SBCIRdK;369TRI->splitReg(DstReg, DstLoReg, DstHiReg);370371auto MIBLO =372buildMI(MBB, MBBI, OpLo)373.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))374.addReg(DstLoReg, getKillRegState(SrcIsKill))375.addImm(Lo8);376377// SREG is always implicitly killed378MIBLO->getOperand(4).setIsKill();379380auto MIBHI =381buildMI(MBB, MBBI, OpHi)382.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))383.addReg(DstHiReg, getKillRegState(SrcIsKill))384.addImm(Hi8);385386if (ImpIsDead)387MIBHI->getOperand(3).setIsDead();388389// SREG is always implicitly killed390MIBHI->getOperand(4).setIsKill();391392MI.eraseFromParent();393return true;394}395396template <>397bool AVRExpandPseudo::expand<AVR::ANDWRdRr>(Block &MBB, BlockIt MBBI) {398return expandLogic(AVR::ANDRdRr, MBB, MBBI);399}400401template <>402bool AVRExpandPseudo::expand<AVR::ANDIWRdK>(Block &MBB, BlockIt MBBI) {403return expandLogicImm(AVR::ANDIRdK, MBB, MBBI);404}405406template <>407bool AVRExpandPseudo::expand<AVR::ORWRdRr>(Block &MBB, BlockIt MBBI) {408return expandLogic(AVR::ORRdRr, MBB, MBBI);409}410411template <>412bool AVRExpandPseudo::expand<AVR::ORIWRdK>(Block &MBB, BlockIt MBBI) {413return expandLogicImm(AVR::ORIRdK, MBB, MBBI);414}415416template <>417bool AVRExpandPseudo::expand<AVR::EORWRdRr>(Block &MBB, BlockIt MBBI) {418return expandLogic(AVR::EORRdRr, MBB, MBBI);419}420421template <>422bool AVRExpandPseudo::expand<AVR::COMWRd>(Block &MBB, BlockIt MBBI) {423MachineInstr &MI = *MBBI;424Register DstLoReg, DstHiReg;425Register DstReg = MI.getOperand(0).getReg();426bool DstIsDead = MI.getOperand(0).isDead();427bool DstIsKill = MI.getOperand(1).isKill();428bool ImpIsDead = MI.getOperand(2).isDead();429unsigned OpLo = AVR::COMRd;430unsigned OpHi = AVR::COMRd;431TRI->splitReg(DstReg, DstLoReg, DstHiReg);432433auto MIBLO =434buildMI(MBB, MBBI, OpLo)435.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))436.addReg(DstLoReg, getKillRegState(DstIsKill));437438// SREG is always implicitly dead439MIBLO->getOperand(2).setIsDead();440441auto MIBHI =442buildMI(MBB, MBBI, OpHi)443.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))444.addReg(DstHiReg, getKillRegState(DstIsKill));445446if (ImpIsDead)447MIBHI->getOperand(2).setIsDead();448449MI.eraseFromParent();450return true;451}452453template <>454bool AVRExpandPseudo::expand<AVR::NEGWRd>(Block &MBB, BlockIt MBBI) {455MachineInstr &MI = *MBBI;456Register DstLoReg, DstHiReg;457Register DstReg = MI.getOperand(0).getReg();458Register ZeroReg = MI.getOperand(2).getReg();459bool DstIsDead = MI.getOperand(0).isDead();460bool DstIsKill = MI.getOperand(1).isKill();461bool ImpIsDead = MI.getOperand(2).isDead();462TRI->splitReg(DstReg, DstLoReg, DstHiReg);463464// Do NEG on the upper byte.465auto MIBHI =466buildMI(MBB, MBBI, AVR::NEGRd)467.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))468.addReg(DstHiReg, RegState::Kill);469// SREG is always implicitly dead470MIBHI->getOperand(2).setIsDead();471472// Do NEG on the lower byte.473buildMI(MBB, MBBI, AVR::NEGRd)474.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))475.addReg(DstLoReg, getKillRegState(DstIsKill));476477// Do an extra SBC.478auto MISBCI =479buildMI(MBB, MBBI, AVR::SBCRdRr)480.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))481.addReg(DstHiReg, getKillRegState(DstIsKill))482.addReg(ZeroReg);483if (ImpIsDead)484MISBCI->getOperand(3).setIsDead();485// SREG is always implicitly killed486MISBCI->getOperand(4).setIsKill();487488MI.eraseFromParent();489return true;490}491492template <>493bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {494MachineInstr &MI = *MBBI;495Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;496Register DstReg = MI.getOperand(0).getReg();497Register SrcReg = MI.getOperand(1).getReg();498bool DstIsKill = MI.getOperand(0).isKill();499bool SrcIsKill = MI.getOperand(1).isKill();500bool ImpIsDead = MI.getOperand(2).isDead();501unsigned OpLo = AVR::CPRdRr;502unsigned OpHi = AVR::CPCRdRr;503TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);504TRI->splitReg(DstReg, DstLoReg, DstHiReg);505506// Low part507buildMI(MBB, MBBI, OpLo)508.addReg(DstLoReg, getKillRegState(DstIsKill))509.addReg(SrcLoReg, getKillRegState(SrcIsKill));510511auto MIBHI = buildMI(MBB, MBBI, OpHi)512.addReg(DstHiReg, getKillRegState(DstIsKill))513.addReg(SrcHiReg, getKillRegState(SrcIsKill));514515if (ImpIsDead)516MIBHI->getOperand(2).setIsDead();517518// SREG is always implicitly killed519MIBHI->getOperand(3).setIsKill();520521MI.eraseFromParent();522return true;523}524525template <>526bool AVRExpandPseudo::expand<AVR::CPCWRdRr>(Block &MBB, BlockIt MBBI) {527MachineInstr &MI = *MBBI;528Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;529Register DstReg = MI.getOperand(0).getReg();530Register SrcReg = MI.getOperand(1).getReg();531bool DstIsKill = MI.getOperand(0).isKill();532bool SrcIsKill = MI.getOperand(1).isKill();533bool ImpIsDead = MI.getOperand(2).isDead();534unsigned OpLo = AVR::CPCRdRr;535unsigned OpHi = AVR::CPCRdRr;536TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);537TRI->splitReg(DstReg, DstLoReg, DstHiReg);538539auto MIBLO = buildMI(MBB, MBBI, OpLo)540.addReg(DstLoReg, getKillRegState(DstIsKill))541.addReg(SrcLoReg, getKillRegState(SrcIsKill));542543// SREG is always implicitly killed544MIBLO->getOperand(3).setIsKill();545546auto MIBHI = buildMI(MBB, MBBI, OpHi)547.addReg(DstHiReg, getKillRegState(DstIsKill))548.addReg(SrcHiReg, getKillRegState(SrcIsKill));549550if (ImpIsDead)551MIBHI->getOperand(2).setIsDead();552553// SREG is always implicitly killed554MIBHI->getOperand(3).setIsKill();555556MI.eraseFromParent();557return true;558}559560template <>561bool AVRExpandPseudo::expand<AVR::LDIWRdK>(Block &MBB, BlockIt MBBI) {562MachineInstr &MI = *MBBI;563Register DstLoReg, DstHiReg;564Register DstReg = MI.getOperand(0).getReg();565bool DstIsDead = MI.getOperand(0).isDead();566unsigned OpLo = AVR::LDIRdK;567unsigned OpHi = AVR::LDIRdK;568TRI->splitReg(DstReg, DstLoReg, DstHiReg);569570auto MIBLO =571buildMI(MBB, MBBI, OpLo)572.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));573574auto MIBHI =575buildMI(MBB, MBBI, OpHi)576.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));577578switch (MI.getOperand(1).getType()) {579case MachineOperand::MO_GlobalAddress: {580const GlobalValue *GV = MI.getOperand(1).getGlobal();581int64_t Offs = MI.getOperand(1).getOffset();582unsigned TF = MI.getOperand(1).getTargetFlags();583584MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_LO);585MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_HI);586break;587}588case MachineOperand::MO_BlockAddress: {589const BlockAddress *BA = MI.getOperand(1).getBlockAddress();590unsigned TF = MI.getOperand(1).getTargetFlags();591592MIBLO.add(MachineOperand::CreateBA(BA, TF | AVRII::MO_LO));593MIBHI.add(MachineOperand::CreateBA(BA, TF | AVRII::MO_HI));594break;595}596case MachineOperand::MO_Immediate: {597unsigned Imm = MI.getOperand(1).getImm();598599MIBLO.addImm(Imm & 0xff);600MIBHI.addImm((Imm >> 8) & 0xff);601break;602}603default:604llvm_unreachable("Unknown operand type!");605}606607MI.eraseFromParent();608return true;609}610611template <>612bool AVRExpandPseudo::expand<AVR::LDSWRdK>(Block &MBB, BlockIt MBBI) {613MachineInstr &MI = *MBBI;614Register DstLoReg, DstHiReg;615Register DstReg = MI.getOperand(0).getReg();616bool DstIsDead = MI.getOperand(0).isDead();617unsigned OpLo = AVR::LDSRdK;618unsigned OpHi = AVR::LDSRdK;619TRI->splitReg(DstReg, DstLoReg, DstHiReg);620621auto MIBLO =622buildMI(MBB, MBBI, OpLo)623.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));624625auto MIBHI =626buildMI(MBB, MBBI, OpHi)627.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));628629switch (MI.getOperand(1).getType()) {630case MachineOperand::MO_GlobalAddress: {631const GlobalValue *GV = MI.getOperand(1).getGlobal();632int64_t Offs = MI.getOperand(1).getOffset();633unsigned TF = MI.getOperand(1).getTargetFlags();634635MIBLO.addGlobalAddress(GV, Offs, TF);636MIBHI.addGlobalAddress(GV, Offs + 1, TF);637break;638}639case MachineOperand::MO_Immediate: {640unsigned Imm = MI.getOperand(1).getImm();641642MIBLO.addImm(Imm);643MIBHI.addImm(Imm + 1);644break;645}646default:647llvm_unreachable("Unknown operand type!");648}649650MIBLO.setMemRefs(MI.memoperands());651MIBHI.setMemRefs(MI.memoperands());652653MI.eraseFromParent();654return true;655}656657template <>658bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {659MachineInstr &MI = *MBBI;660Register DstReg = MI.getOperand(0).getReg();661Register SrcReg = MI.getOperand(1).getReg();662bool DstIsKill = MI.getOperand(0).isKill();663bool SrcIsKill = MI.getOperand(1).isKill();664const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();665666// DstReg has an earlyclobber so the register allocator will allocate them in667// separate registers.668assert(DstReg != SrcReg && "Dst and Src registers are the same!");669670if (STI.hasTinyEncoding()) {671// Handle this case in the expansion of LDDWRdPtrQ because it is very672// similar.673buildMI(MBB, MBBI, AVR::LDDWRdPtrQ)674.addDef(DstReg, getKillRegState(DstIsKill))675.addReg(SrcReg, getKillRegState(SrcIsKill))676.addImm(0)677.setMemRefs(MI.memoperands());678679} else {680Register DstLoReg, DstHiReg;681TRI->splitReg(DstReg, DstLoReg, DstHiReg);682683// Load low byte.684buildMI(MBB, MBBI, AVR::LDRdPtr)685.addReg(DstLoReg, RegState::Define)686.addReg(SrcReg)687.setMemRefs(MI.memoperands());688689// Load high byte.690buildMI(MBB, MBBI, AVR::LDDRdPtrQ)691.addReg(DstHiReg, RegState::Define)692.addReg(SrcReg, getKillRegState(SrcIsKill))693.addImm(1)694.setMemRefs(MI.memoperands());695}696697MI.eraseFromParent();698return true;699}700701template <>702bool AVRExpandPseudo::expand<AVR::LDWRdPtrPi>(Block &MBB, BlockIt MBBI) {703MachineInstr &MI = *MBBI;704Register DstLoReg, DstHiReg;705Register DstReg = MI.getOperand(0).getReg();706Register SrcReg = MI.getOperand(1).getReg();707bool DstIsDead = MI.getOperand(0).isDead();708bool SrcIsDead = MI.getOperand(1).isKill();709unsigned OpLo = AVR::LDRdPtrPi;710unsigned OpHi = AVR::LDRdPtrPi;711TRI->splitReg(DstReg, DstLoReg, DstHiReg);712713assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");714715auto MIBLO =716buildMI(MBB, MBBI, OpLo)717.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))718.addReg(SrcReg, RegState::Define)719.addReg(SrcReg, RegState::Kill);720721auto MIBHI =722buildMI(MBB, MBBI, OpHi)723.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))724.addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))725.addReg(SrcReg, RegState::Kill);726727MIBLO.setMemRefs(MI.memoperands());728MIBHI.setMemRefs(MI.memoperands());729730MI.eraseFromParent();731return true;732}733734template <>735bool AVRExpandPseudo::expand<AVR::LDWRdPtrPd>(Block &MBB, BlockIt MBBI) {736MachineInstr &MI = *MBBI;737Register DstLoReg, DstHiReg;738Register DstReg = MI.getOperand(0).getReg();739Register SrcReg = MI.getOperand(1).getReg();740bool DstIsDead = MI.getOperand(0).isDead();741bool SrcIsDead = MI.getOperand(1).isKill();742unsigned OpLo = AVR::LDRdPtrPd;743unsigned OpHi = AVR::LDRdPtrPd;744TRI->splitReg(DstReg, DstLoReg, DstHiReg);745746assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");747748auto MIBHI =749buildMI(MBB, MBBI, OpHi)750.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))751.addReg(SrcReg, RegState::Define)752.addReg(SrcReg, RegState::Kill);753754auto MIBLO =755buildMI(MBB, MBBI, OpLo)756.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))757.addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))758.addReg(SrcReg, RegState::Kill);759760MIBLO.setMemRefs(MI.memoperands());761MIBHI.setMemRefs(MI.memoperands());762763MI.eraseFromParent();764return true;765}766767template <>768bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {769MachineInstr &MI = *MBBI;770Register DstReg = MI.getOperand(0).getReg();771Register SrcReg = MI.getOperand(1).getReg();772unsigned Imm = MI.getOperand(2).getImm();773bool DstIsKill = MI.getOperand(0).isKill();774bool SrcIsKill = MI.getOperand(1).isKill();775const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();776777// Since we add 1 to the Imm value for the high byte below, and 63 is the778// highest Imm value allowed for the instruction, 62 is the limit here.779assert(Imm <= 62 && "Offset is out of range");780781// DstReg has an earlyclobber so the register allocator will allocate them in782// separate registers.783assert(DstReg != SrcReg && "Dst and Src registers are the same!");784785if (STI.hasTinyEncoding()) {786// Reduced tiny cores don't support load/store with displacement. However,787// they do support postincrement. So we'll simply adjust the pointer before788// and after and use postincrement to load multiple registers.789790// Add offset. The offset can be 0 when expanding this instruction from the791// more specific LDWRdPtr instruction.792if (Imm != 0) {793buildMI(MBB, MBBI, AVR::SUBIWRdK, SrcReg)794.addReg(SrcReg)795.addImm(0x10000 - Imm);796}797798// Do a word load with postincrement. This will be lowered to a two byte799// load.800buildMI(MBB, MBBI, AVR::LDWRdPtrPi)801.addDef(DstReg, getKillRegState(DstIsKill))802.addReg(SrcReg, getKillRegState(SrcIsKill))803.addImm(0)804.setMemRefs(MI.memoperands());805806// If the pointer is used after the store instruction, subtract the new807// offset (with 2 added after the postincrement instructions) so it is the808// same as before.809if (!SrcIsKill) {810buildMI(MBB, MBBI, AVR::SUBIWRdK, SrcReg).addReg(SrcReg).addImm(Imm + 2);811}812} else {813Register DstLoReg, DstHiReg;814TRI->splitReg(DstReg, DstLoReg, DstHiReg);815816// Load low byte.817buildMI(MBB, MBBI, AVR::LDDRdPtrQ)818.addReg(DstLoReg, RegState::Define)819.addReg(SrcReg)820.addImm(Imm)821.setMemRefs(MI.memoperands());822823// Load high byte.824buildMI(MBB, MBBI, AVR::LDDRdPtrQ)825.addReg(DstHiReg, RegState::Define)826.addReg(SrcReg, getKillRegState(SrcIsKill))827.addImm(Imm + 1)828.setMemRefs(MI.memoperands());829}830831MI.eraseFromParent();832return true;833}834835bool AVRExpandPseudo::expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsELPM) {836MachineInstr &MI = *MBBI;837Register DstLoReg, DstHiReg;838Register DstReg = MI.getOperand(0).getReg();839Register SrcReg = MI.getOperand(1).getReg();840Register SrcLoReg, SrcHiReg;841bool SrcIsKill = MI.getOperand(1).isKill();842const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();843bool IsLPMRn = IsELPM ? STI.hasELPMX() : STI.hasLPMX();844845TRI->splitReg(DstReg, DstLoReg, DstHiReg);846TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);847848// Set the I/O register RAMPZ for ELPM.849if (IsELPM) {850Register Bank = MI.getOperand(2).getReg();851// out RAMPZ, rtmp852buildMI(MBB, MBBI, AVR::OUTARr).addImm(STI.getIORegRAMPZ()).addReg(Bank);853}854855// This is enforced by the @earlyclobber constraint.856assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");857858if (IsLPMRn) {859unsigned OpLo = IsELPM ? AVR::ELPMRdZPi : AVR::LPMRdZPi;860unsigned OpHi = IsELPM ? AVR::ELPMRdZ : AVR::LPMRdZ;861// Load low byte.862auto MIBLO = buildMI(MBB, MBBI, OpLo)863.addReg(DstLoReg, RegState::Define)864.addReg(SrcReg);865// Load high byte.866auto MIBHI = buildMI(MBB, MBBI, OpHi)867.addReg(DstHiReg, RegState::Define)868.addReg(SrcReg, getKillRegState(SrcIsKill));869MIBLO.setMemRefs(MI.memoperands());870MIBHI.setMemRefs(MI.memoperands());871} else {872unsigned Opc = IsELPM ? AVR::ELPM : AVR::LPM;873// Load low byte, and copy to the low destination register.874auto MIBLO = buildMI(MBB, MBBI, Opc);875buildMI(MBB, MBBI, AVR::MOVRdRr)876.addReg(DstLoReg, RegState::Define)877.addReg(AVR::R0, RegState::Kill);878MIBLO.setMemRefs(MI.memoperands());879// Increase the Z register by 1.880if (STI.hasADDSUBIW()) {881// adiw r31:r30, 1882auto MIINC = buildMI(MBB, MBBI, AVR::ADIWRdK)883.addReg(SrcReg, RegState::Define)884.addReg(SrcReg, getKillRegState(SrcIsKill))885.addImm(1);886MIINC->getOperand(3).setIsDead();887} else {888// subi r30, 255889// sbci r31, 255890buildMI(MBB, MBBI, AVR::SUBIRdK)891.addReg(SrcLoReg, RegState::Define)892.addReg(SrcLoReg, getKillRegState(SrcIsKill))893.addImm(255);894auto MIZHI = buildMI(MBB, MBBI, AVR::SBCIRdK)895.addReg(SrcHiReg, RegState::Define)896.addReg(SrcHiReg, getKillRegState(SrcIsKill))897.addImm(255);898MIZHI->getOperand(3).setIsDead();899MIZHI->getOperand(4).setIsKill();900}901// Load high byte, and copy to the high destination register.902auto MIBHI = buildMI(MBB, MBBI, Opc);903buildMI(MBB, MBBI, AVR::MOVRdRr)904.addReg(DstHiReg, RegState::Define)905.addReg(AVR::R0, RegState::Kill);906MIBHI.setMemRefs(MI.memoperands());907}908909// Restore the Z register if it is not killed.910if (!SrcIsKill) {911if (STI.hasADDSUBIW()) {912// sbiw r31:r30, 1913auto MIDEC = buildMI(MBB, MBBI, AVR::SBIWRdK)914.addReg(SrcReg, RegState::Define)915.addReg(SrcReg, getKillRegState(SrcIsKill))916.addImm(1);917MIDEC->getOperand(3).setIsDead();918} else {919// subi r30, 1920// sbci r31, 0921buildMI(MBB, MBBI, AVR::SUBIRdK)922.addReg(SrcLoReg, RegState::Define)923.addReg(SrcLoReg, getKillRegState(SrcIsKill))924.addImm(1);925auto MIZHI = buildMI(MBB, MBBI, AVR::SBCIRdK)926.addReg(SrcHiReg, RegState::Define)927.addReg(SrcHiReg, getKillRegState(SrcIsKill))928.addImm(0);929MIZHI->getOperand(3).setIsDead();930MIZHI->getOperand(4).setIsKill();931}932}933934MI.eraseFromParent();935return true;936}937938template <>939bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {940return expandLPMWELPMW(MBB, MBBI, false);941}942943template <>944bool AVRExpandPseudo::expand<AVR::ELPMWRdZ>(Block &MBB, BlockIt MBBI) {945return expandLPMWELPMW(MBB, MBBI, true);946}947948bool AVRExpandPseudo::expandLPMBELPMB(Block &MBB, BlockIt MBBI, bool IsELPM) {949MachineInstr &MI = *MBBI;950Register DstReg = MI.getOperand(0).getReg();951Register SrcReg = MI.getOperand(1).getReg();952bool SrcIsKill = MI.getOperand(1).isKill();953const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();954bool IsLPMRn = IsELPM ? STI.hasELPMX() : STI.hasLPMX();955956// Set the I/O register RAMPZ for ELPM (out RAMPZ, rtmp).957if (IsELPM) {958Register BankReg = MI.getOperand(2).getReg();959buildMI(MBB, MBBI, AVR::OUTARr).addImm(STI.getIORegRAMPZ()).addReg(BankReg);960}961962// Load byte.963if (IsLPMRn) {964unsigned Opc = IsELPM ? AVR::ELPMRdZ : AVR::LPMRdZ;965auto MILB = buildMI(MBB, MBBI, Opc)966.addReg(DstReg, RegState::Define)967.addReg(SrcReg, getKillRegState(SrcIsKill));968MILB.setMemRefs(MI.memoperands());969} else {970// For the basic ELPM/LPM instruction, its operand[0] is the implicit971// 'Z' register, and its operand[1] is the implicit 'R0' register.972unsigned Opc = IsELPM ? AVR::ELPM : AVR::LPM;973auto MILB = buildMI(MBB, MBBI, Opc);974buildMI(MBB, MBBI, AVR::MOVRdRr)975.addReg(DstReg, RegState::Define)976.addReg(AVR::R0, RegState::Kill);977MILB.setMemRefs(MI.memoperands());978}979980MI.eraseFromParent();981return true;982}983984template <>985bool AVRExpandPseudo::expand<AVR::ELPMBRdZ>(Block &MBB, BlockIt MBBI) {986return expandLPMBELPMB(MBB, MBBI, true);987}988989template <>990bool AVRExpandPseudo::expand<AVR::LPMBRdZ>(Block &MBB, BlockIt MBBI) {991return expandLPMBELPMB(MBB, MBBI, false);992}993994template <>995bool AVRExpandPseudo::expand<AVR::LPMWRdZPi>(Block &MBB, BlockIt MBBI) {996llvm_unreachable("16-bit LPMPi is unimplemented");997}998999template <>1000bool AVRExpandPseudo::expand<AVR::ELPMBRdZPi>(Block &MBB, BlockIt MBBI) {1001llvm_unreachable("8-bit ELPMPi is unimplemented");1002}10031004template <>1005bool AVRExpandPseudo::expand<AVR::ELPMWRdZPi>(Block &MBB, BlockIt MBBI) {1006llvm_unreachable("16-bit ELPMPi is unimplemented");1007}10081009template <typename Func>1010bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {1011MachineInstr &MI = *MBBI;1012const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();10131014// Store the SREG.1015buildMI(MBB, MBBI, AVR::INRdA)1016.addReg(STI.getTmpRegister(), RegState::Define)1017.addImm(STI.getIORegSREG());10181019// Disable exceptions.1020buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI10211022f(MI);10231024// Restore the status reg.1025buildMI(MBB, MBBI, AVR::OUTARr)1026.addImm(STI.getIORegSREG())1027.addReg(STI.getTmpRegister());10281029MI.eraseFromParent();1030return true;1031}10321033template <typename Func>1034bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode, Block &MBB,1035BlockIt MBBI, Func f) {1036return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {1037auto Op1 = MI.getOperand(0);1038auto Op2 = MI.getOperand(1);10391040MachineInstr &NewInst =1041*buildMI(MBB, MBBI, Opcode).add(Op1).add(Op2).getInstr();1042f(NewInst);1043});1044}10451046bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode, Block &MBB,1047BlockIt MBBI) {1048return expandAtomicBinaryOp(Opcode, MBB, MBBI, [](MachineInstr &MI) {});1049}10501051template <>1052bool AVRExpandPseudo::expand<AVR::AtomicLoad8>(Block &MBB, BlockIt MBBI) {1053return expandAtomicBinaryOp(AVR::LDRdPtr, MBB, MBBI);1054}10551056template <>1057bool AVRExpandPseudo::expand<AVR::AtomicLoad16>(Block &MBB, BlockIt MBBI) {1058return expandAtomicBinaryOp(AVR::LDWRdPtr, MBB, MBBI);1059}10601061template <>1062bool AVRExpandPseudo::expand<AVR::AtomicStore8>(Block &MBB, BlockIt MBBI) {1063return expandAtomicBinaryOp(AVR::STPtrRr, MBB, MBBI);1064}10651066template <>1067bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {1068return expandAtomicBinaryOp(AVR::STWPtrRr, MBB, MBBI);1069}10701071template <>1072bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {1073// On AVR, there is only one core and so atomic fences do nothing.1074MBBI->eraseFromParent();1075return true;1076}10771078template <>1079bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {1080const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();1081MachineInstr &MI = *MBBI;1082Register SrcLoReg, SrcHiReg;1083Register SrcReg = MI.getOperand(1).getReg();1084bool SrcIsKill = MI.getOperand(1).isKill();1085TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);10861087auto MIB0 = buildMI(MBB, MBBI, AVR::STSKRr);1088auto MIB1 = buildMI(MBB, MBBI, AVR::STSKRr);10891090switch (MI.getOperand(0).getType()) {1091case MachineOperand::MO_GlobalAddress: {1092const GlobalValue *GV = MI.getOperand(0).getGlobal();1093int64_t Offs = MI.getOperand(0).getOffset();1094unsigned TF = MI.getOperand(0).getTargetFlags();10951096if (STI.hasLowByteFirst()) {1097// Write the low byte first for XMEGA devices.1098MIB0.addGlobalAddress(GV, Offs, TF);1099MIB1.addGlobalAddress(GV, Offs + 1, TF);1100} else {1101// Write the high byte first for traditional devices.1102MIB0.addGlobalAddress(GV, Offs + 1, TF);1103MIB1.addGlobalAddress(GV, Offs, TF);1104}11051106break;1107}1108case MachineOperand::MO_Immediate: {1109unsigned Imm = MI.getOperand(0).getImm();11101111if (STI.hasLowByteFirst()) {1112// Write the low byte first for XMEGA devices.1113MIB0.addImm(Imm);1114MIB1.addImm(Imm + 1);1115} else {1116// Write the high byte first for traditional devices.1117MIB0.addImm(Imm + 1);1118MIB1.addImm(Imm);1119}11201121break;1122}1123default:1124llvm_unreachable("Unknown operand type!");1125}11261127if (STI.hasLowByteFirst()) {1128// Write the low byte first for XMEGA devices.1129MIB0.addReg(SrcLoReg, getKillRegState(SrcIsKill))1130.setMemRefs(MI.memoperands());1131MIB1.addReg(SrcHiReg, getKillRegState(SrcIsKill))1132.setMemRefs(MI.memoperands());1133} else {1134// Write the high byte first for traditional devices.1135MIB0.addReg(SrcHiReg, getKillRegState(SrcIsKill))1136.setMemRefs(MI.memoperands());1137MIB1.addReg(SrcLoReg, getKillRegState(SrcIsKill))1138.setMemRefs(MI.memoperands());1139}11401141MI.eraseFromParent();1142return true;1143}11441145template <>1146bool AVRExpandPseudo::expand<AVR::STWPtrRr>(Block &MBB, BlockIt MBBI) {1147MachineInstr &MI = *MBBI;1148Register DstReg = MI.getOperand(0).getReg();1149Register SrcReg = MI.getOperand(1).getReg();1150bool DstIsKill = MI.getOperand(0).isKill();1151bool DstIsUndef = MI.getOperand(0).isUndef();1152bool SrcIsKill = MI.getOperand(1).isKill();1153const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();11541155//: TODO: need to reverse this order like inw and stsw?11561157if (STI.hasTinyEncoding()) {1158// Handle this case in the expansion of STDWPtrQRr because it is very1159// similar.1160buildMI(MBB, MBBI, AVR::STDWPtrQRr)1161.addReg(DstReg,1162getKillRegState(DstIsKill) | getUndefRegState(DstIsUndef))1163.addImm(0)1164.addReg(SrcReg, getKillRegState(SrcIsKill))1165.setMemRefs(MI.memoperands());11661167} else {1168Register SrcLoReg, SrcHiReg;1169TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);1170if (STI.hasLowByteFirst()) {1171buildMI(MBB, MBBI, AVR::STPtrRr)1172.addReg(DstReg, getUndefRegState(DstIsUndef))1173.addReg(SrcLoReg, getKillRegState(SrcIsKill))1174.setMemRefs(MI.memoperands());1175buildMI(MBB, MBBI, AVR::STDPtrQRr)1176.addReg(DstReg, getUndefRegState(DstIsUndef))1177.addImm(1)1178.addReg(SrcHiReg, getKillRegState(SrcIsKill))1179.setMemRefs(MI.memoperands());1180} else {1181buildMI(MBB, MBBI, AVR::STDPtrQRr)1182.addReg(DstReg, getUndefRegState(DstIsUndef))1183.addImm(1)1184.addReg(SrcHiReg, getKillRegState(SrcIsKill))1185.setMemRefs(MI.memoperands());1186buildMI(MBB, MBBI, AVR::STPtrRr)1187.addReg(DstReg, getUndefRegState(DstIsUndef))1188.addReg(SrcLoReg, getKillRegState(SrcIsKill))1189.setMemRefs(MI.memoperands());1190}1191}11921193MI.eraseFromParent();1194return true;1195}11961197template <>1198bool AVRExpandPseudo::expand<AVR::STWPtrPiRr>(Block &MBB, BlockIt MBBI) {1199MachineInstr &MI = *MBBI;1200Register SrcLoReg, SrcHiReg;1201Register DstReg = MI.getOperand(0).getReg();1202Register SrcReg = MI.getOperand(2).getReg();1203unsigned Imm = MI.getOperand(3).getImm();1204bool DstIsDead = MI.getOperand(0).isDead();1205bool SrcIsKill = MI.getOperand(2).isKill();1206unsigned OpLo = AVR::STPtrPiRr;1207unsigned OpHi = AVR::STPtrPiRr;1208TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);12091210assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");12111212auto MIBLO = buildMI(MBB, MBBI, OpLo)1213.addReg(DstReg, RegState::Define)1214.addReg(DstReg, RegState::Kill)1215.addReg(SrcLoReg, getKillRegState(SrcIsKill))1216.addImm(Imm);12171218auto MIBHI =1219buildMI(MBB, MBBI, OpHi)1220.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1221.addReg(DstReg, RegState::Kill)1222.addReg(SrcHiReg, getKillRegState(SrcIsKill))1223.addImm(Imm);12241225MIBLO.setMemRefs(MI.memoperands());1226MIBHI.setMemRefs(MI.memoperands());12271228MI.eraseFromParent();1229return true;1230}12311232template <>1233bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {1234MachineInstr &MI = *MBBI;1235Register SrcLoReg, SrcHiReg;1236Register DstReg = MI.getOperand(0).getReg();1237Register SrcReg = MI.getOperand(2).getReg();1238unsigned Imm = MI.getOperand(3).getImm();1239bool DstIsDead = MI.getOperand(0).isDead();1240bool SrcIsKill = MI.getOperand(2).isKill();1241unsigned OpLo = AVR::STPtrPdRr;1242unsigned OpHi = AVR::STPtrPdRr;1243TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);12441245assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");12461247auto MIBHI = buildMI(MBB, MBBI, OpHi)1248.addReg(DstReg, RegState::Define)1249.addReg(DstReg, RegState::Kill)1250.addReg(SrcHiReg, getKillRegState(SrcIsKill))1251.addImm(Imm);12521253auto MIBLO =1254buildMI(MBB, MBBI, OpLo)1255.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1256.addReg(DstReg, RegState::Kill)1257.addReg(SrcLoReg, getKillRegState(SrcIsKill))1258.addImm(Imm);12591260MIBLO.setMemRefs(MI.memoperands());1261MIBHI.setMemRefs(MI.memoperands());12621263MI.eraseFromParent();1264return true;1265}12661267template <>1268bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {1269MachineInstr &MI = *MBBI;1270const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();12711272Register DstReg = MI.getOperand(0).getReg();1273bool DstIsKill = MI.getOperand(0).isKill();1274unsigned Imm = MI.getOperand(1).getImm();1275Register SrcReg = MI.getOperand(2).getReg();1276bool SrcIsKill = MI.getOperand(2).isKill();12771278// STD's maximum displacement is 63, so larger stores have to be split into a1279// set of operations.1280// For avrtiny chips, STD is not available at all so we always have to fall1281// back to manual pointer adjustments.1282if (Imm >= 63 || STI.hasTinyEncoding()) {1283// Add offset. The offset can be 0 when expanding this instruction from the1284// more specific STWPtrRr instruction.1285if (Imm != 0) {1286buildMI(MBB, MBBI, AVR::SUBIWRdK, DstReg)1287.addReg(DstReg, RegState::Kill)1288.addImm(0x10000 - Imm);1289}12901291// Do the store. This is a word store, that will be expanded further.1292buildMI(MBB, MBBI, AVR::STWPtrPiRr, DstReg)1293.addReg(DstReg, getKillRegState(DstIsKill))1294.addReg(SrcReg, getKillRegState(SrcIsKill))1295.addImm(0)1296.setMemRefs(MI.memoperands());12971298// If the pointer is used after the store instruction, subtract the new1299// offset (with 2 added after the postincrement instructions) so it is the1300// same as before.1301if (!DstIsKill) {1302buildMI(MBB, MBBI, AVR::SUBIWRdK, DstReg)1303.addReg(DstReg, RegState::Kill)1304.addImm(Imm + 2);1305}1306} else {1307Register SrcLoReg, SrcHiReg;1308TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);13091310if (STI.hasLowByteFirst()) {1311buildMI(MBB, MBBI, AVR::STDPtrQRr)1312.addReg(DstReg)1313.addImm(Imm)1314.addReg(SrcLoReg, getKillRegState(SrcIsKill))1315.setMemRefs(MI.memoperands());1316buildMI(MBB, MBBI, AVR::STDPtrQRr)1317.addReg(DstReg, getKillRegState(DstIsKill))1318.addImm(Imm + 1)1319.addReg(SrcHiReg, getKillRegState(SrcIsKill))1320.setMemRefs(MI.memoperands());1321} else {1322buildMI(MBB, MBBI, AVR::STDPtrQRr)1323.addReg(DstReg)1324.addImm(Imm + 1)1325.addReg(SrcHiReg, getKillRegState(SrcIsKill))1326.setMemRefs(MI.memoperands());1327buildMI(MBB, MBBI, AVR::STDPtrQRr)1328.addReg(DstReg, getKillRegState(DstIsKill))1329.addImm(Imm)1330.addReg(SrcLoReg, getKillRegState(SrcIsKill))1331.setMemRefs(MI.memoperands());1332}1333}13341335MI.eraseFromParent();1336return true;1337}13381339template <>1340bool AVRExpandPseudo::expand<AVR::STDSPQRr>(Block &MBB, BlockIt MBBI) {1341MachineInstr &MI = *MBBI;1342const MachineFunction &MF = *MBB.getParent();1343const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();13441345assert(MI.getOperand(0).getReg() == AVR::SP &&1346"SP is expected as base pointer");13471348assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&1349"unexpected STDSPQRr pseudo instruction");1350(void)STI;13511352MI.setDesc(TII->get(AVR::STDPtrQRr));1353MI.getOperand(0).setReg(AVR::R29R28);13541355return true;1356}13571358template <>1359bool AVRExpandPseudo::expand<AVR::STDWSPQRr>(Block &MBB, BlockIt MBBI) {1360MachineInstr &MI = *MBBI;1361const MachineFunction &MF = *MBB.getParent();1362const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();13631364assert(MI.getOperand(0).getReg() == AVR::SP &&1365"SP is expected as base pointer");13661367assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&1368"unexpected STDWSPQRr pseudo instruction");1369(void)STI;13701371MI.setDesc(TII->get(AVR::STDWPtrQRr));1372MI.getOperand(0).setReg(AVR::R29R28);13731374return true;1375}13761377template <>1378bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {1379MachineInstr &MI = *MBBI;1380Register DstLoReg, DstHiReg;1381unsigned Imm = MI.getOperand(1).getImm();1382Register DstReg = MI.getOperand(0).getReg();1383bool DstIsDead = MI.getOperand(0).isDead();1384unsigned OpLo = AVR::INRdA;1385unsigned OpHi = AVR::INRdA;1386TRI->splitReg(DstReg, DstLoReg, DstHiReg);13871388// Since we add 1 to the Imm value for the high byte below, and 63 is the1389// highest Imm value allowed for the instruction, 62 is the limit here.1390assert(Imm <= 62 && "Address is out of range");13911392auto MIBLO =1393buildMI(MBB, MBBI, OpLo)1394.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1395.addImm(Imm);13961397auto MIBHI =1398buildMI(MBB, MBBI, OpHi)1399.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1400.addImm(Imm + 1);14011402MIBLO.setMemRefs(MI.memoperands());1403MIBHI.setMemRefs(MI.memoperands());14041405MI.eraseFromParent();1406return true;1407}14081409template <>1410bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {1411const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();1412MachineInstr &MI = *MBBI;1413Register SrcLoReg, SrcHiReg;1414unsigned Imm = MI.getOperand(0).getImm();1415Register SrcReg = MI.getOperand(1).getReg();1416bool SrcIsKill = MI.getOperand(1).isKill();1417TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);14181419// Since we add 1 to the Imm value for the high byte below, and 63 is the1420// highest Imm value allowed for the instruction, 62 is the limit here.1421assert(Imm <= 62 && "Address is out of range");14221423// 16 bit I/O writes need the high byte first on normal AVR devices,1424// and in reverse order for the XMEGA/XMEGA3/XMEGAU families.1425auto MIBHI = buildMI(MBB, MBBI, AVR::OUTARr)1426.addImm(STI.hasLowByteFirst() ? Imm : Imm + 1)1427.addReg(STI.hasLowByteFirst() ? SrcLoReg : SrcHiReg,1428getKillRegState(SrcIsKill));1429auto MIBLO = buildMI(MBB, MBBI, AVR::OUTARr)1430.addImm(STI.hasLowByteFirst() ? Imm + 1 : Imm)1431.addReg(STI.hasLowByteFirst() ? SrcHiReg : SrcLoReg,1432getKillRegState(SrcIsKill));14331434MIBLO.setMemRefs(MI.memoperands());1435MIBHI.setMemRefs(MI.memoperands());14361437MI.eraseFromParent();1438return true;1439}14401441template <>1442bool AVRExpandPseudo::expand<AVR::PUSHWRr>(Block &MBB, BlockIt MBBI) {1443MachineInstr &MI = *MBBI;1444Register SrcLoReg, SrcHiReg;1445Register SrcReg = MI.getOperand(0).getReg();1446bool SrcIsKill = MI.getOperand(0).isKill();1447unsigned Flags = MI.getFlags();1448unsigned OpLo = AVR::PUSHRr;1449unsigned OpHi = AVR::PUSHRr;1450TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);14511452// Low part1453buildMI(MBB, MBBI, OpLo)1454.addReg(SrcLoReg, getKillRegState(SrcIsKill))1455.setMIFlags(Flags);14561457// High part1458buildMI(MBB, MBBI, OpHi)1459.addReg(SrcHiReg, getKillRegState(SrcIsKill))1460.setMIFlags(Flags);14611462MI.eraseFromParent();1463return true;1464}14651466template <>1467bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {1468MachineInstr &MI = *MBBI;1469Register DstLoReg, DstHiReg;1470Register DstReg = MI.getOperand(0).getReg();1471unsigned Flags = MI.getFlags();1472unsigned OpLo = AVR::POPRd;1473unsigned OpHi = AVR::POPRd;1474TRI->splitReg(DstReg, DstLoReg, DstHiReg);14751476buildMI(MBB, MBBI, OpHi, DstHiReg).setMIFlags(Flags); // High1477buildMI(MBB, MBBI, OpLo, DstLoReg).setMIFlags(Flags); // Low14781479MI.eraseFromParent();1480return true;1481}14821483bool AVRExpandPseudo::expandROLBRd(Block &MBB, BlockIt MBBI) {1484// In AVR, the rotate instructions behave quite unintuitively. They rotate1485// bits through the carry bit in SREG, effectively rotating over 9 bits,1486// instead of 8. This is useful when we are dealing with numbers over1487// multiple registers, but when we actually need to rotate stuff, we have1488// to explicitly add the carry bit.14891490MachineInstr &MI = *MBBI;1491unsigned OpShift, OpCarry;1492Register DstReg = MI.getOperand(0).getReg();1493Register ZeroReg = MI.getOperand(3).getReg();1494bool DstIsDead = MI.getOperand(0).isDead();1495bool DstIsKill = MI.getOperand(1).isKill();1496OpShift = AVR::ADDRdRr;1497OpCarry = AVR::ADCRdRr;14981499// add r16, r161500// adc r16, r115011502// Shift part1503buildMI(MBB, MBBI, OpShift)1504.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1505.addReg(DstReg, RegState::Kill)1506.addReg(DstReg, RegState::Kill);15071508// Add the carry bit1509auto MIB = buildMI(MBB, MBBI, OpCarry)1510.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))1511.addReg(DstReg, getKillRegState(DstIsKill))1512.addReg(ZeroReg);15131514MIB->getOperand(3).setIsDead(); // SREG is always dead1515MIB->getOperand(4).setIsKill(); // SREG is always implicitly killed15161517MI.eraseFromParent();1518return true;1519}15201521template <>1522bool AVRExpandPseudo::expand<AVR::ROLBRdR1>(Block &MBB, BlockIt MBBI) {1523return expandROLBRd(MBB, MBBI);1524}15251526template <>1527bool AVRExpandPseudo::expand<AVR::ROLBRdR17>(Block &MBB, BlockIt MBBI) {1528return expandROLBRd(MBB, MBBI);1529}15301531template <>1532bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) {1533// In AVR, the rotate instructions behave quite unintuitively. They rotate1534// bits through the carry bit in SREG, effectively rotating over 9 bits,1535// instead of 8. This is useful when we are dealing with numbers over1536// multiple registers, but when we actually need to rotate stuff, we have1537// to explicitly add the carry bit.15381539MachineInstr &MI = *MBBI;1540Register DstReg = MI.getOperand(0).getReg();15411542// bst r16, 01543// ror r161544// bld r16, 715451546// Move the lowest bit from DstReg into the T bit1547buildMI(MBB, MBBI, AVR::BST).addReg(DstReg).addImm(0);15481549// Rotate to the right1550buildMI(MBB, MBBI, AVR::RORRd, DstReg).addReg(DstReg);15511552// Move the T bit into the highest bit of DstReg.1553buildMI(MBB, MBBI, AVR::BLD, DstReg).addReg(DstReg).addImm(7);15541555MI.eraseFromParent();1556return true;1557}15581559template <>1560bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {1561MachineInstr &MI = *MBBI;1562Register DstLoReg, DstHiReg;1563Register DstReg = MI.getOperand(0).getReg();1564bool DstIsDead = MI.getOperand(0).isDead();1565bool DstIsKill = MI.getOperand(1).isKill();1566bool ImpIsDead = MI.getOperand(2).isDead();1567unsigned OpLo = AVR::ADDRdRr; // ADD Rd, Rd <==> LSL Rd1568unsigned OpHi = AVR::ADCRdRr; // ADC Rd, Rd <==> ROL Rd1569TRI->splitReg(DstReg, DstLoReg, DstHiReg);15701571// Low part1572buildMI(MBB, MBBI, OpLo)1573.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1574.addReg(DstLoReg, getKillRegState(DstIsKill))1575.addReg(DstLoReg, getKillRegState(DstIsKill));15761577auto MIBHI =1578buildMI(MBB, MBBI, OpHi)1579.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1580.addReg(DstHiReg, getKillRegState(DstIsKill))1581.addReg(DstHiReg, getKillRegState(DstIsKill));15821583if (ImpIsDead)1584MIBHI->getOperand(3).setIsDead();15851586// SREG is always implicitly killed1587MIBHI->getOperand(4).setIsKill();15881589MI.eraseFromParent();1590return true;1591}15921593template <>1594bool AVRExpandPseudo::expand<AVR::LSLWHiRd>(Block &MBB, BlockIt MBBI) {1595MachineInstr &MI = *MBBI;1596Register DstLoReg, DstHiReg;1597Register DstReg = MI.getOperand(0).getReg();1598bool DstIsDead = MI.getOperand(0).isDead();1599bool DstIsKill = MI.getOperand(1).isKill();1600bool ImpIsDead = MI.getOperand(2).isDead();1601TRI->splitReg(DstReg, DstLoReg, DstHiReg);16021603// add hireg, hireg <==> lsl hireg1604auto MILSL =1605buildMI(MBB, MBBI, AVR::ADDRdRr)1606.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1607.addReg(DstHiReg, getKillRegState(DstIsKill))1608.addReg(DstHiReg, getKillRegState(DstIsKill));16091610if (ImpIsDead)1611MILSL->getOperand(3).setIsDead();16121613MI.eraseFromParent();1614return true;1615}16161617bool AVRExpandPseudo::expandLSLW4Rd(Block &MBB, BlockIt MBBI) {1618MachineInstr &MI = *MBBI;1619Register DstLoReg, DstHiReg;1620Register DstReg = MI.getOperand(0).getReg();1621bool DstIsDead = MI.getOperand(0).isDead();1622bool DstIsKill = MI.getOperand(1).isKill();1623bool ImpIsDead = MI.getOperand(3).isDead();1624TRI->splitReg(DstReg, DstLoReg, DstHiReg);16251626// swap Rh1627// swap Rl1628buildMI(MBB, MBBI, AVR::SWAPRd)1629.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1630.addReg(DstHiReg, RegState::Kill);1631buildMI(MBB, MBBI, AVR::SWAPRd)1632.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1633.addReg(DstLoReg, RegState::Kill);16341635// andi Rh, 0xf01636auto MI0 =1637buildMI(MBB, MBBI, AVR::ANDIRdK)1638.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1639.addReg(DstHiReg, RegState::Kill)1640.addImm(0xf0);1641// SREG is implicitly dead.1642MI0->getOperand(3).setIsDead();16431644// eor Rh, Rl1645auto MI1 =1646buildMI(MBB, MBBI, AVR::EORRdRr)1647.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1648.addReg(DstHiReg, RegState::Kill)1649.addReg(DstLoReg);1650// SREG is implicitly dead.1651MI1->getOperand(3).setIsDead();16521653// andi Rl, 0xf01654auto MI2 =1655buildMI(MBB, MBBI, AVR::ANDIRdK)1656.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1657.addReg(DstLoReg, getKillRegState(DstIsKill))1658.addImm(0xf0);1659// SREG is implicitly dead.1660MI2->getOperand(3).setIsDead();16611662// eor Rh, Rl1663auto MI3 =1664buildMI(MBB, MBBI, AVR::EORRdRr)1665.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1666.addReg(DstHiReg, getKillRegState(DstIsKill))1667.addReg(DstLoReg);1668if (ImpIsDead)1669MI3->getOperand(3).setIsDead();16701671MI.eraseFromParent();1672return true;1673}16741675bool AVRExpandPseudo::expandLSLW8Rd(Block &MBB, BlockIt MBBI) {1676MachineInstr &MI = *MBBI;1677Register DstLoReg, DstHiReg;1678Register DstReg = MI.getOperand(0).getReg();1679bool DstIsDead = MI.getOperand(0).isDead();1680bool DstIsKill = MI.getOperand(1).isKill();1681bool ImpIsDead = MI.getOperand(3).isDead();1682TRI->splitReg(DstReg, DstLoReg, DstHiReg);16831684// mov Rh, Rl1685buildMI(MBB, MBBI, AVR::MOVRdRr)1686.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1687.addReg(DstLoReg);16881689// clr Rl1690auto MIBLO =1691buildMI(MBB, MBBI, AVR::EORRdRr)1692.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1693.addReg(DstLoReg, getKillRegState(DstIsKill))1694.addReg(DstLoReg, getKillRegState(DstIsKill));1695if (ImpIsDead)1696MIBLO->getOperand(3).setIsDead();16971698MI.eraseFromParent();1699return true;1700}17011702bool AVRExpandPseudo::expandLSLW12Rd(Block &MBB, BlockIt MBBI) {1703MachineInstr &MI = *MBBI;1704Register DstLoReg, DstHiReg;1705Register DstReg = MI.getOperand(0).getReg();1706bool DstIsDead = MI.getOperand(0).isDead();1707bool DstIsKill = MI.getOperand(1).isKill();1708bool ImpIsDead = MI.getOperand(3).isDead();1709TRI->splitReg(DstReg, DstLoReg, DstHiReg);17101711// mov Rh, Rl1712buildMI(MBB, MBBI, AVR::MOVRdRr)1713.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1714.addReg(DstLoReg);17151716// swap Rh1717buildMI(MBB, MBBI, AVR::SWAPRd)1718.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1719.addReg(DstHiReg, RegState::Kill);17201721// andi Rh, 0xf01722auto MI0 =1723buildMI(MBB, MBBI, AVR::ANDIRdK)1724.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1725.addReg(DstHiReg, getKillRegState(DstIsKill))1726.addImm(0xf0);1727// SREG is implicitly dead.1728MI0->getOperand(3).setIsDead();17291730// clr Rl1731auto MI1 =1732buildMI(MBB, MBBI, AVR::EORRdRr)1733.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1734.addReg(DstLoReg, getKillRegState(DstIsKill))1735.addReg(DstLoReg, getKillRegState(DstIsKill));1736if (ImpIsDead)1737MI1->getOperand(3).setIsDead();17381739MI.eraseFromParent();1740return true;1741}17421743template <>1744bool AVRExpandPseudo::expand<AVR::LSLWNRd>(Block &MBB, BlockIt MBBI) {1745MachineInstr &MI = *MBBI;1746unsigned Imm = MI.getOperand(2).getImm();1747switch (Imm) {1748case 4:1749return expandLSLW4Rd(MBB, MBBI);1750case 8:1751return expandLSLW8Rd(MBB, MBBI);1752case 12:1753return expandLSLW12Rd(MBB, MBBI);1754default:1755llvm_unreachable("unimplemented lslwn");1756return false;1757}1758}17591760template <>1761bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {1762MachineInstr &MI = *MBBI;1763Register DstLoReg, DstHiReg;1764Register DstReg = MI.getOperand(0).getReg();1765bool DstIsDead = MI.getOperand(0).isDead();1766bool DstIsKill = MI.getOperand(1).isKill();1767bool ImpIsDead = MI.getOperand(2).isDead();1768unsigned OpLo = AVR::RORRd;1769unsigned OpHi = AVR::LSRRd;1770TRI->splitReg(DstReg, DstLoReg, DstHiReg);17711772// High part1773buildMI(MBB, MBBI, OpHi)1774.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1775.addReg(DstHiReg, getKillRegState(DstIsKill));17761777auto MIBLO =1778buildMI(MBB, MBBI, OpLo)1779.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1780.addReg(DstLoReg, getKillRegState(DstIsKill));17811782if (ImpIsDead)1783MIBLO->getOperand(2).setIsDead();17841785// SREG is always implicitly killed1786MIBLO->getOperand(3).setIsKill();17871788MI.eraseFromParent();1789return true;1790}17911792template <>1793bool AVRExpandPseudo::expand<AVR::LSRWLoRd>(Block &MBB, BlockIt MBBI) {1794MachineInstr &MI = *MBBI;1795Register DstLoReg, DstHiReg;1796Register DstReg = MI.getOperand(0).getReg();1797bool DstIsDead = MI.getOperand(0).isDead();1798bool DstIsKill = MI.getOperand(1).isKill();1799bool ImpIsDead = MI.getOperand(2).isDead();1800TRI->splitReg(DstReg, DstLoReg, DstHiReg);18011802// lsr loreg1803auto MILSR =1804buildMI(MBB, MBBI, AVR::LSRRd)1805.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1806.addReg(DstLoReg, getKillRegState(DstIsKill));18071808if (ImpIsDead)1809MILSR->getOperand(2).setIsDead();18101811MI.eraseFromParent();1812return true;1813}18141815bool AVRExpandPseudo::expandLSRW4Rd(Block &MBB, BlockIt MBBI) {1816MachineInstr &MI = *MBBI;1817Register DstLoReg, DstHiReg;1818Register DstReg = MI.getOperand(0).getReg();1819bool DstIsDead = MI.getOperand(0).isDead();1820bool DstIsKill = MI.getOperand(1).isKill();1821bool ImpIsDead = MI.getOperand(3).isDead();1822TRI->splitReg(DstReg, DstLoReg, DstHiReg);18231824// swap Rh1825// swap Rl1826buildMI(MBB, MBBI, AVR::SWAPRd)1827.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1828.addReg(DstHiReg, RegState::Kill);1829buildMI(MBB, MBBI, AVR::SWAPRd)1830.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1831.addReg(DstLoReg, RegState::Kill);18321833// andi Rl, 0xf1834auto MI0 =1835buildMI(MBB, MBBI, AVR::ANDIRdK)1836.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1837.addReg(DstLoReg, RegState::Kill)1838.addImm(0xf);1839// SREG is implicitly dead.1840MI0->getOperand(3).setIsDead();18411842// eor Rl, Rh1843auto MI1 =1844buildMI(MBB, MBBI, AVR::EORRdRr)1845.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1846.addReg(DstLoReg, RegState::Kill)1847.addReg(DstHiReg);1848// SREG is implicitly dead.1849MI1->getOperand(3).setIsDead();18501851// andi Rh, 0xf1852auto MI2 =1853buildMI(MBB, MBBI, AVR::ANDIRdK)1854.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1855.addReg(DstHiReg, getKillRegState(DstIsKill))1856.addImm(0xf);1857// SREG is implicitly dead.1858MI2->getOperand(3).setIsDead();18591860// eor Rl, Rh1861auto MI3 =1862buildMI(MBB, MBBI, AVR::EORRdRr)1863.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1864.addReg(DstLoReg, getKillRegState(DstIsKill))1865.addReg(DstHiReg);1866if (ImpIsDead)1867MI3->getOperand(3).setIsDead();18681869MI.eraseFromParent();1870return true;1871}18721873bool AVRExpandPseudo::expandLSRW8Rd(Block &MBB, BlockIt MBBI) {1874MachineInstr &MI = *MBBI;1875Register DstLoReg, DstHiReg;1876Register DstReg = MI.getOperand(0).getReg();1877bool DstIsDead = MI.getOperand(0).isDead();1878bool DstIsKill = MI.getOperand(1).isKill();1879bool ImpIsDead = MI.getOperand(3).isDead();1880TRI->splitReg(DstReg, DstLoReg, DstHiReg);18811882// Move upper byte to lower byte.1883buildMI(MBB, MBBI, AVR::MOVRdRr)1884.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1885.addReg(DstHiReg);18861887// Clear upper byte.1888auto MIBHI =1889buildMI(MBB, MBBI, AVR::EORRdRr)1890.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1891.addReg(DstHiReg, getKillRegState(DstIsKill))1892.addReg(DstHiReg, getKillRegState(DstIsKill));1893if (ImpIsDead)1894MIBHI->getOperand(3).setIsDead();18951896MI.eraseFromParent();1897return true;1898}18991900bool AVRExpandPseudo::expandLSRW12Rd(Block &MBB, BlockIt MBBI) {1901MachineInstr &MI = *MBBI;1902Register DstLoReg, DstHiReg;1903Register DstReg = MI.getOperand(0).getReg();1904bool DstIsDead = MI.getOperand(0).isDead();1905bool DstIsKill = MI.getOperand(1).isKill();1906bool ImpIsDead = MI.getOperand(3).isDead();1907TRI->splitReg(DstReg, DstLoReg, DstHiReg);19081909// Move upper byte to lower byte.1910buildMI(MBB, MBBI, AVR::MOVRdRr)1911.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1912.addReg(DstHiReg);19131914// swap Rl1915buildMI(MBB, MBBI, AVR::SWAPRd)1916.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1917.addReg(DstLoReg, RegState::Kill);19181919// andi Rl, 0xf1920auto MI0 =1921buildMI(MBB, MBBI, AVR::ANDIRdK)1922.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1923.addReg(DstLoReg, getKillRegState(DstIsKill))1924.addImm(0xf);1925// SREG is implicitly dead.1926MI0->getOperand(3).setIsDead();19271928// Clear upper byte.1929auto MIBHI =1930buildMI(MBB, MBBI, AVR::EORRdRr)1931.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1932.addReg(DstHiReg, getKillRegState(DstIsKill))1933.addReg(DstHiReg, getKillRegState(DstIsKill));1934if (ImpIsDead)1935MIBHI->getOperand(3).setIsDead();19361937MI.eraseFromParent();1938return true;1939}19401941template <>1942bool AVRExpandPseudo::expand<AVR::LSRWNRd>(Block &MBB, BlockIt MBBI) {1943MachineInstr &MI = *MBBI;1944unsigned Imm = MI.getOperand(2).getImm();1945switch (Imm) {1946case 4:1947return expandLSRW4Rd(MBB, MBBI);1948case 8:1949return expandLSRW8Rd(MBB, MBBI);1950case 12:1951return expandLSRW12Rd(MBB, MBBI);1952default:1953llvm_unreachable("unimplemented lsrwn");1954return false;1955}1956}19571958template <>1959bool AVRExpandPseudo::expand<AVR::RORWRd>(Block &MBB, BlockIt MBBI) {1960llvm_unreachable("RORW unimplemented");1961return false;1962}19631964template <>1965bool AVRExpandPseudo::expand<AVR::ROLWRd>(Block &MBB, BlockIt MBBI) {1966llvm_unreachable("ROLW unimplemented");1967return false;1968}19691970template <>1971bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {1972MachineInstr &MI = *MBBI;1973Register DstLoReg, DstHiReg;1974Register DstReg = MI.getOperand(0).getReg();1975bool DstIsDead = MI.getOperand(0).isDead();1976bool DstIsKill = MI.getOperand(1).isKill();1977bool ImpIsDead = MI.getOperand(2).isDead();1978unsigned OpLo = AVR::RORRd;1979unsigned OpHi = AVR::ASRRd;1980TRI->splitReg(DstReg, DstLoReg, DstHiReg);19811982// High part1983buildMI(MBB, MBBI, OpHi)1984.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))1985.addReg(DstHiReg, getKillRegState(DstIsKill));19861987auto MIBLO =1988buildMI(MBB, MBBI, OpLo)1989.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))1990.addReg(DstLoReg, getKillRegState(DstIsKill));19911992if (ImpIsDead)1993MIBLO->getOperand(2).setIsDead();19941995// SREG is always implicitly killed1996MIBLO->getOperand(3).setIsKill();19971998MI.eraseFromParent();1999return true;2000}20012002template <>2003bool AVRExpandPseudo::expand<AVR::ASRWLoRd>(Block &MBB, BlockIt MBBI) {2004MachineInstr &MI = *MBBI;2005Register DstLoReg, DstHiReg;2006Register DstReg = MI.getOperand(0).getReg();2007bool DstIsDead = MI.getOperand(0).isDead();2008bool DstIsKill = MI.getOperand(1).isKill();2009bool ImpIsDead = MI.getOperand(2).isDead();2010TRI->splitReg(DstReg, DstLoReg, DstHiReg);20112012// asr loreg2013auto MIASR =2014buildMI(MBB, MBBI, AVR::ASRRd)2015.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2016.addReg(DstLoReg, getKillRegState(DstIsKill));20172018if (ImpIsDead)2019MIASR->getOperand(2).setIsDead();20202021MI.eraseFromParent();2022return true;2023}20242025bool AVRExpandPseudo::expandASRW7Rd(Block &MBB, BlockIt MBBI) {2026MachineInstr &MI = *MBBI;2027Register DstLoReg, DstHiReg;2028Register DstReg = MI.getOperand(0).getReg();2029bool DstIsDead = MI.getOperand(0).isDead();2030bool DstIsKill = MI.getOperand(1).isKill();2031bool ImpIsDead = MI.getOperand(3).isDead();2032TRI->splitReg(DstReg, DstLoReg, DstHiReg);20332034// lsl r242035// mov r24,r252036// rol r242037// sbc r25,r2520382039// lsl r24 <=> add r24, r242040buildMI(MBB, MBBI, AVR::ADDRdRr)2041.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2042.addReg(DstLoReg, RegState::Kill)2043.addReg(DstLoReg, RegState::Kill);20442045// mov r24, r252046buildMI(MBB, MBBI, AVR::MOVRdRr)2047.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2048.addReg(DstHiReg);20492050// rol r24 <=> adc r24, r242051buildMI(MBB, MBBI, AVR::ADCRdRr)2052.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2053.addReg(DstLoReg, getKillRegState(DstIsKill))2054.addReg(DstLoReg, getKillRegState(DstIsKill));20552056// sbc r25, r252057auto MISBC =2058buildMI(MBB, MBBI, AVR::SBCRdRr)2059.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2060.addReg(DstHiReg, getKillRegState(DstIsKill))2061.addReg(DstHiReg, getKillRegState(DstIsKill));20622063if (ImpIsDead)2064MISBC->getOperand(3).setIsDead();2065// SREG is always implicitly killed2066MISBC->getOperand(4).setIsKill();20672068MI.eraseFromParent();2069return true;2070}20712072bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {2073MachineInstr &MI = *MBBI;2074Register DstLoReg, DstHiReg;2075Register DstReg = MI.getOperand(0).getReg();2076bool DstIsDead = MI.getOperand(0).isDead();2077bool DstIsKill = MI.getOperand(1).isKill();2078bool ImpIsDead = MI.getOperand(3).isDead();2079TRI->splitReg(DstReg, DstLoReg, DstHiReg);20802081// Move upper byte to lower byte.2082buildMI(MBB, MBBI, AVR::MOVRdRr)2083.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2084.addReg(DstHiReg);20852086// Move the sign bit to the C flag.2087buildMI(MBB, MBBI, AVR::ADDRdRr)2088.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2089.addReg(DstHiReg, RegState::Kill)2090.addReg(DstHiReg, RegState::Kill);20912092// Set upper byte to 0 or -1.2093auto MIBHI =2094buildMI(MBB, MBBI, AVR::SBCRdRr)2095.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2096.addReg(DstHiReg, getKillRegState(DstIsKill))2097.addReg(DstHiReg, getKillRegState(DstIsKill));20982099if (ImpIsDead)2100MIBHI->getOperand(3).setIsDead();2101// SREG is always implicitly killed2102MIBHI->getOperand(4).setIsKill();21032104MI.eraseFromParent();2105return true;2106}2107bool AVRExpandPseudo::expandASRW14Rd(Block &MBB, BlockIt MBBI) {2108MachineInstr &MI = *MBBI;2109Register DstLoReg, DstHiReg;2110Register DstReg = MI.getOperand(0).getReg();2111bool DstIsDead = MI.getOperand(0).isDead();2112bool DstIsKill = MI.getOperand(1).isKill();2113bool ImpIsDead = MI.getOperand(3).isDead();2114TRI->splitReg(DstReg, DstLoReg, DstHiReg);21152116// lsl r252117// sbc r24, r242118// lsl r252119// mov r25, r242120// rol r2421212122// lsl r25 <=> add r25, r252123buildMI(MBB, MBBI, AVR::ADDRdRr)2124.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2125.addReg(DstHiReg, RegState::Kill)2126.addReg(DstHiReg, RegState::Kill);21272128// sbc r24, r242129buildMI(MBB, MBBI, AVR::SBCRdRr)2130.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2131.addReg(DstLoReg, RegState::Kill)2132.addReg(DstLoReg, RegState::Kill);21332134// lsl r25 <=> add r25, r252135buildMI(MBB, MBBI, AVR::ADDRdRr)2136.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2137.addReg(DstHiReg, RegState::Kill)2138.addReg(DstHiReg, RegState::Kill);21392140// mov r25, r242141buildMI(MBB, MBBI, AVR::MOVRdRr)2142.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2143.addReg(DstLoReg);21442145// rol r24 <=> adc r24, r242146auto MIROL =2147buildMI(MBB, MBBI, AVR::ADCRdRr)2148.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2149.addReg(DstLoReg, getKillRegState(DstIsKill))2150.addReg(DstLoReg, getKillRegState(DstIsKill));21512152if (ImpIsDead)2153MIROL->getOperand(3).setIsDead();2154// SREG is always implicitly killed2155MIROL->getOperand(4).setIsKill();21562157MI.eraseFromParent();2158return false;2159}21602161bool AVRExpandPseudo::expandASRW15Rd(Block &MBB, BlockIt MBBI) {2162MachineInstr &MI = *MBBI;2163Register DstLoReg, DstHiReg;2164Register DstReg = MI.getOperand(0).getReg();2165bool DstIsDead = MI.getOperand(0).isDead();2166bool ImpIsDead = MI.getOperand(3).isDead();2167TRI->splitReg(DstReg, DstLoReg, DstHiReg);21682169// lsl r252170// sbc r25, r252171// mov r24, r2521722173// lsl r25 <=> add r25, r252174buildMI(MBB, MBBI, AVR::ADDRdRr)2175.addReg(DstHiReg, RegState::Define)2176.addReg(DstHiReg, RegState::Kill)2177.addReg(DstHiReg, RegState::Kill);21782179// sbc r25, r252180auto MISBC =2181buildMI(MBB, MBBI, AVR::SBCRdRr)2182.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2183.addReg(DstHiReg, RegState::Kill)2184.addReg(DstHiReg, RegState::Kill);2185if (ImpIsDead)2186MISBC->getOperand(3).setIsDead();2187// SREG is always implicitly killed2188MISBC->getOperand(4).setIsKill();21892190// mov r24, r252191buildMI(MBB, MBBI, AVR::MOVRdRr)2192.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2193.addReg(DstHiReg);21942195MI.eraseFromParent();2196return true;2197}21982199template <>2200bool AVRExpandPseudo::expand<AVR::ASRWNRd>(Block &MBB, BlockIt MBBI) {2201MachineInstr &MI = *MBBI;2202unsigned Imm = MI.getOperand(2).getImm();2203switch (Imm) {2204case 7:2205return expandASRW7Rd(MBB, MBBI);2206case 8:2207return expandASRW8Rd(MBB, MBBI);2208case 14:2209return expandASRW14Rd(MBB, MBBI);2210case 15:2211return expandASRW15Rd(MBB, MBBI);2212default:2213llvm_unreachable("unimplemented asrwn");2214return false;2215}2216}22172218bool AVRExpandPseudo::expandLSLB7Rd(Block &MBB, BlockIt MBBI) {2219MachineInstr &MI = *MBBI;2220Register DstReg = MI.getOperand(0).getReg();2221bool DstIsDead = MI.getOperand(0).isDead();2222bool DstIsKill = MI.getOperand(1).isKill();2223bool ImpIsDead = MI.getOperand(3).isDead();22242225// ror r242226// clr r242227// ror r2422282229buildMI(MBB, MBBI, AVR::RORRd)2230.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2231.addReg(DstReg, RegState::Kill)2232->getOperand(3)2233.setIsUndef(true);22342235buildMI(MBB, MBBI, AVR::EORRdRr)2236.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2237.addReg(DstReg, RegState::Kill)2238.addReg(DstReg, RegState::Kill);22392240auto MIRRC =2241buildMI(MBB, MBBI, AVR::RORRd)2242.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2243.addReg(DstReg, getKillRegState(DstIsKill));22442245if (ImpIsDead)2246MIRRC->getOperand(2).setIsDead();22472248// SREG is always implicitly killed2249MIRRC->getOperand(3).setIsKill();22502251MI.eraseFromParent();2252return true;2253}22542255template <>2256bool AVRExpandPseudo::expand<AVR::LSLBNRd>(Block &MBB, BlockIt MBBI) {2257MachineInstr &MI = *MBBI;2258unsigned Imm = MI.getOperand(2).getImm();2259switch (Imm) {2260case 7:2261return expandLSLB7Rd(MBB, MBBI);2262default:2263llvm_unreachable("unimplemented lslbn");2264return false;2265}2266}22672268bool AVRExpandPseudo::expandLSRB7Rd(Block &MBB, BlockIt MBBI) {2269MachineInstr &MI = *MBBI;2270Register DstReg = MI.getOperand(0).getReg();2271bool DstIsDead = MI.getOperand(0).isDead();2272bool DstIsKill = MI.getOperand(1).isKill();2273bool ImpIsDead = MI.getOperand(3).isDead();22742275// rol r242276// clr r242277// rol r2422782279buildMI(MBB, MBBI, AVR::ADCRdRr)2280.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2281.addReg(DstReg, RegState::Kill)2282.addReg(DstReg, RegState::Kill)2283->getOperand(4)2284.setIsUndef(true);22852286buildMI(MBB, MBBI, AVR::EORRdRr)2287.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2288.addReg(DstReg, RegState::Kill)2289.addReg(DstReg, RegState::Kill);22902291auto MIRRC =2292buildMI(MBB, MBBI, AVR::ADCRdRr)2293.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2294.addReg(DstReg, getKillRegState(DstIsKill))2295.addReg(DstReg, getKillRegState(DstIsKill));22962297if (ImpIsDead)2298MIRRC->getOperand(3).setIsDead();22992300// SREG is always implicitly killed2301MIRRC->getOperand(4).setIsKill();23022303MI.eraseFromParent();2304return true;2305}23062307template <>2308bool AVRExpandPseudo::expand<AVR::LSRBNRd>(Block &MBB, BlockIt MBBI) {2309MachineInstr &MI = *MBBI;2310unsigned Imm = MI.getOperand(2).getImm();2311switch (Imm) {2312case 7:2313return expandLSRB7Rd(MBB, MBBI);2314default:2315llvm_unreachable("unimplemented lsrbn");2316return false;2317}2318}23192320bool AVRExpandPseudo::expandASRB6Rd(Block &MBB, BlockIt MBBI) {2321MachineInstr &MI = *MBBI;2322Register DstReg = MI.getOperand(0).getReg();2323bool DstIsDead = MI.getOperand(0).isDead();2324bool DstIsKill = MI.getOperand(1).isKill();23252326// bst r24, 62327// lsl r242328// sbc r24, r242329// bld r24, 023302331buildMI(MBB, MBBI, AVR::BST)2332.addReg(DstReg)2333.addImm(6)2334->getOperand(2)2335.setIsUndef(true);23362337buildMI(MBB, MBBI, AVR::ADDRdRr) // LSL Rd <==> ADD Rd, Rd2338.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2339.addReg(DstReg, RegState::Kill)2340.addReg(DstReg, RegState::Kill);23412342buildMI(MBB, MBBI, AVR::SBCRdRr)2343.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2344.addReg(DstReg, RegState::Kill)2345.addReg(DstReg, RegState::Kill);23462347buildMI(MBB, MBBI, AVR::BLD)2348.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2349.addReg(DstReg, getKillRegState(DstIsKill))2350.addImm(0)2351->getOperand(3)2352.setIsKill();23532354MI.eraseFromParent();2355return true;2356}23572358bool AVRExpandPseudo::expandASRB7Rd(Block &MBB, BlockIt MBBI) {2359MachineInstr &MI = *MBBI;2360Register DstReg = MI.getOperand(0).getReg();2361bool DstIsDead = MI.getOperand(0).isDead();2362bool DstIsKill = MI.getOperand(1).isKill();2363bool ImpIsDead = MI.getOperand(3).isDead();23642365// lsl r242366// sbc r24, r2423672368buildMI(MBB, MBBI, AVR::ADDRdRr)2369.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2370.addReg(DstReg, RegState::Kill)2371.addReg(DstReg, RegState::Kill);23722373auto MIRRC =2374buildMI(MBB, MBBI, AVR::SBCRdRr)2375.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))2376.addReg(DstReg, getKillRegState(DstIsKill))2377.addReg(DstReg, getKillRegState(DstIsKill));23782379if (ImpIsDead)2380MIRRC->getOperand(3).setIsDead();23812382// SREG is always implicitly killed2383MIRRC->getOperand(4).setIsKill();23842385MI.eraseFromParent();2386return true;2387}23882389template <>2390bool AVRExpandPseudo::expand<AVR::ASRBNRd>(Block &MBB, BlockIt MBBI) {2391MachineInstr &MI = *MBBI;2392unsigned Imm = MI.getOperand(2).getImm();2393switch (Imm) {2394case 6:2395return expandASRB6Rd(MBB, MBBI);2396case 7:2397return expandASRB7Rd(MBB, MBBI);2398default:2399llvm_unreachable("unimplemented asrbn");2400return false;2401}2402}24032404template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {2405MachineInstr &MI = *MBBI;2406Register DstLoReg, DstHiReg;2407// sext R17:R16, R172408// mov r16, r172409// lsl r172410// sbc r17, r172411// sext R17:R16, R132412// mov r16, r132413// mov r17, r132414// lsl r172415// sbc r17, r172416// sext R17:R16, R162417// mov r17, r162418// lsl r172419// sbc r17, r172420Register DstReg = MI.getOperand(0).getReg();2421Register SrcReg = MI.getOperand(1).getReg();2422bool DstIsDead = MI.getOperand(0).isDead();2423bool SrcIsKill = MI.getOperand(1).isKill();2424bool ImpIsDead = MI.getOperand(2).isDead();2425TRI->splitReg(DstReg, DstLoReg, DstHiReg);24262427if (SrcReg != DstLoReg)2428buildMI(MBB, MBBI, AVR::MOVRdRr)2429.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2430.addReg(SrcReg);24312432if (SrcReg != DstHiReg) {2433auto MOV = buildMI(MBB, MBBI, AVR::MOVRdRr)2434.addReg(DstHiReg, RegState::Define)2435.addReg(SrcReg);2436if (SrcReg != DstLoReg && SrcIsKill)2437MOV->getOperand(1).setIsKill();2438}24392440buildMI(MBB, MBBI, AVR::ADDRdRr) // LSL Rd <==> ADD Rd, Rr2441.addReg(DstHiReg, RegState::Define)2442.addReg(DstHiReg, RegState::Kill)2443.addReg(DstHiReg, RegState::Kill);24442445auto SBC =2446buildMI(MBB, MBBI, AVR::SBCRdRr)2447.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2448.addReg(DstHiReg, RegState::Kill)2449.addReg(DstHiReg, RegState::Kill);24502451if (ImpIsDead)2452SBC->getOperand(3).setIsDead();24532454// SREG is always implicitly killed2455SBC->getOperand(4).setIsKill();24562457MI.eraseFromParent();2458return true;2459}24602461template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {2462MachineInstr &MI = *MBBI;2463Register DstLoReg, DstHiReg;2464// zext R25:R24, R202465// mov R24, R202466// eor R25, R252467// zext R25:R24, R242468// eor R25, R252469// zext R25:R24, R252470// mov R24, R252471// eor R25, R252472Register DstReg = MI.getOperand(0).getReg();2473Register SrcReg = MI.getOperand(1).getReg();2474bool DstIsDead = MI.getOperand(0).isDead();2475bool SrcIsKill = MI.getOperand(1).isKill();2476bool ImpIsDead = MI.getOperand(2).isDead();2477TRI->splitReg(DstReg, DstLoReg, DstHiReg);24782479if (SrcReg != DstLoReg) {2480buildMI(MBB, MBBI, AVR::MOVRdRr)2481.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2482.addReg(SrcReg, getKillRegState(SrcIsKill));2483}24842485auto EOR =2486buildMI(MBB, MBBI, AVR::EORRdRr)2487.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2488.addReg(DstHiReg, RegState::Kill | RegState::Undef)2489.addReg(DstHiReg, RegState::Kill | RegState::Undef);24902491if (ImpIsDead)2492EOR->getOperand(3).setIsDead();24932494MI.eraseFromParent();2495return true;2496}24972498template <>2499bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {2500MachineInstr &MI = *MBBI;2501Register DstLoReg, DstHiReg;2502Register DstReg = MI.getOperand(0).getReg();2503bool DstIsDead = MI.getOperand(0).isDead();2504unsigned Flags = MI.getFlags();2505unsigned OpLo = AVR::INRdA;2506unsigned OpHi = AVR::INRdA;2507TRI->splitReg(DstReg, DstLoReg, DstHiReg);25082509// Low part2510buildMI(MBB, MBBI, OpLo)2511.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))2512.addImm(0x3d)2513.setMIFlags(Flags);25142515// High part2516buildMI(MBB, MBBI, OpHi)2517.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))2518.addImm(0x3e)2519.setMIFlags(Flags);25202521MI.eraseFromParent();2522return true;2523}25242525template <>2526bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {2527const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();2528MachineInstr &MI = *MBBI;2529Register SrcLoReg, SrcHiReg;2530Register SrcReg = MI.getOperand(1).getReg();2531bool SrcIsKill = MI.getOperand(1).isKill();2532unsigned Flags = MI.getFlags();2533TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);25342535buildMI(MBB, MBBI, AVR::INRdA)2536.addReg(STI.getTmpRegister(), RegState::Define)2537.addImm(STI.getIORegSREG())2538.setMIFlags(Flags);25392540buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);25412542buildMI(MBB, MBBI, AVR::OUTARr)2543.addImm(0x3e)2544.addReg(SrcHiReg, getKillRegState(SrcIsKill))2545.setMIFlags(Flags);25462547buildMI(MBB, MBBI, AVR::OUTARr)2548.addImm(STI.getIORegSREG())2549.addReg(STI.getTmpRegister(), RegState::Kill)2550.setMIFlags(Flags);25512552buildMI(MBB, MBBI, AVR::OUTARr)2553.addImm(0x3d)2554.addReg(SrcLoReg, getKillRegState(SrcIsKill))2555.setMIFlags(Flags);25562557MI.eraseFromParent();2558return true;2559}25602561bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {2562MachineInstr &MI = *MBBI;2563int Opcode = MBBI->getOpcode();25642565#define EXPAND(Op) \2566case Op: \2567return expand<Op>(MBB, MI)25682569switch (Opcode) {2570EXPAND(AVR::ADDWRdRr);2571EXPAND(AVR::ADCWRdRr);2572EXPAND(AVR::SUBWRdRr);2573EXPAND(AVR::SUBIWRdK);2574EXPAND(AVR::SBCWRdRr);2575EXPAND(AVR::SBCIWRdK);2576EXPAND(AVR::ANDWRdRr);2577EXPAND(AVR::ANDIWRdK);2578EXPAND(AVR::ORWRdRr);2579EXPAND(AVR::ORIWRdK);2580EXPAND(AVR::EORWRdRr);2581EXPAND(AVR::COMWRd);2582EXPAND(AVR::NEGWRd);2583EXPAND(AVR::CPWRdRr);2584EXPAND(AVR::CPCWRdRr);2585EXPAND(AVR::LDIWRdK);2586EXPAND(AVR::LDSWRdK);2587EXPAND(AVR::LDWRdPtr);2588EXPAND(AVR::LDWRdPtrPi);2589EXPAND(AVR::LDWRdPtrPd);2590case AVR::LDDWRdYQ: //: FIXME: remove this once PR13375 gets fixed2591EXPAND(AVR::LDDWRdPtrQ);2592EXPAND(AVR::LPMBRdZ);2593EXPAND(AVR::LPMWRdZ);2594EXPAND(AVR::LPMWRdZPi);2595EXPAND(AVR::ELPMBRdZ);2596EXPAND(AVR::ELPMWRdZ);2597EXPAND(AVR::ELPMBRdZPi);2598EXPAND(AVR::ELPMWRdZPi);2599EXPAND(AVR::AtomicLoad8);2600EXPAND(AVR::AtomicLoad16);2601EXPAND(AVR::AtomicStore8);2602EXPAND(AVR::AtomicStore16);2603EXPAND(AVR::AtomicFence);2604EXPAND(AVR::STSWKRr);2605EXPAND(AVR::STWPtrRr);2606EXPAND(AVR::STWPtrPiRr);2607EXPAND(AVR::STWPtrPdRr);2608EXPAND(AVR::STDWPtrQRr);2609EXPAND(AVR::STDSPQRr);2610EXPAND(AVR::STDWSPQRr);2611EXPAND(AVR::INWRdA);2612EXPAND(AVR::OUTWARr);2613EXPAND(AVR::PUSHWRr);2614EXPAND(AVR::POPWRd);2615EXPAND(AVR::ROLBRdR1);2616EXPAND(AVR::ROLBRdR17);2617EXPAND(AVR::RORBRd);2618EXPAND(AVR::LSLWRd);2619EXPAND(AVR::LSRWRd);2620EXPAND(AVR::RORWRd);2621EXPAND(AVR::ROLWRd);2622EXPAND(AVR::ASRWRd);2623EXPAND(AVR::LSLWHiRd);2624EXPAND(AVR::LSRWLoRd);2625EXPAND(AVR::ASRWLoRd);2626EXPAND(AVR::LSLWNRd);2627EXPAND(AVR::LSRWNRd);2628EXPAND(AVR::ASRWNRd);2629EXPAND(AVR::LSLBNRd);2630EXPAND(AVR::LSRBNRd);2631EXPAND(AVR::ASRBNRd);2632EXPAND(AVR::SEXT);2633EXPAND(AVR::ZEXT);2634EXPAND(AVR::SPREAD);2635EXPAND(AVR::SPWRITE);2636}2637#undef EXPAND2638return false;2639}26402641} // end of anonymous namespace26422643INITIALIZE_PASS(AVRExpandPseudo, "avr-expand-pseudo", AVR_EXPAND_PSEUDO_NAME,2644false, false)2645namespace llvm {26462647FunctionPass *createAVRExpandPseudoPass() { return new AVRExpandPseudo(); }26482649} // end of namespace llvm265026512652