Skip to content

Commit 99e7bf4

Browse files
committed
[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
1 parent 5c57e6a commit 99e7bf4

File tree

5 files changed

+124
-10
lines changed

5 files changed

+124
-10
lines changed

llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,30 @@ bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
14121412
return true;
14131413
}
14141414

1415+
template <>
1416+
bool AVRExpandPseudo::expand<AVR::LSLWHiRd>(Block &MBB, BlockIt MBBI) {
1417+
MachineInstr &MI = *MBBI;
1418+
Register DstLoReg, DstHiReg;
1419+
Register DstReg = MI.getOperand(0).getReg();
1420+
bool DstIsDead = MI.getOperand(0).isDead();
1421+
bool DstIsKill = MI.getOperand(1).isKill();
1422+
bool ImpIsDead = MI.getOperand(2).isDead();
1423+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1424+
1425+
// add hireg, hireg <==> lsl hireg
1426+
auto MILSL =
1427+
buildMI(MBB, MBBI, AVR::ADDRdRr)
1428+
.addReg(DstHiReg, RegState::Define, getDeadRegState(DstIsDead))
1429+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1430+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1431+
1432+
if (ImpIsDead)
1433+
MILSL->getOperand(3).setIsDead();
1434+
1435+
MI.eraseFromParent();
1436+
return true;
1437+
}
1438+
14151439
bool AVRExpandPseudo::expandLSLW4Rd(Block &MBB, BlockIt MBBI) {
14161440
MachineInstr &MI = *MBBI;
14171441
Register DstLoReg, DstHiReg;
@@ -1587,6 +1611,29 @@ bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
15871611
return true;
15881612
}
15891613

1614+
template <>
1615+
bool AVRExpandPseudo::expand<AVR::LSRWLoRd>(Block &MBB, BlockIt MBBI) {
1616+
MachineInstr &MI = *MBBI;
1617+
Register DstLoReg, DstHiReg;
1618+
Register DstReg = MI.getOperand(0).getReg();
1619+
bool DstIsDead = MI.getOperand(0).isDead();
1620+
bool DstIsKill = MI.getOperand(1).isKill();
1621+
bool ImpIsDead = MI.getOperand(2).isDead();
1622+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1623+
1624+
// lsr loreg
1625+
auto MILSR =
1626+
buildMI(MBB, MBBI, AVR::LSRRd)
1627+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1628+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1629+
1630+
if (ImpIsDead)
1631+
MILSR->getOperand(2).setIsDead();
1632+
1633+
MI.eraseFromParent();
1634+
return true;
1635+
}
1636+
15901637
bool AVRExpandPseudo::expandLSRW4Rd(Block &MBB, BlockIt MBBI) {
15911638
MachineInstr &MI = *MBBI;
15921639
Register DstLoReg, DstHiReg;
@@ -1774,6 +1821,29 @@ bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
17741821
return true;
17751822
}
17761823

