summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorDylan McKay <dylanmckay34@gmail.com>2016-12-07 11:08:56 +0000
committerDylan McKay <dylanmckay34@gmail.com>2016-12-07 11:08:56 +0000
commit8cec7eb6dd762850964a6c63fd9187a72d9550c0 (patch)
treed15a680bf62c23cb09477aad80e29578110a3de6 /llvm/lib
parent840f8df67759b6893b6e58d2eb08124cb5822525 (diff)
downloadbcm5719-llvm-8cec7eb6dd762850964a6c63fd9187a72d9550c0.tar.gz
bcm5719-llvm-8cec7eb6dd762850964a6c63fd9187a72d9550c0.zip
[AVR] Allow loading from stack slots where src and dest registers are identical
Fixes PR 31256 llvm-svn: 288897
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AVR/AVR.h2
-rw-r--r--llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp47
-rw-r--r--llvm/lib/Target/AVR/AVRInstrInfo.td4
-rw-r--r--llvm/lib/Target/AVR/AVRTargetMachine.cpp3
4 files changed, 48 insertions, 8 deletions
diff --git a/llvm/lib/Target/AVR/AVR.h b/llvm/lib/Target/AVR/AVR.h
index 041c77cfcb9..0b4ba45262f 100644
--- a/llvm/lib/Target/AVR/AVR.h
+++ b/llvm/lib/Target/AVR/AVR.h
@@ -30,6 +30,8 @@ FunctionPass *createAVRFrameAnalyzerPass();
FunctionPass *createAVRDynAllocaSRPass();
FunctionPass *createAVRBranchSelectionPass();
+void initializeAVRExpandPseudoPass(PassRegistry&);
+
/// Contains the AVR backend.
namespace AVR {
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index a50e2fd2b98..3dc32576014 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -25,6 +25,8 @@
using namespace llvm;
+#define AVR_EXPAND_PSEUDO_NAME "AVR pseudo instruction expansion pass"
+
namespace {
/// Expands "placeholder" instructions marked as pseudo into
@@ -33,13 +35,13 @@ class AVRExpandPseudo : public MachineFunctionPass {
public:
static char ID;
- AVRExpandPseudo() : MachineFunctionPass(ID) {}
+ AVRExpandPseudo() : MachineFunctionPass(ID) {
+ initializeAVRExpandPseudoPass(*PassRegistry::getPassRegistry());
+ }
bool runOnMachineFunction(MachineFunction &MF) override;
- StringRef getPassName() const override {
- return "AVR pseudo instruction expansion pass";
- }
+ StringRef getPassName() const override { return AVR_EXPAND_PSEUDO_NAME; }
private:
typedef MachineBasicBlock Block;
@@ -653,18 +655,47 @@ bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
assert(Imm < 63 && "Offset is out of range");
- assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
+
+ unsigned TmpLoReg = DstLoReg;
+ unsigned TmpHiReg = DstHiReg;
+
+ // HACK: We shouldn't have instances of this instruction
+ // where src==dest because the instruction itself is
+ // marked earlyclobber. We do however get this instruction when
+ // loading from stack slots where the earlyclobber isn't useful.
+ //
+ // In this case, just use a temporary register.
+ if (DstReg == SrcReg) {
+ TmpLoReg = SCRATCH_REGISTER;
+ TmpHiReg = SCRATCH_REGISTER;
+ }
auto MIBLO = buildMI(MBB, MBBI, OpLo)
- .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(TmpLoReg, RegState::Define | getDeadRegState(DstIsDead))
.addReg(SrcReg)
.addImm(Imm);
+ // Push the low part of the temporary register to the stack.
+ if (TmpLoReg != DstLoReg)
+ buildMI(MBB, MBBI, AVR::PUSHRr)
+ .addReg(AVR::R0);
+
auto MIBHI = buildMI(MBB, MBBI, OpHi)
- .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(TmpHiReg, RegState::Define | getDeadRegState(DstIsDead))
.addReg(SrcReg, getKillRegState(SrcIsKill))
.addImm(Imm + 1);
+ // 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);
+
+ // Pop the lo result calculated previously and put it into
+ // the lo destination.
+ buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
+ }
+
MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
@@ -1424,6 +1455,8 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
} // end of anonymous namespace
+INITIALIZE_PASS(AVRExpandPseudo, "avr-expand-pseudo",
+ AVR_EXPAND_PSEUDO_NAME, false, false)
namespace llvm {
FunctionPass *createAVRExpandPseudoPass() { return new AVRExpandPseudo(); }
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index f30cbf0b2e2..56673020c0e 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -1207,6 +1207,7 @@ Constraints = "$ptrreg = $base_wb,@earlyclobber $reg,@earlyclobber $base_wb" in
let canFoldAsLoad = 1,
isReMaterializable = 1 in
{
+ let Constraints = "@earlyclobber $reg" in
def LDDRdPtrQ : FSTDLDD<0,
(outs GPR8:$reg),
(ins memri:$memri),
@@ -1227,7 +1228,8 @@ isReMaterializable = 1 in
Requires<[HasSRAM]>;
let mayLoad = 1,
- hasSideEffects = 0 in
+ hasSideEffects = 0,
+ Constraints = "@earlyclobber $dst" in
def LDDWRdYQ : Pseudo<(outs DREGS:$dst),
(ins memri:$memri),
"lddw\t$dst, $memri",
diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.cpp b/llvm/lib/Target/AVR/AVRTargetMachine.cpp
index a5381d83057..4189a242e9d 100644
--- a/llvm/lib/Target/AVR/AVRTargetMachine.cpp
+++ b/llvm/lib/Target/AVR/AVRTargetMachine.cpp
@@ -77,6 +77,9 @@ TargetPassConfig *AVRTargetMachine::createPassConfig(PassManagerBase &PM) {
extern "C" void LLVMInitializeAVRTarget() {
// Register the target.
RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
+
+ auto &PR = *PassRegistry::getPassRegistry();
+ initializeAVRExpandPseudoPass(PR);
}
const AVRSubtarget *AVRTargetMachine::getSubtargetImpl() const {
OpenPOWER on IntegriCloud