[AVR] Fix rotate instructions

This patch fixes some issues with the RORB pseudo instruction.

  - A minor issue in which the instructions were said to use the SREG,
    which is not true.
  - An issue with the BLD instruction, which did not have an output operand.
  - A major issue in which invalid instructions were generated. The fix
    also reduce RORB from 4 to 3 instructions, so it's also a small
    optimization.

These issues were flagged by the machine verifier.

Differential Revision: https://reviews.llvm.org/D96957
This commit is contained in:
Ayke van Laethem 2021-02-18 16:12:11 +01:00
parent 6aa9e746eb
commit 41f905b211
No known key found for this signature in database
GPG Key ID: E97FF5335DFDFDED
3 changed files with 26 additions and 49 deletions

View File

@ -1345,42 +1345,20 @@ bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) {
// 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
// bst r16, 0
// ror r16
// bld r16, 7
// Shift out
buildMI(MBB, MBBI, OpShiftOut)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
.addReg(DstReg);
// Move the lowest bit from DstReg into the T bit
buildMI(MBB, MBBI, AVR::BST).addReg(DstReg).addImm(0);
// Put 0 in temporary register
buildMI(MBB, MBBI, OpLoad)
.addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true))
.addImm(0x00);
// Rotate to the right
buildMI(MBB, MBBI, AVR::RORRd, DstReg).addReg(DstReg);
// Shift in
buildMI(MBB, MBBI, OpShiftIn)
.addReg(SCRATCH_REGISTER, RegState::Define | getDeadRegState(true))
.addReg(SCRATCH_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);
// 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;

View File

@ -1735,20 +1735,19 @@ Defs = [SREG] in
"asrw\t$rd",
[(set i16:$rd, (AVRasr 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),
@ -1804,10 +1803,11 @@ def BST : FRdB<0b01,
"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",
[]>;

View File

@ -37,10 +37,9 @@ define i8 @ror8(i8 %val, i8 %amt) {
; 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