Index: llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp =================================================================== --- llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -1328,39 +1328,27 @@ // to explicitly add the carry bit. MachineInstr &MI = *MBBI; - unsigned OpShiftOut, OpLoad, OpShiftIn, OpAdd; Register DstReg = MI.getOperand(0).getReg(); bool DstIsDead = MI.getOperand(0).isDead(); - OpShiftOut = AVR::LSRRd; - OpLoad = AVR::LDIRdK; - OpShiftIn = AVR::RORRd; - OpAdd = AVR::ORRdRr; // lsr r16 - // ldi r0, 0 - // ror r0 - // or r16, r17 + // ror r1 + // clr r1 // Shift out - buildMI(MBB, MBBI, OpShiftOut) + buildMI(MBB, MBBI, AVR::LSRRd) .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) .addReg(DstReg); - // Put 0 in temporary register - buildMI(MBB, MBBI, OpLoad) - .addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true)) - .addImm(0x00); - - // Shift in - buildMI(MBB, MBBI, OpShiftIn) - .addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true)) - .addReg(SCRATCH_REGISTER); + // Shift in, clobbering the zero register + buildMI(MBB, MBBI, AVR::RORRd) + .addReg(ZERO_REGISTER, RegState::Define | getDeadRegState(true)) + .addReg(ZERO_REGISTER); - // Add the results together using an or-instruction - auto MIB = buildMI(MBB, MBBI, OpAdd) - .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) - .addReg(DstReg) - .addReg(SCRATCH_REGISTER); + // Clear the zero register + auto MIB = buildMI(MBB, MBBI, AVR::EORRdRr, ZERO_REGISTER) + .addReg(ZERO_REGISTER) + .addReg(ZERO_REGISTER); // SREG is always implicitly killed MIB->getOperand(2).setIsKill(); Index: llvm/lib/Target/AVR/AVRInstrInfo.td =================================================================== --- llvm/lib/Target/AVR/AVRInstrInfo.td +++ llvm/lib/Target/AVR/AVRInstrInfo.td @@ -1750,20 +1750,21 @@ "asrw8\t$rd", [(set i16:$rd, (AVRasr8 i16:$src)), (implicit SREG)]>; + // 8-bit ROL is an alias of ADC Rd, Rd + + def ROLBRd : Pseudo<(outs GPR8:$rd), + (ins GPR8:$src), + "rolb\t$rd", + [(set i8:$rd, (AVRrol i8:$src)), (implicit SREG)]>; + + def RORBRd : Pseudo<(outs GPR8:$rd), + (ins GPR8:$src), + "rorb\t$rd", + [(set i8:$rd, (AVRror i8:$src)), (implicit SREG)]>; + // Bit rotate operations. let Uses = [SREG] in { - // 8-bit ROL is an alias of ADC Rd, Rd - - def ROLBRd : Pseudo<(outs GPR8:$rd), - (ins GPR8:$src), - "rolb\t$rd", - [(set i8:$rd, (AVRrol i8:$src)), (implicit SREG)]>; - - def RORBRd : Pseudo<(outs GPR8:$rd), - (ins GPR8:$src), - "rorb\t$rd", - [(set i8:$rd, (AVRror i8:$src)), (implicit SREG)]>; def ROLWRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), Index: llvm/test/CodeGen/AVR/rot.ll =================================================================== --- llvm/test/CodeGen/AVR/rot.ll +++ llvm/test/CodeGen/AVR/rot.ll @@ -38,9 +38,8 @@ ; CHECK-NEXT: .LBB1_1: ; CHECK-NEXT: lsr r24 - ; CHECK-NEXT: ldi r0, 0 - ; CHECK-NEXT: ror r0 - ; CHECK-NEXT: or r24, r0 + ; CHECK-NEXT: ror r1 + ; CHECK-NEXT: clr r1 ; CHECK-NEXT: dec r22 ; CHECK-NEXT: brpl .LBB1_1