1824+
template <>
1825+
bool AVRExpandPseudo::expand<AVR::ASRWLoRd>(Block &MBB, BlockIt MBBI) {
1826+
MachineInstr &MI = *MBBI;
1827+
Register DstLoReg, DstHiReg;
1828+
Register DstReg = MI.getOperand(0).getReg();
1829+
bool DstIsDead = MI.getOperand(0).isDead();
1830+
bool DstIsKill = MI.getOperand(1).isKill();
1831+
bool ImpIsDead = MI.getOperand(2).isDead();
1832+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1833+
1834+
// asr loreg
1835+
auto MIASR =
1836+
buildMI(MBB, MBBI, AVR::ASRRd)
1837+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1838+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1839+
1840+
if (ImpIsDead)
1841+
MIASR->getOperand(2).setIsDead();
1842+
1843+
MI.eraseFromParent();
1844+
return true;
1845+
}
1846+
17771847
bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {
17781848
MachineInstr &MI = *MBBI;
17791849
Register DstLoReg, DstHiReg;
@@ -2230,6 +2300,9 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
22302300
EXPAND(AVR::RORWRd);
22312301
EXPAND(AVR::ROLWRd);
22322302
EXPAND(AVR::ASRWRd);
2303+
EXPAND(AVR::LSLWHiRd);
2304+
EXPAND(AVR::LSRWLoRd);
2305+
EXPAND(AVR::ASRWLoRd);
22332306
EXPAND(AVR::LSLWNRd);
22342307
EXPAND(AVR::LSRWNRd);
22352308
EXPAND(AVR::ASRWNRd);

llvm/lib/Target/AVR/AVRISelLowering.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,16 +392,22 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
392392
Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
393393
DAG.getConstant(8, dl, VT));
394394
ShiftAmount -= 8;
395+
// Only operate on the higher byte for remaining shift bits.
396+
Opc8 = AVRISD::LSLHI;
395397
break;
396398
case ISD::SRL:
397399
Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
398400
DAG.getConstant(8, dl, VT));
399401
ShiftAmount -= 8;
402+
// Only operate on the lower byte for remaining shift bits.
403+
Opc8 = AVRISD::LSRLO;
400404
break;
401405
case ISD::SRA:
402406
Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
403407
DAG.getConstant(8, dl, VT));
404408
ShiftAmount -= 8;
409+
// Only operate on the lower byte for remaining shift bits.
410+
Opc8 = AVRISD::ASRLO;
405411
break;
406412
default:
407413
break;
@@ -412,11 +418,22 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
412418
Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
413419
DAG.getConstant(12, dl, VT));
414420
ShiftAmount -= 12;
421+
// Only operate on the higher byte for remaining shift bits.
422+
Opc8 = AVRISD::LSLHI;
415423
break;
416424
case ISD::SRL:
417425
Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
418426
DAG.getConstant(12, dl, VT));
419427
ShiftAmount -= 12;
428+
// Only operate on the lower byte for remaining shift bits.
429+
Opc8 = AVRISD::LSRLO;
430+
break;
431+
case ISD::SRA:
432+
Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
433+
DAG.getConstant(8, dl, VT));
434+
ShiftAmount -= 8;
435+
// Only operate on the lower byte for remaining shift bits.
436+
Opc8 = AVRISD::ASRLO;
420437
break;
421438
default:
422439
break;

llvm/lib/Target/AVR/AVRISelLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@ enum NodeType {
3838
LSL, ///< Logical shift left.
3939
LSLBN, ///< Byte logical shift left N bits.
4040
LSLWN, ///< Word logical shift left N bits.
41+
LSLHI, ///< Higher 8-bit of word logical shift left.
4142
LSR, ///< Logical shift right.
4243
LSRBN, ///< Byte logical shift right N bits.
4344
LSRWN, ///< Word logical shift right N bits.
45+
LSRLO, ///< Lower 8-bit of word logical shift right.
4446
ASR, ///< Arithmetic shift right.
4547
ASRBN, ///< Byte arithmetic shift right N bits.
4648
ASRWN, ///< Word arithmetic shift right N bits.
49+
ASRLO, ///< Lower 8-bit of word arithmetic shift right.
4750
ROR, ///< Bit rotate right.
4851
ROL, ///< Bit rotate left.
4952
LSLLOOP, ///< A loop of single logical shift left instructions.

llvm/lib/Target/AVR/AVRInstrInfo.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ def AVRlsr : SDNode<"AVRISD::LSR", SDTIntUnaryOp>;
6060
def AVRrol : SDNode<"AVRISD::ROL", SDTIntUnaryOp>;
6161
def AVRror : SDNode<"AVRISD::ROR", SDTIntUnaryOp>;
6262
def AVRasr : SDNode<"AVRISD::ASR", SDTIntUnaryOp>;
63+
def AVRlslhi : SDNode<"AVRISD::LSLHI", SDTIntUnaryOp>;
64+
def AVRlsrlo : SDNode<"AVRISD::LSRLO", SDTIntUnaryOp>;
65+
def AVRasrlo : SDNode<"AVRISD::ASRLO", SDTIntUnaryOp>;
6366
def AVRlslbn : SDNode<"AVRISD::LSLBN", SDTIntBinOp>;
6467
def AVRlsrbn : SDNode<"AVRISD::LSRBN", SDTIntBinOp>;
6568
def AVRasrbn : SDNode<"AVRISD::ASRBN", SDTIntBinOp>;
@@ -1848,6 +1851,9 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
18481851
: $src)),
18491852
(implicit SREG)]>;
18501853

