diff options
| author | Dylan McKay <dylanmckay34@gmail.com> | 2016-12-07 11:08:56 +0000 |
|---|---|---|
| committer | Dylan McKay <dylanmckay34@gmail.com> | 2016-12-07 11:08:56 +0000 |
| commit | 8cec7eb6dd762850964a6c63fd9187a72d9550c0 (patch) | |
| tree | d15a680bf62c23cb09477aad80e29578110a3de6 /llvm/lib | |
| parent | 840f8df67759b6893b6e58d2eb08124cb5822525 (diff) | |
| download | bcm5719-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.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 47 | ||||
| -rw-r--r-- | llvm/lib/Target/AVR/AVRInstrInfo.td | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/AVR/AVRTargetMachine.cpp | 3 |
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 { |

