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 @@ -1332,42 +1332,20 @@ // 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 - - // Shift out - buildMI(MBB, MBBI, OpShiftOut) - .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); + // bst r16, 0 + // ror r16 + // bld r16, 7 - // Shift in - buildMI(MBB, MBBI, OpShiftIn) - .addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true)) - .addReg(SCRATCH_REGISTER); + // Move the lowest bit from DstReg into the T bit + buildMI(MBB, MBBI, AVR::BST).addReg(DstReg).addImm(0); - // 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); + // Rotate to the right + buildMI(MBB, MBBI, AVR::RORRd, DstReg).addReg(DstReg); - // SREG is always implicitly killed - MIB->getOperand(2).setIsKill(); + // Move the T bit into the highest bit of DstReg. + buildMI(MBB, MBBI, AVR::BLD, DstReg).addReg(DstReg).addImm(7); MI.eraseFromParent(); return true; 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 @@ -1751,20 +1751,19 @@ "asrw8\t$rd", [(set i16:$rd, (AVRasr8 i16:$src)), (implicit SREG)]>; + 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), @@ -1820,10 +1819,11 @@ "bst\t$rd, $b", []>; -let Uses = [SREG] in +let Constraints = "$src = $rd", +Uses = [SREG] in def BLD : FRdB<0b00, - (outs), - (ins GPR8:$rd, i8imm:$b), + (outs GPR8:$rd), + (ins GPR8:$src, i8imm:$b), "bld\t$rd, $b", []>; diff --git a/llvm/test/CodeGen/AVR/rot.ll b/llvm/test/CodeGen/AVR/rot.ll --- a/llvm/test/CodeGen/AVR/rot.ll +++ b/llvm/test/CodeGen/AVR/rot.ll @@ -37,10 +37,9 @@ ; CHECK-NEXT: brmi .LBB1_2 ; CHECK-NEXT: .LBB1_1: - ; CHECK-NEXT: lsr r24 - ; CHECK-NEXT: ldi r0, 0 - ; CHECK-NEXT: ror r0 - ; CHECK-NEXT: or r24, r0 + ; CHECK-NEXT: bst r24, 0 + ; CHECK-NEXT: ror r24 + ; CHECK-NEXT: bld r24, 7 ; CHECK-NEXT: dec r22 ; CHECK-NEXT: brpl .LBB1_1