[AVR] Use the register scavenger when expanding 'LDDW' instructions

Summary: This gets rid of the hardcoded 'r0' that was used previously.

Reviewers: asl

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D27567

llvm-svn: 289322
This commit is contained in:
Dylan McKay 2016-12-10 10:51:55 +00:00
parent 5d0233bea2
commit 5c90b8cb4f
2 changed files with 58 additions and 37 deletions

View File

@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm; using namespace llvm;
@ -110,6 +111,9 @@ bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
TRI = STI.getRegisterInfo(); TRI = STI.getRegisterInfo();
TII = STI.getInstrInfo(); TII = STI.getInstrInfo();
// We need to track liveness in order to use register scavenging.
MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness);
for (Block &MBB : MF) { for (Block &MBB : MF) {
bool ContinueExpanding = true; bool ContinueExpanding = true;
unsigned ExpandCount = 0; unsigned ExpandCount = 0;
@ -656,8 +660,7 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
assert(Imm <= 63 && "Offset is out of range"); assert(Imm <= 63 && "Offset is out of range");
unsigned TmpLoReg = DstLoReg; MachineInstr *MIBLO, *MIBHI;
unsigned TmpHiReg = DstHiReg;
// HACK: We shouldn't have instances of this instruction // HACK: We shouldn't have instances of this instruction
// where src==dest because the instruction itself is // where src==dest because the instruction itself is
@ -666,34 +669,51 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
// //
// In this case, just use a temporary register. // In this case, just use a temporary register.
if (DstReg == SrcReg) { if (DstReg == SrcReg) {
TmpLoReg = SCRATCH_REGISTER; RegScavenger RS;
TmpHiReg = SCRATCH_REGISTER;
}
auto MIBLO = buildMI(MBB, MBBI, OpLo) RS.enterBasicBlock(MBB);
.addReg(TmpLoReg, RegState::Define | getDeadRegState(DstIsDead)) RS.forward(MBBI);
.addReg(SrcReg)
.addImm(Imm);
// Push the low part of the temporary register to the stack. BitVector Candidates =
if (TmpLoReg != DstLoReg) TRI->getAllocatableSet
buildMI(MBB, MBBI, AVR::PUSHRr) (*MBB.getParent(), &AVR::GPR8RegClass);
.addReg(AVR::R0);
auto MIBHI = buildMI(MBB, MBBI, OpHi) // Exclude all the registers being used by the instruction.
.addReg(TmpHiReg, RegState::Define | getDeadRegState(DstIsDead)) for (MachineOperand &MO : MI.operands()) {
.addReg(SrcReg, getKillRegState(SrcIsKill)) if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() &&
.addImm(Imm + 1); !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
Candidates.reset(MO.getReg());
}
// If we need to use a temporary register. BitVector Available = RS.getRegsAvailable(&AVR::GPR8RegClass);
if (TmpHiReg != DstHiReg) { Available &= Candidates;
// Move the hi result from the tmp register to the destination.
buildMI(MBB, MBBI, AVR::MOVRdRr)
.addReg(DstHiReg).addReg(SCRATCH_REGISTER);
// Pop the lo result calculated previously and put it into unsigned TmpReg = Available.find_first();
// the lo destination. assert(TmpReg != -1 && "ran out of registers");
buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
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);
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()); MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());

View File

@ -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 # 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 # where we are expanding a 16-bit LDD instruction where the source and
@ -9,25 +9,26 @@
--- | --- |
target triple = "avr--" target triple = "avr--"
define void @test_lddw() { define void @test_lddw() {
entry: entry:
ret void ret void
} }
...
...
--- ---
name: test_lddw name: test_lddw
registers: stack:
- { id: 0, class: _ } - { id: 0, type: spill-slot, offset: -4, size: 1, alignment: 1, callee-saved-register: '%r28' }
body: | body: |
; CHECK-LABEL: bb.0.entry
bb.0.entry: bb.0.entry:
liveins: %r28, %r29
; CHECK-NEXT: early-clobber %r0 = LDDRdPtrQ %r29r28, 1 ; CHECK-LABEL: test_lddw
; 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
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
... ...