Skip to content

Commit 50f1aa1

Browse files
committed
[AVR] Optimize 16-bit int shift
Reviewed By: dylanmckay Differential Revision: https://reviews.llvm.org/D90092
1 parent 7e99bdd commit 50f1aa1

File tree

5 files changed

+483
-7
lines changed

5 files changed

+483
-7
lines changed

llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,135 @@ bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
14021402
return true;
14031403
}
14041404

1405+
template <>
1406+
bool AVRExpandPseudo::expand<AVR::LSLW4Rd>(Block &MBB, BlockIt MBBI) {
1407+
MachineInstr &MI = *MBBI;
1408+
Register DstLoReg, DstHiReg;
1409+
Register DstReg = MI.getOperand(0).getReg();
1410+
bool DstIsDead = MI.getOperand(0).isDead();
1411+
bool DstIsKill = MI.getOperand(1).isKill();
1412+
bool ImpIsDead = MI.getOperand(2).isDead();
1413+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1414+
1415+
// swap Rh
1416+
// swap Rl
1417+
buildMI(MBB, MBBI, AVR::SWAPRd)
1418+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1419+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1420+
buildMI(MBB, MBBI, AVR::SWAPRd)
1421+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1422+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1423+
1424+
// andi Rh, 0xf0
1425+
auto MI0 =
1426+
buildMI(MBB, MBBI, AVR::ANDIRdK)
1427+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1428+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1429+
.addImm(0xf0);
1430+
// SREG is implicitly dead.
1431+
MI0->getOperand(3).setIsDead();
1432+
1433+
// eor Rh, Rl
1434+
auto MI1 =
1435+
buildMI(MBB, MBBI, AVR::EORRdRr)
1436+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1437+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1438+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1439+
// SREG is implicitly dead.
1440+
MI1->getOperand(3).setIsDead();
1441+
1442+
// andi Rl, 0xf0
1443+
auto MI2 =
1444+
buildMI(MBB, MBBI, AVR::ANDIRdK)
1445+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1446+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1447+
.addImm(0xf0);
1448+
// SREG is implicitly dead.
1449+
MI2->getOperand(3).setIsDead();
1450+
1451+
// eor Rh, Rl
1452+
auto MI3 =
1453+
buildMI(MBB, MBBI, AVR::EORRdRr)
1454+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1455+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1456+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1457+
if (ImpIsDead)
1458+
MI3->getOperand(3).setIsDead();
1459+
1460+
MI.eraseFromParent();
1461+
return true;
1462+
}
1463+
1464+
template <>
1465+
bool AVRExpandPseudo::expand<AVR::LSLW8Rd>(Block &MBB, BlockIt MBBI) {
1466+
MachineInstr &MI = *MBBI;
1467+
Register DstLoReg, DstHiReg;
1468+
Register DstReg = MI.getOperand(0).getReg();
1469+
bool DstIsDead = MI.getOperand(0).isDead();
1470+
bool DstIsKill = MI.getOperand(1).isKill();
1471+
bool ImpIsDead = MI.getOperand(2).isDead();
1472+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1473+
1474+
// mov Rh, Rl
1475+
buildMI(MBB, MBBI, AVR::MOVRdRr)
1476+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1477+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1478+
1479+
// clr Rl
1480+
auto MIBLO =
1481+
buildMI(MBB, MBBI, AVR::EORRdRr)
1482+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1483+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1484+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1485+
if (ImpIsDead)
1486+
MIBLO->getOperand(3).setIsDead();
1487+
1488+
MI.eraseFromParent();
1489+
return true;
1490+
}
1491+
1492+
template <>
1493+
bool AVRExpandPseudo::expand<AVR::LSLW12Rd>(Block &MBB, BlockIt MBBI) {
1494+
MachineInstr &MI = *MBBI;
1495+
Register DstLoReg, DstHiReg;
1496+
Register DstReg = MI.getOperand(0).getReg();
1497+
bool DstIsDead = MI.getOperand(0).isDead();
1498+
bool DstIsKill = MI.getOperand(1).isKill();
1499+
bool ImpIsDead = MI.getOperand(2).isDead();
1500+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1501+
1502+
// mov Rh, Rl
1503+
buildMI(MBB, MBBI, AVR::MOVRdRr)
1504+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1505+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1506+
1507+
// swap Rh
1508+
buildMI(MBB, MBBI, AVR::SWAPRd)
1509+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1510+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1511+
1512+
// andi Rh, 0xf0
1513+
auto MI0 =
1514+
buildMI(MBB, MBBI, AVR::ANDIRdK)
1515+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1516+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1517+
.addImm(0xf0);
1518+
// SREG is implicitly dead.
1519+
MI0->getOperand(3).setIsDead();
1520+
1521+
// clr Rl
1522+
auto MI1 =
1523+
buildMI(MBB, MBBI, AVR::EORRdRr)
1524+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1525+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1526+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1527+
if (ImpIsDead)
1528+
MI1->getOperand(3).setIsDead();
1529+
1530+
MI.eraseFromParent();
1531+
return true;
1532+
}
1533+
14051534
template <>
14061535
bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
14071536
MachineInstr &MI = *MBBI;
@@ -1433,6 +1562,135 @@ bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
14331562
return true;
14341563
}
14351564

