forked from OSchip/llvm-project
[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:
parent
5d0233bea2
commit
5c90b8cb4f
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
...
|
...
|
||||||
|
|
Loading…
Reference in New Issue