summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Shi <ben.shi@streamcomputing.com>2022-01-04 11:14:30 +0000
committerBen Shi <ben.shi@streamcomputing.com>2022-01-04 11:48:50 +0000
commit99e7bf46c9e34644a8c0033684798dcafc790200 (patch)
tree12b92da7af6bf6d628c71816d12130ad4780fe95
parent5c57e6aa5777bddf9ddaca5d927f1b47a1a9d381 (diff)
downloadllvm-99e7bf46c9e34644a8c0033684798dcafc790200.tar.gz
[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
-rw-r--r--llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp73
-rw-r--r--llvm/lib/Target/AVR/AVRISelLowering.cpp17
-rw-r--r--llvm/lib/Target/AVR/AVRISelLowering.h3
-rw-r--r--llvm/lib/Target/AVR/AVRInstrInfo.td12
-rw-r--r--llvm/test/CodeGen/AVR/shift.ll29
5 files changed, 124 insertions, 10 deletions
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 3c93da8e2039..7d101f6cfb14 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -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);
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index f3e74e843695..f7f560ff5db3 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -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;
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.h b/llvm/lib/Target/AVR/AVRISelLowering.h
index 3ae036b66bcb..223a47372ef7 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.h
+++ b/llvm/lib/Target/AVR/AVRISelLowering.h
@@ -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.
diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td
index c7f423292da0..c695cde04590 100644
--- a/llvm/lib/Target/AVR/AVRInstrInfo.td
+++ b/llvm/lib/Target/AVR/AVRInstrInfo.td
@@ -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
diff --git a/llvm/test/CodeGen/AVR/shift.ll b/llvm/test/CodeGen/AVR/shift.ll
index 90e1b25bd762..beba537cd104 100644
--- a/llvm/test/CodeGen/AVR/shift.ll
+++ b/llvm/test/CodeGen/AVR/shift.ll
@@ -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
+}