1565+
template <>
1566+
bool AVRExpandPseudo::expand<AVR::LSRW4Rd>(Block &MBB, BlockIt MBBI) {
1567+
MachineInstr &MI = *MBBI;
1568+
Register DstLoReg, DstHiReg;
1569+
Register DstReg = MI.getOperand(0).getReg();
1570+
bool DstIsDead = MI.getOperand(0).isDead();
1571+
bool DstIsKill = MI.getOperand(1).isKill();
1572+
bool ImpIsDead = MI.getOperand(2).isDead();
1573+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1574+
1575+
// swap Rh
1576+
// swap Rl
1577+
buildMI(MBB, MBBI, AVR::SWAPRd)
1578+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1579+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1580+
buildMI(MBB, MBBI, AVR::SWAPRd)
1581+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1582+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1583+
1584+
// andi Rl, 0xf
1585+
auto MI0 =
1586+
buildMI(MBB, MBBI, AVR::ANDIRdK)
1587+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1588+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1589+
.addImm(0xf);
1590+
// SREG is implicitly dead.
1591+
MI0->getOperand(3).setIsDead();
1592+
1593+
// eor Rl, Rh
1594+
auto MI1 =
1595+
buildMI(MBB, MBBI, AVR::EORRdRr)
1596+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1597+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1598+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1599+
// SREG is implicitly dead.
1600+
MI1->getOperand(3).setIsDead();
1601+
1602+
// andi Rh, 0xf
1603+
auto MI2 =
1604+
buildMI(MBB, MBBI, AVR::ANDIRdK)
1605+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1606+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1607+
.addImm(0xf);
1608+
// SREG is implicitly dead.
1609+
MI2->getOperand(3).setIsDead();
1610+
1611+
// eor Rl, Rh
1612+
auto MI3 =
1613+
buildMI(MBB, MBBI, AVR::EORRdRr)
1614+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1615+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1616+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1617+
if (ImpIsDead)
1618+
MI3->getOperand(3).setIsDead();
1619+
1620+
MI.eraseFromParent();
1621+
return true;
1622+
}
1623+
1624+
template <>
1625+
bool AVRExpandPseudo::expand<AVR::LSRW8Rd>(Block &MBB, BlockIt MBBI) {
1626+
MachineInstr &MI = *MBBI;
1627+
Register DstLoReg, DstHiReg;
1628+
Register DstReg = MI.getOperand(0).getReg();
1629+
bool DstIsDead = MI.getOperand(0).isDead();
1630+
bool DstIsKill = MI.getOperand(1).isKill();
1631+
bool ImpIsDead = MI.getOperand(2).isDead();
1632+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1633+
1634+
// Move upper byte to lower byte.
1635+
buildMI(MBB, MBBI, AVR::MOVRdRr)
1636+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1637+
.addReg(DstHiReg);
1638+
1639+
// Clear upper byte.
1640+
auto MIBHI =
1641+
buildMI(MBB, MBBI, AVR::EORRdRr)
1642+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1643+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1644+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1645+
if (ImpIsDead)
1646+
MIBHI->getOperand(3).setIsDead();
1647+
1648+
MI.eraseFromParent();
1649+
return true;
1650+
}
1651+
1652+
template <>
1653+
bool AVRExpandPseudo::expand<AVR::LSRW12Rd>(Block &MBB, BlockIt MBBI) {
1654+
MachineInstr &MI = *MBBI;
1655+
Register DstLoReg, DstHiReg;
1656+
Register DstReg = MI.getOperand(0).getReg();
1657+
bool DstIsDead = MI.getOperand(0).isDead();
1658+
bool DstIsKill = MI.getOperand(1).isKill();
1659+
bool ImpIsDead = MI.getOperand(2).isDead();
1660+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1661+
1662+
// Move upper byte to lower byte.
1663+
buildMI(MBB, MBBI, AVR::MOVRdRr)
1664+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1665+
.addReg(DstHiReg);
1666+
1667+
// swap Rl
1668+
buildMI(MBB, MBBI, AVR::SWAPRd)
1669+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1670+
.addReg(DstLoReg, getKillRegState(DstIsKill));
1671+
1672+
// andi Rl, 0xf
1673+
auto MI0 =
1674+
buildMI(MBB, MBBI, AVR::ANDIRdK)
1675+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1676+
.addReg(DstLoReg, getKillRegState(DstIsKill))
1677+
.addImm(0xf);
1678+
// SREG is implicitly dead.
1679+
MI0->getOperand(3).setIsDead();
1680+
1681+
// Clear upper byte.
1682+
auto MIBHI =
1683+
buildMI(MBB, MBBI, AVR::EORRdRr)
1684+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1685+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1686+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1687+
if (ImpIsDead)
1688+
MIBHI->getOperand(3).setIsDead();
1689+
1690+
MI.eraseFromParent();
1691+
return true;
1692+
}
1693+
14361694
template <>
14371695
bool AVRExpandPseudo::expand<AVR::RORWRd>(Block &MBB, BlockIt MBBI) {
14381696
llvm_unreachable("RORW unimplemented");
@@ -1476,6 +1734,39 @@ bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
14761734
return true;
14771735
}
14781736