1854+
def LSLWHiRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lslwhi\t$rd",
1855+
[(set i16:$rd, (AVRlslhi i16:$src)), (implicit SREG)]>;
1856+
18511857
def LSLWNRd : Pseudo<(outs DLDREGS
18521858
: $rd),
18531859
(ins DREGS
@@ -1895,6 +1901,9 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
18951901
: $src)),
18961902
(implicit SREG)]>;
18971903

1904+
def LSRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "lsrwlo\t$rd",
1905+
[(set i16:$rd, (AVRlsrlo i16:$src)), (implicit SREG)]>;
1906+
18981907
def LSRWNRd : Pseudo<(outs DLDREGS
18991908
: $rd),
19001909
(ins DREGS
@@ -1968,6 +1977,9 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
19681977
: $src)),
19691978
(implicit SREG)]>;
19701979

1980+
def ASRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "asrwlo\t$rd",
1981+
[(set i16:$rd, (AVRasrlo i16:$src)), (implicit SREG)]>;
1982+
19711983
def ROLBRd : Pseudo<(outs GPR8
19721984
: $rd),
19731985
(ins GPR8

llvm/test/CodeGen/AVR/shift.ll

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,7 @@ define i16 @lsl_i16_9(i16 %a) {
227227
; CHECK-LABEL: lsl_i16_9
228228
; CHECK: mov r25, r24
229229
; CHECK-NEXT: clr r24
230-
; CHECK-NEXT: lsl r24
231-
; CHECK-NEXT: rol r25
230+
; CHECK-NEXT: lsl r25
232231
; CHECK-NEXT: ret
233232
%result = shl i16 %a, 9
234233
ret i16 %result
@@ -240,8 +239,7 @@ define i16 @lsl_i16_13(i16 %a) {
240239
; CHECK-NEXT: swap r25
241240
; CHECK-NEXT: andi r25, 240
242241
; CHECK-NEXT: clr r24
243-
; CHECK-NEXT: lsl r24
244-
; CHECK-NEXT: rol r25
242+
; CHECK-NEXT: lsl r25
245243
; CHECK-NEXT: ret
246244
%result = shl i16 %a, 13
247245
ret i16 %result
@@ -285,8 +283,7 @@ define i16 @lsr_i16_9(i16 %a) {
285283
; CHECK-LABEL: lsr_i16_9
286284
; CHECK: mov r24, r25
287285
; CHECK-NEXT: clr r25
288-
; CHECK-NEXT: lsr r25
289-
; CHECK-NEXT: ror r24
286+
; CHECK-NEXT: lsr r24
290287
; CHECK-NEXT: ret
291288
%result = lshr i16 %a, 9
292289
ret i16 %result
@@ -298,8 +295,7 @@ define i16 @lsr_i16_13(i16 %a) {
298295
; CHECK-NEXT: swap r24
299296
; CHECK-NEXT: andi r24, 15
300297
; CHECK-NEXT: clr r25
301-
; CHECK-NEXT: lsr r25
302-
; CHECK-NEXT: ror r24
298+
; CHECK-NEXT: lsr r24
303299
; CHECK-NEXT: ret
304300
%result = lshr i16 %a, 13
305301
ret i16 %result
@@ -310,9 +306,22 @@ define i16 @asr_i16_9(i16 %a) {
310306
; CHECK: mov r24, r25
311307
; CHECK-NEXT: lsl r25
312308
; CHECK-NEXT: sbc r25, r25
313-
; CHECK-NEXT: asr r25
314-
; CHECK-NEXT: ror r24
309+
; CHECK-NEXT: asr r24
315310
; CHECK-NEXT: ret
316311
%result = ashr i16 %a, 9
317312
ret i16 %result
318313
}
314+
315+
define i16 @asr_i16_12(i16 %a) {
316+
; CHECK-LABEL: asr_i16_12
317+
; CHECK: mov r24, r25
318+
; CHECK-NEXT: lsl r25
319+
; CHECK-NEXT: sbc r25, r25
320+
; CHECK-NEXT: asr r24
321+
; CHECK-NEXT: asr r24
322+
; CHECK-NEXT: asr r24
323+
; CHECK-NEXT: asr r24
324+
; CHECK-NEXT: ret
325+
%result = ashr i16 %a, 12
326+
ret i16 %result
327+
}

0 commit comments

Comments
 (0)