diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp index c19eac64aa300b..bb952e27dc9381 100644 --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; @@ -110,6 +111,9 @@ bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) { TRI = STI.getRegisterInfo(); TII = STI.getInstrInfo(); + // We need to track liveness in order to use register scavenging. + MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness); + for (Block &MBB : MF) { bool ContinueExpanding = true; unsigned ExpandCount = 0; @@ -656,8 +660,7 @@ bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { assert(Imm <= 63 && "Offset is out of range"); - unsigned TmpLoReg = DstLoReg; - unsigned TmpHiReg = DstHiReg; + MachineInstr *MIBLO, *MIBHI; // HACK: We shouldn't have instances of this instruction // where src==dest because the instruction itself is @@ -666,34 +669,51 @@ bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { // // In this case, just use a temporary register. if (DstReg == SrcReg) { - TmpLoReg = SCRATCH_REGISTER; - TmpHiReg = SCRATCH_REGISTER; - } + RegScavenger RS; - auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addReg(TmpLoReg, RegState::Define | getDeadRegState(DstIsDead)) - .addReg(SrcReg) - .addImm(Imm); + RS.enterBasicBlock(MBB); + RS.forward(MBBI); - // Push the low part of the temporary register to the stack. - if (TmpLoReg != DstLoReg) - buildMI(MBB, MBBI, AVR::PUSHRr) - .addReg(AVR::R0); + BitVector Candidates = + TRI->getAllocatableSet + (*MBB.getParent(), &AVR::GPR8RegClass); - auto MIBHI = buildMI(MBB, MBBI, OpHi) - .addReg(TmpHiReg, RegState::Define | getDeadRegState(DstIsDead)) - .addReg(SrcReg, getKillRegState(SrcIsKill)) - .addImm(Imm + 1); + // Exclude all the registers being used by the instruction. + for (MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() && + !TargetRegisterInfo::isVirtualRegister(MO.getReg())) + Candidates.reset(MO.getReg()); + } - // If we need to use a temporary register. - if (TmpHiReg != DstHiReg) { - // Move the hi result from the tmp register to the destination. - buildMI(MBB, MBBI, AVR::MOVRdRr) - .addReg(DstHiReg).addReg(SCRATCH_REGISTER); + BitVector Available = RS.getRegsAvailable(&AVR::GPR8RegClass); + Available &= Candidates; + + unsigned TmpReg = Available.find_first(); + assert(TmpReg != -1 && "ran out of registers"); + + MIBLO = buildMI(MBB, MBBI, OpLo) + .addReg(TmpReg, RegState::Define) + .addReg(SrcReg) + .addImm(Imm); + + buildMI(MBB, MBBI, AVR::MOVRdRr).addReg(DstLoReg).addReg(TmpReg); + + MIBHI = buildMI(MBB, MBBI, OpHi) + .addReg(TmpReg, RegState::Define) + .addReg(SrcReg, getKillRegState(SrcIsKill)) + .addImm(Imm + 1); + + buildMI(MBB, MBBI, AVR::MOVRdRr).addReg(DstHiReg).addReg(TmpReg); + } else { + MIBLO = buildMI(MBB, MBBI, OpLo) + .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(SrcReg) + .addImm(Imm); - // Pop the lo result calculated previously and put it into - // the lo destination. - buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg); + MIBHI = buildMI(MBB, MBBI, OpHi) + .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(SrcReg, getKillRegState(SrcIsKill)) + .addImm(Imm + 1); } MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); diff --git a/llvm/test/CodeGen/AVR/pseudo/expand-lddw-dst-src-same.mir b/llvm/test/CodeGen/AVR/pseudo/expand-lddw-dst-src-same.mir index 1fe7ce381483d5..cc164605167ba7 100644 --- a/llvm/test/CodeGen/AVR/pseudo/expand-lddw-dst-src-same.mir +++ b/llvm/test/CodeGen/AVR/pseudo/expand-lddw-dst-src-same.mir @@ -1,4 +1,4 @@ -# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - 2>&1 | FileCheck %s +# RUN: llc -O0 %s -o - 2>&1 | FileCheck %s # This test ensures that the pseudo expander can correctly handle the case # where we are expanding a 16-bit LDD instruction where the source and @@ -9,25 +9,26 @@ --- | target triple = "avr--" + define void @test_lddw() { entry: ret void } -... +... --- name: test_lddw -registers: - - { id: 0, class: _ } -body: | - ; CHECK-LABEL: bb.0.entry +stack: + - { id: 0, type: spill-slot, offset: -4, size: 1, alignment: 1, callee-saved-register: '%r28' } +body: | bb.0.entry: + liveins: %r28, %r29 - ; CHECK-NEXT: early-clobber %r0 = LDDRdPtrQ %r29r28, 1 - ; CHECK-NEXT: PUSHRr %r0, implicit-def %sp, implicit %sp - ; CHECK-NEXT: early-clobber %r0 = LDDRdPtrQ %r29r28, 2 - ; CHECK-NEXT: MOVRdRr %r29, %r0 - ; CHECK-NEXT: POPRd %r28, implicit-def %sp, implicit %sp + ; CHECK-LABEL: test_lddw - early-clobber %r29r28 = LDDWRdYQ %r29r28, 1 + ; CHECK: ldd [[TMPREG:r[0-9]+]], Y+0 + ; CHECK-NEXT: mov r28, [[TMPREG]] + ; CHECK-NEXT: ldd [[TMPREG]], Y+1 + ; CHECK-NEXT: mov r29, [[TMPREG]] + dead early-clobber %r29r28 = LDDWRdYQ killed %r29r28, 0 ...