1737+
template <>
1738+
bool AVRExpandPseudo::expand<AVR::ASRW8Rd>(Block &MBB, BlockIt MBBI) {
1739+
MachineInstr &MI = *MBBI;
1740+
Register DstLoReg, DstHiReg;
1741+
Register DstReg = MI.getOperand(0).getReg();
1742+
bool DstIsDead = MI.getOperand(0).isDead();
1743+
bool DstIsKill = MI.getOperand(1).isKill();
1744+
bool ImpIsDead = MI.getOperand(2).isDead();
1745+
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1746+
1747+
// Move upper byte to lower byte.
1748+
buildMI(MBB, MBBI, AVR::MOVRdRr)
1749+
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1750+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1751+
1752+
// Move the sign bit to the C flag.
1753+
buildMI(MBB, MBBI, AVR::ADDRdRr).addReg(DstHiReg)
1754+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1755+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1756+
1757+
// Set upper byte to 0 or -1.
1758+
auto MIBHI =
1759+
buildMI(MBB, MBBI, AVR::SBCRdRr)
1760+
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1761+
.addReg(DstHiReg, getKillRegState(DstIsKill))
1762+
.addReg(DstHiReg, getKillRegState(DstIsKill));
1763+
if (ImpIsDead)
1764+
MIBHI->getOperand(3).setIsDead();
1765+
1766+
MI.eraseFromParent();
1767+
return true;
1768+
}
1769+
14791770
template <>
14801771
bool AVRExpandPseudo::expand<AVR::LSLB7Rd>(Block &MBB, BlockIt MBBI) {
14811772
MachineInstr &MI = *MBBI;
@@ -1798,10 +2089,17 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
17982089
EXPAND(AVR::ROLBRd);
17992090
EXPAND(AVR::RORBRd);
18002091
EXPAND(AVR::LSLWRd);
2092+
EXPAND(AVR::LSLW4Rd);
2093+
EXPAND(AVR::LSLW8Rd);
2094+
EXPAND(AVR::LSLW12Rd);
18012095
EXPAND(AVR::LSRWRd);
2096+
EXPAND(AVR::LSRW4Rd);
2097+
EXPAND(AVR::LSRW8Rd);
2098+
EXPAND(AVR::LSRW12Rd);
18022099
EXPAND(AVR::RORWRd);
18032100
EXPAND(AVR::ROLWRd);
18042101
EXPAND(AVR::ASRWRd);
2102+
EXPAND(AVR::ASRW8Rd);
18052103
EXPAND(AVR::LSLB7Rd);
18062104
EXPAND(AVR::LSRB7Rd);
18072105
EXPAND(AVR::ASRB7Rd);

llvm/lib/Target/AVR/AVRISelLowering.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
334334
llvm_unreachable("Invalid shift opcode");
335335
}
336336

