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 @@ -104,9 +104,6 @@ // Common implementation of LPMWRdZ and ELPMWRdZ. bool expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsExt); - - /// Scavenges a free GPR8 register for use. - Register scavengeGPR8(MachineInstr &MI); }; char AVRExpandPseudo::ID = 0; @@ -647,7 +644,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 = AVR::LDRdPtr; @@ -655,35 +651,19 @@ TRI->splitReg(DstReg, DstLoReg, DstHiReg); // 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; + assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same"); // 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)) .addImm(1); - 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()); @@ -762,7 +742,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(); unsigned Imm = MI.getOperand(2).getImm(); bool SrcIsKill = MI.getOperand(1).isKill(); @@ -775,36 +754,20 @@ assert(Imm <= 62 && "Offset is out of range"); // 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; + assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same"); // Load low byte. auto MIBLO = buildMI(MBB, MBBI, OpLo) - .addReg(CurDstLoReg, RegState::Define) + .addReg(DstLoReg, RegState::Define) .addReg(SrcReg) .addImm(Imm); - // 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)) .addImm(Imm + 1); - 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()); @@ -816,7 +779,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 +793,18 @@ 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; + assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same"); // 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()); @@ -980,31 +925,6 @@ }); } -Register AVRExpandPseudo::scavengeGPR8(MachineInstr &MI) { - MachineBasicBlock &MBB = *MI.getParent(); - RegScavenger RS; - - RS.enterBasicBlock(MBB); - RS.forward(MI); - - BitVector Candidates = - TRI->getAllocatableSet(*MBB.getParent(), &AVR::GPR8RegClass); - - // Exclude all the registers being used by the instruction. - for (MachineOperand &MO : MI.operands()) { - if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() && - !Register::isVirtualRegister(MO.getReg())) - Candidates.reset(MO.getReg()); - } - - BitVector Available = RS.getRegsAvailable(&AVR::GPR8RegClass); - Available &= Candidates; - - signed Reg = Available.find_first(); - assert(Reg != -1 && "ran out of registers"); - return Reg; -} - template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { return expandAtomicBinaryOp(AVR::LDRdPtr, MBB, MBBI); diff --git a/llvm/test/CodeGen/AVR/pseudo/ELPMWRdZ.mir b/llvm/test/CodeGen/AVR/pseudo/ELPMWRdZ.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/pseudo/ELPMWRdZ.mir @@ -0,0 +1,32 @@ +# RUN: llc -mcpu=atmega1284p -start-before=greedy %s -o - | FileCheck %s + +# This test checks the expansion of the 16-bit ELPM pseudo instruction and that +# the register allocator won't use R31R30 as an output register (which would +# lead to undefined behavior). + +--- | + target triple = "avr--" + define void @test_elpmwrdz() { + entry: + ret void + } +... + +--- +name: test_elpmwrdz +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $r31r30 + + ; CHECK-LABEL: test_elpmwrdz + ; CHECK: elpm r24, Z+ + ; CHECK-NEXT: elpm r25, Z + ; CHECK-NEXT: movw r30, r24 + + %1:zreg = COPY killed $r31r30 + %2:ld8 = LDIRdK 1 + %3:dregs = ELPMWRdZ %1, %2, implicit-def dead $r31r30 + $r31r30 = COPY %3 + RET implicit $r31r30 +... diff --git a/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr-same-src-dst.mir b/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr-same-src-dst.mir deleted file mode 100644 --- a/llvm/test/CodeGen/AVR/pseudo/LDWRdPtr-same-src-dst.mir +++ /dev/null @@ -1,30 +0,0 @@ -# RUN: llc -O0 %s -o - | FileCheck %s - -# This test checks the expansion of the 16-bit LDWRdPtr pseudo instruction. - ---- | - target triple = "avr--" - define void @test_ldwrdptr() { - entry: - ret void - } -... - ---- -name: test_ldwrdptr -tracksRegLiveness: true -body: | - bb.0.entry: - liveins: $r31r30 - - ; CHECK-LABEL: test_ldwrdptr - - ; CHECK: ld [[SCRATCH:r[0-9]+]], Z - ; CHECK-NEXT: push [[SCRATCH]] - ; CHECK-NEXT: ldd [[SCRATCH]], Z+1 - ; CHECK-NEXT: mov r31, [[SCRATCH]] - ; CHECK-NEXT: pop r30 - - early-clobber $r31r30 = LDWRdPtr undef $r31r30 -... -