diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -816,7 +816,6 @@ MachineInstr &MI = *MBBI; Register DstLoReg, DstHiReg; Register DstReg = MI.getOperand(0).getReg(); - Register TmpReg = 0; // 0 for no temporary register Register SrcReg = MI.getOperand(1).getReg(); bool SrcIsKill = MI.getOperand(1).isKill(); unsigned OpLo = IsExt ? AVR::ELPMRdZPi : AVR::LPMRdZPi; @@ -831,35 +830,16 @@ buildMI(MBB, MBBI, AVR::OUTARr).addImm(STI.getIORegRAMPZ()).addReg(Bank); } - // Use a temporary register if src and dst registers are the same. - if (DstReg == SrcReg) - TmpReg = scavengeGPR8(MI); - - Register CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg; - Register CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg; - // Load low byte. auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addReg(CurDstLoReg, RegState::Define) + .addReg(DstLoReg, RegState::Define) .addReg(SrcReg); - // Push low byte onto stack if necessary. - if (TmpReg) - buildMI(MBB, MBBI, AVR::PUSHRr).addReg(TmpReg); - // Load high byte. auto MIBHI = buildMI(MBB, MBBI, OpHi) - .addReg(CurDstHiReg, RegState::Define) + .addReg(DstHiReg, RegState::Define) .addReg(SrcReg, getKillRegState(SrcIsKill)); - if (TmpReg) { - // Move the high byte into the final destination. - buildMI(MBB, MBBI, AVR::MOVRdRr, DstHiReg).addReg(TmpReg); - - // Move the low byte from the scratch space into the final destination. - buildMI(MBB, MBBI, AVR::POPRd, DstLoReg); - } - MIBLO.setMemRefs(MI.memoperands()); MIBHI.setMemRefs(MI.memoperands()); diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -1662,34 +1662,26 @@ Requires<[HasLPM]>; def LPMRdZ : FLPMX<0, 0, - (outs GPR8 - : $dst), - (ins ZREG - : $z), + (outs LPM8:$dst), + (ins ZREG:$z), "lpm\t$dst, $z", []>, Requires<[HasLPMX]>; // Load program memory, while postincrementing the Z register. let Defs = [R31R30] in { def LPMRdZPi : FLPMX<0, 1, - (outs GPR8 - : $dst), - (ins ZREG - : $z), + (outs LPM8:$dst), + (ins ZREG:$z), "lpm\t$dst, $z+", []>, Requires<[HasLPMX]>; - def LPMWRdZ : Pseudo<(outs DREGS - : $dst), - (ins ZREG - : $z), + def LPMWRdZ : Pseudo<(outs DREGSLPM:$dst), + (ins ZREG:$z), "lpmw\t$dst, $z", []>, Requires<[HasLPMX]>; - def LPMWRdZPi : Pseudo<(outs DREGS - : $dst), - (ins ZREG - : $z), + def LPMWRdZPi : Pseudo<(outs DREGSLPM:$dst), + (ins ZREG:$z), "lpmw\t$dst, $z+", []>, Requires<[HasLPMX]>; } @@ -1702,31 +1694,31 @@ : F16<0b1001010111011000, (outs), (ins), "elpm", []>, Requires<[HasELPM]>; - def ELPMRdZ : FLPMX<1, 0, (outs GPR8:$dst), (ins ZREG:$z), + def ELPMRdZ : FLPMX<1, 0, (outs LPM8:$dst), (ins ZREG:$z), "elpm\t$dst, $z", []>, Requires<[HasELPMX]>; let Defs = [R31R30] in { - def ELPMRdZPi : FLPMX<1, 1, (outs GPR8:$dst), (ins ZREG:$z), + def ELPMRdZPi : FLPMX<1, 1, (outs LPM8:$dst), (ins ZREG:$z), "elpm\t$dst, $z+", []>, Requires<[HasELPMX]>; } // These pseudos are combination of the OUT and ELPM instructions. let Defs = [R31R30], hasSideEffects = 1 in { - def ELPMBRdZ : Pseudo<(outs GPR8:$dst), (ins ZREG:$z, LD8:$p), + def ELPMBRdZ : Pseudo<(outs LPM8:$dst), (ins ZREG:$z, LD8:$p), "elpmb\t$dst, $z, $p", []>, Requires<[HasELPMX]>; - def ELPMWRdZ : Pseudo<(outs DREGS:$dst), (ins ZREG:$z, LD8:$p), + def ELPMWRdZ : Pseudo<(outs DREGSLPM:$dst), (ins ZREG:$z, LD8:$p), "elpmw\t$dst, $z, $p", []>, Requires<[HasELPMX]>; - def ELPMBRdZPi : Pseudo<(outs GPR8:$dst), (ins ZREG:$z, LD8:$p), + def ELPMBRdZPi : Pseudo<(outs LPM8:$dst), (ins ZREG:$z, LD8:$p), "elpmb\t$dst, $z+, $p", []>, Requires<[HasELPMX]>; - def ELPMWRdZPi : Pseudo<(outs DREGS:$dst), (ins ZREG:$z, LD8:$p), + def ELPMWRdZPi : Pseudo<(outs DREGSLPM:$dst), (ins ZREG:$z, LD8:$p), "elpmw\t$dst, $z+, $p", []>, Requires<[HasELPMX]>; } diff --git a/llvm/lib/Target/AVR/AVRRegisterInfo.td b/llvm/lib/Target/AVR/AVRRegisterInfo.td --- a/llvm/lib/Target/AVR/AVRRegisterInfo.td +++ b/llvm/lib/Target/AVR/AVRRegisterInfo.td @@ -140,6 +140,10 @@ def LD8lo : RegisterClass<"AVR", [i8], 8, (add R23, R22, R21, R20, R19, R18, R17, R16)>; +// 8-bit register class for instructions that take a Z pointer operand, such as +// lpm. +def LPM8 : RegisterClass<"AVR", [i8], 8, (sub GPR8, R30, R31)>; + // Main 16-bit pair register class. def DREGS : RegisterClass<"AVR", [i16], 8, ( @@ -178,6 +182,10 @@ R29R28, R17R16, R15R14, R13R12, R11R10, R9R8, R7R6, R5R4, R3R2, R1R0)>; +// 16-bit pair register class for lpm, elpm and similar instructions that don't +// allow r30 or r31 as output operands. +def DREGSLPM : RegisterClass<"AVR", [i16], 8, (sub DREGS, R31R30)>; + // The 16-bit DREGS register class, excluding the Z pointer register. // // This is used by instructions which cause high pointer register