337-
// Optimize int8 shifts.
337+
// Optimize int8/int16 shifts.
338338
if (VT.getSizeInBits() == 8) {
339339
if (Op.getOpcode() == ISD::SHL && 4 <= ShiftAmount && ShiftAmount < 7) {
340340
// Optimize LSL when 4 <= ShiftAmount <= 6.
@@ -362,6 +362,50 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
362362
Victim = DAG.getNode(AVRISD::ASR7, dl, VT, Victim);
363363
ShiftAmount = 0;
364364
}
365+
} else if (VT.getSizeInBits() == 16) {
366+
if (4 <= ShiftAmount && ShiftAmount < 8)
367+
switch (Op.getOpcode()) {
368+
case ISD::SHL:
369+
Victim = DAG.getNode(AVRISD::LSL4, dl, VT, Victim);
370+
ShiftAmount -= 4;
371+
break;
372+
case ISD::SRL:
373+
Victim = DAG.getNode(AVRISD::LSR4, dl, VT, Victim);
374+
ShiftAmount -= 4;
375+
break;
376+
default:
377+
break;
378+
}
379+
else if (8 <= ShiftAmount && ShiftAmount < 12)
380+
switch (Op.getOpcode()) {
381+
case ISD::SHL:
382+
Victim = DAG.getNode(AVRISD::LSL8, dl, VT, Victim);
383+
ShiftAmount -= 8;
384+
break;
385+
case ISD::SRL:
386+
Victim = DAG.getNode(AVRISD::LSR8, dl, VT, Victim);
387+
ShiftAmount -= 8;
388+
break;
389+
case ISD::SRA:
390+
Victim = DAG.getNode(AVRISD::ASR8, dl, VT, Victim);
391+
ShiftAmount -= 8;
392+
break;
393+
default:
394+
break;
395+
}
396+
else if (12 <= ShiftAmount)
397+
switch (Op.getOpcode()) {
398+
case ISD::SHL:
399+
Victim = DAG.getNode(AVRISD::LSL12, dl, VT, Victim);
400+
ShiftAmount -= 12;
401+
break;
402+
case ISD::SRL:
403+
Victim = DAG.getNode(AVRISD::LSR12, dl, VT, Victim);
404+
ShiftAmount -= 12;
405+
break;
406+
default:
407+
break;
408+
}
365409
}
366410

367411
while (ShiftAmount--) {

0 commit comments

Comments
 (0)