forked from OSchip/llvm-project
[AVR] Optimize int16 shift operation for shift amount greater than 8
Skip operation on the lower byte in int16 logical left shift when shift amount is greater than 8. Skip operation on the higher byte in int16 logical & arithmetic right shift when shift amount is greater than 8. Reviewed By: aykevl Differential Revision: https://reviews.llvm.org/D115594
This commit is contained in:
parent
5c57e6aa57
commit
99e7bf46c9
|
@ -1412,6 +1412,30 @@ bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool AVRExpandPseudo::expand<AVR::LSLWHiRd>(Block &MBB, BlockIt MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
Register DstLoReg, DstHiReg;
|
||||
Register DstReg = MI.getOperand(0).getReg();
|
||||
bool DstIsDead = MI.getOperand(0).isDead();
|
||||
bool DstIsKill = MI.getOperand(1).isKill();
|
||||
bool ImpIsDead = MI.getOperand(2).isDead();
|
||||
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
|
||||
|
||||
// add hireg, hireg <==> lsl hireg
|
||||
auto MILSL =
|
||||
buildMI(MBB, MBBI, AVR::ADDRdRr)
|
||||
.addReg(DstHiReg, RegState::Define, getDeadRegState(DstIsDead))
|
||||
.addReg(DstHiReg, getKillRegState(DstIsKill))
|
||||
.addReg(DstHiReg, getKillRegState(DstIsKill));
|
||||
|
||||
if (ImpIsDead)
|
||||
MILSL->getOperand(3).setIsDead();
|
||||
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AVRExpandPseudo::expandLSLW4Rd(Block &MBB, BlockIt MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
Register DstLoReg, DstHiReg;
|
||||
|
@ -1587,6 +1611,29 @@ bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool AVRExpandPseudo::expand<AVR::LSRWLoRd>(Block &MBB, BlockIt MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
Register DstLoReg, DstHiReg;
|
||||
Register DstReg = MI.getOperand(0).getReg();
|
||||
bool DstIsDead = MI.getOperand(0).isDead();
|
||||
bool DstIsKill = MI.getOperand(1).isKill();
|
||||
bool ImpIsDead = MI.getOperand(2).isDead();
|
||||
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
|
||||
|
||||
// lsr loreg
|
||||
auto MILSR =
|
||||
buildMI(MBB, MBBI, AVR::LSRRd)
|
||||
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
|
||||
.addReg(DstLoReg, getKillRegState(DstIsKill));
|
||||
|
||||
if (ImpIsDead)
|
||||
MILSR->getOperand(2).setIsDead();
|
||||
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AVRExpandPseudo::expandLSRW4Rd(Block &MBB, BlockIt MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
Register DstLoReg, DstHiReg;
|
||||
|
@ -1774,6 +1821,29 @@ bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool AVRExpandPseudo::expand<AVR::ASRWLoRd>(Block &MBB, BlockIt MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
Register DstLoReg, DstHiReg;
|
||||
Register DstReg = MI.getOperand(0).getReg();
|
||||
bool DstIsDead = MI.getOperand(0).isDead();
|
||||
bool DstIsKill = MI.getOperand(1).isKill();
|
||||
bool ImpIsDead = MI.getOperand(2).isDead();
|
||||
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
|
||||
|
||||
// asr loreg
|
||||
auto MIASR =
|
||||
buildMI(MBB, MBBI, AVR::ASRRd)
|
||||
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
|
||||
.addReg(DstLoReg, getKillRegState(DstIsKill));
|
||||
|
||||
if (ImpIsDead)
|
||||
MIASR->getOperand(2).setIsDead();
|
||||
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
Register DstLoReg, DstHiReg;
|
||||
|
@ -2230,6 +2300,9 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
|
|||
EXPAND(AVR::RORWRd);
|
||||
EXPAND(AVR::ROLWRd);
|
||||
EXPAND(AVR::ASRWRd);
|
||||
EXPAND(AVR::LSLWHiRd);
|
||||
EXPAND(AVR::LSRWLoRd);
|
||||
EXPAND(AVR::ASRWLoRd);
|
||||
EXPAND(AVR::LSLWNRd);
|
||||
EXPAND(AVR::LSRWNRd);
|
||||
EXPAND(AVR::ASRWNRd);
|
||||
|
|
|
@ -392,16 +392,22 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
|
|||
Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
|
||||
DAG.getConstant(8, dl, VT));
|
||||
ShiftAmount -= 8;
|
||||
// Only operate on the higher byte for remaining shift bits.
|
||||
Opc8 = AVRISD::LSLHI;
|
||||
break;
|
||||
case ISD::SRL:
|
||||
Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
|
||||
DAG.getConstant(8, dl, VT));
|
||||
ShiftAmount -= 8;
|
||||
// Only operate on the lower byte for remaining shift bits.
|
||||
Opc8 = AVRISD::LSRLO;
|
||||
break;
|
||||
case ISD::SRA:
|
||||
Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
|
||||
DAG.getConstant(8, dl, VT));
|
||||
ShiftAmount -= 8;
|
||||
// Only operate on the lower byte for remaining shift bits.
|
||||
Opc8 = AVRISD::ASRLO;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -412,11 +418,22 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
|
|||
Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
|
||||
DAG.getConstant(12, dl, VT));
|
||||
ShiftAmount -= 12;
|
||||
// Only operate on the higher byte for remaining shift bits.
|
||||
Opc8 = AVRISD::LSLHI;
|
||||
break;
|
||||
case ISD::SRL:
|
||||
Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
|
||||
DAG.getConstant(12, dl, VT));
|
||||
ShiftAmount -= 12;
|
||||
// Only operate on the lower byte for remaining shift bits.
|
||||
Opc8 = AVRISD::LSRLO;
|
||||
break;
|
||||
case ISD::SRA:
|
||||
Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
|
||||
DAG.getConstant(8, dl, VT));
|
||||
ShiftAmount -= 8;
|
||||
// Only operate on the lower byte for remaining shift bits.
|
||||
Opc8 = AVRISD::ASRLO;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -38,12 +38,15 @@ enum NodeType {
|
|||
LSL, ///< Logical shift left.
|
||||
LSLBN, ///< Byte logical shift left N bits.
|
||||
LSLWN, ///< Word logical shift left N bits.
|
||||
LSLHI, ///< Higher 8-bit of word logical shift left.
|
||||
LSR, ///< Logical shift right.
|
||||
LSRBN, ///< Byte logical shift right N bits.
|
||||
LSRWN, ///< Word logical shift right N bits.
|
||||
LSRLO, ///< Lower 8-bit of word logical shift right.
|
||||
ASR, ///< Arithmetic shift right.
|
||||
ASRBN, ///< Byte arithmetic shift right N bits.
|
||||
ASRWN, ///< Word arithmetic shift right N bits.
|
||||
ASRLO, ///< Lower 8-bit of word arithmetic shift right.
|
||||
ROR, ///< Bit rotate right.
|
||||
ROL, ///< Bit rotate left.
|
||||
LSLLOOP, ///< A loop of single logical shift left instructions.
|
||||
|
|
|
@ -60,6 +60,9 @@ def AVRlsr : SDNode<"AVRISD::LSR", SDTIntUnaryOp>;
|
|||
def AVRrol : SDNode<"AVRISD::ROL", SDTIntUnaryOp>;
|
||||
def AVRror : SDNode<"AVRISD::ROR", SDTIntUnaryOp>;
|
||||
def AVRasr : SDNode<"AVRISD::ASR", SDTIntUnaryOp>;
|
||||
def AVRlslhi : SDNode<"AVRISD::LSLHI", SDTIntUnaryOp>;
|
||||
def AVRlsrlo : SDNode<"AVRISD::LSRLO", SDTIntUnaryOp>;
|
||||
def AVRasrlo : SDNode<"AVRISD::ASRLO", SDTIntUnaryOp>;
|
||||
def AVRlslbn : SDNode<"AVRISD::LSLBN", SDTIntBinOp>;
|
||||
def AVRlsrbn : SDNode<"AVRISD::LSRBN", SDTIntBinOp>;
|
||||
def AVRasrbn : SDNode<"AVRISD::ASRBN", SDTIntBinOp>;
|
||||
|
@ -1848,6 +1851,9 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
|
|||
: $src)),
|
||||
(implicit SREG)]>;
|
||||
|
||||
def LSLWHiRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lslwhi\t$rd",
|
||||
[(set i16:$rd, (AVRlslhi i16:$src)), (implicit SREG)]>;
|
||||
|
||||
def LSLWNRd : Pseudo<(outs DLDREGS
|
||||
: $rd),
|
||||
(ins DREGS
|
||||
|
@ -1895,6 +1901,9 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
|
|||
: $src)),
|
||||
(implicit SREG)]>;
|
||||
|
||||
def LSRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lsrwlo\t$rd",
|
||||
[(set i16:$rd, (AVRlsrlo i16:$src)), (implicit SREG)]>;
|
||||
|
||||
def LSRWNRd : Pseudo<(outs DLDREGS
|
||||
: $rd),
|
||||
(ins DREGS
|
||||
|
@ -1968,6 +1977,9 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
|
|||
: $src)),
|
||||
(implicit SREG)]>;
|
||||
|
||||
def ASRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "asrwlo\t$rd",
|
||||
[(set i16:$rd, (AVRasrlo i16:$src)), (implicit SREG)]>;
|
||||
|
||||
def ROLBRd : Pseudo<(outs GPR8
|
||||
: $rd),
|
||||
(ins GPR8
|
||||
|
|
|
@ -227,8 +227,7 @@ define i16 @lsl_i16_9(i16 %a) {
|
|||
; CHECK-LABEL: lsl_i16_9
|
||||
; CHECK: mov r25, r24
|
||||
; CHECK-NEXT: clr r24
|
||||
; CHECK-NEXT: lsl r24
|
||||
; CHECK-NEXT: rol r25
|
||||
; CHECK-NEXT: lsl r25
|
||||
; CHECK-NEXT: ret
|
||||
%result = shl i16 %a, 9
|
||||
ret i16 %result
|
||||
|
@ -240,8 +239,7 @@ define i16 @lsl_i16_13(i16 %a) {
|
|||
; CHECK-NEXT: swap r25
|
||||
; CHECK-NEXT: andi r25, 240
|
||||
; CHECK-NEXT: clr r24
|
||||
; CHECK-NEXT: lsl r24
|
||||
; CHECK-NEXT: rol r25
|
||||
; CHECK-NEXT: lsl r25
|
||||
; CHECK-NEXT: ret
|
||||
%result = shl i16 %a, 13
|
||||
ret i16 %result
|
||||
|
@ -285,8 +283,7 @@ define i16 @lsr_i16_9(i16 %a) {
|
|||
; CHECK-LABEL: lsr_i16_9
|
||||
; CHECK: mov r24, r25
|
||||
; CHECK-NEXT: clr r25
|
||||
; CHECK-NEXT: lsr r25
|
||||
; CHECK-NEXT: ror r24
|
||||
; CHECK-NEXT: lsr r24
|
||||
; CHECK-NEXT: ret
|
||||
%result = lshr i16 %a, 9
|
||||
ret i16 %result
|
||||
|
@ -298,8 +295,7 @@ define i16 @lsr_i16_13(i16 %a) {
|
|||
; CHECK-NEXT: swap r24
|
||||
; CHECK-NEXT: andi r24, 15
|
||||
; CHECK-NEXT: clr r25
|
||||
; CHECK-NEXT: lsr r25
|
||||
; CHECK-NEXT: ror r24
|
||||
; CHECK-NEXT: lsr r24
|
||||
; CHECK-NEXT: ret
|
||||
%result = lshr i16 %a, 13
|
||||
ret i16 %result
|
||||
|
@ -310,9 +306,22 @@ define i16 @asr_i16_9(i16 %a) {
|
|||
; CHECK: mov r24, r25
|
||||
; CHECK-NEXT: lsl r25
|
||||
; CHECK-NEXT: sbc r25, r25
|
||||
; CHECK-NEXT: asr r25
|
||||
; CHECK-NEXT: ror r24
|
||||
; CHECK-NEXT: asr r24
|
||||
; CHECK-NEXT: ret
|
||||
%result = ashr i16 %a, 9
|
||||
ret i16 %result
|
||||
}
|
||||
|
||||
define i16 @asr_i16_12(i16 %a) {
|
||||
; CHECK-LABEL: asr_i16_12
|
||||
; CHECK: mov r24, r25
|
||||
; CHECK-NEXT: lsl r25
|
||||
; CHECK-NEXT: sbc r25, r25
|
||||
; CHECK-NEXT: asr r24
|
||||
; CHECK-NEXT: asr r24
|
||||
; CHECK-NEXT: asr r24
|
||||
; CHECK-NEXT: asr r24
|
||||
; CHECK-NEXT: ret
|
||||
%result = ashr i16 %a, 12
|
||||
ret i16 %result
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue