aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp')
-rw-r--r--llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp446
1 files changed, 284 insertions, 162 deletions
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 144ae2b320f9..a9dc9af819e6 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -54,8 +54,6 @@ private:
const Register SCRATCH_REGISTER = AVR::R0;
/// The register that will always contain zero.
const Register ZERO_REGISTER = AVR::R1;
- /// The IO address of the status register.
- const unsigned SREG_ADDR = 0x3f;
bool expandMBB(Block &MBB);
bool expandMI(Block &MBB, BlockIt MBBI);
@@ -86,21 +84,23 @@ private:
bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI);
- bool expandAtomicArithmeticOp(unsigned MemOpcode, unsigned ArithOpcode,
- Block &MBB, BlockIt MBBI);
-
- /// Specific shift implementation.
+ /// Specific shift implementation for int8.
bool expandLSLB7Rd(Block &MBB, BlockIt MBBI);
bool expandLSRB7Rd(Block &MBB, BlockIt MBBI);
bool expandASRB6Rd(Block &MBB, BlockIt MBBI);
bool expandASRB7Rd(Block &MBB, BlockIt MBBI);
+
+ /// Specific shift implementation for int16.
bool expandLSLW4Rd(Block &MBB, BlockIt MBBI);
bool expandLSRW4Rd(Block &MBB, BlockIt MBBI);
+ bool expandASRW7Rd(Block &MBB, BlockIt MBBI);
bool expandLSLW8Rd(Block &MBB, BlockIt MBBI);
bool expandLSRW8Rd(Block &MBB, BlockIt MBBI);
bool expandASRW8Rd(Block &MBB, BlockIt MBBI);
bool expandLSLW12Rd(Block &MBB, BlockIt MBBI);
bool expandLSRW12Rd(Block &MBB, BlockIt MBBI);
+ bool expandASRW14Rd(Block &MBB, BlockIt MBBI);
+ bool expandASRW15Rd(Block &MBB, BlockIt MBBI);
// Common implementation of LPMWRdZ and ELPMWRdZ.
bool expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsExt);
@@ -141,6 +141,7 @@ bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
// Continue expanding the block until all pseudos are expanded.
do {
assert(ExpandCount < 10 && "pseudo expand limit reached");
+ (void)ExpandCount;
bool BlockModified = expandMBB(MBB);
Modified |= BlockModified;
@@ -453,7 +454,7 @@ bool AVRExpandPseudo::expand<AVR::NEGWRd>(Block &MBB, BlockIt MBBI) {
auto MIBHI =
buildMI(MBB, MBBI, AVR::NEGRd)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill));
+ .addReg(DstHiReg, RegState::Kill);
// SREG is always implicitly dead
MIBHI->getOperand(2).setIsDead();
@@ -917,13 +918,13 @@ bool AVRExpandPseudo::expand<AVR::ELPMWRdZPi>(Block &MBB, BlockIt MBBI) {
template <typename Func>
bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {
- // Remove the pseudo instruction.
MachineInstr &MI = *MBBI;
+ const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
// Store the SREG.
buildMI(MBB, MBBI, AVR::INRdA)
.addReg(SCRATCH_REGISTER, RegState::Define)
- .addImm(SREG_ADDR);
+ .addImm(STI.getIORegSREG());
// Disable exceptions.
buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI
@@ -931,7 +932,9 @@ bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {
f(MI);
// Restore the status reg.
- buildMI(MBB, MBBI, AVR::OUTARr).addImm(SREG_ADDR).addReg(SCRATCH_REGISTER);
+ buildMI(MBB, MBBI, AVR::OUTARr)
+ .addImm(STI.getIORegSREG())
+ .addReg(SCRATCH_REGISTER);
MI.eraseFromParent();
return true;
@@ -955,31 +958,6 @@ bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode, Block &MBB,
return expandAtomicBinaryOp(Opcode, MBB, MBBI, [](MachineInstr &MI) {});
}
-bool AVRExpandPseudo::expandAtomicArithmeticOp(unsigned Width,
- unsigned ArithOpcode, Block &MBB,
- BlockIt MBBI) {
- return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
- auto DstReg = MI.getOperand(0).getReg();
- auto PtrOp = MI.getOperand(1);
- auto SrcReg = MI.getOperand(2).getReg();
-
- unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
- unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
-
- // FIXME: this returns the new value (after the operation), not the old
- // value as the atomicrmw instruction is supposed to do!
-
- // Create the load
- buildMI(MBB, MBBI, LoadOpcode, DstReg).addReg(PtrOp.getReg());
-
- // Create the arithmetic op
- buildMI(MBB, MBBI, ArithOpcode, DstReg).addReg(DstReg).addReg(SrcReg);
-
- // Create the store
- buildMI(MBB, MBBI, StoreOpcode).add(PtrOp).addReg(DstReg);
- });
-}
-
Register AVRExpandPseudo::scavengeGPR8(MachineInstr &MI) {
MachineBasicBlock &MBB = *MI.getParent();
RegScavenger RS;
@@ -1026,56 +1004,6 @@ bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {
}
template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd8>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(8, AVR::ADDRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd16>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(16, AVR::ADDWRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadSub8>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(8, AVR::SUBRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadSub16>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(16, AVR::SUBWRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd8>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(8, AVR::ANDRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd16>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(16, AVR::ANDWRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadOr8>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(8, AVR::ORRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadOr16>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(16, AVR::ORWRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadXor8>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(8, AVR::EORRdRr, MBB, MBBI);
-}
-
-template <>
-bool AVRExpandPseudo::expand<AVR::AtomicLoadXor16>(Block &MBB, BlockIt MBBI) {
- return expandAtomicArithmeticOp(16, AVR::EORWRdRr, MBB, MBBI);
-}
-
-template <>
bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {
// On AVR, there is only one core and so atomic fences do nothing.
MBBI->eraseFromParent();
@@ -1230,38 +1158,95 @@ bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
- Register SrcLoReg, SrcHiReg;
+
Register DstReg = MI.getOperand(0).getReg();
- Register SrcReg = MI.getOperand(2).getReg();
- unsigned Imm = MI.getOperand(1).getImm();
bool DstIsKill = MI.getOperand(0).isKill();
+ unsigned Imm = MI.getOperand(1).getImm();
+ Register SrcReg = MI.getOperand(2).getReg();
bool SrcIsKill = MI.getOperand(2).isKill();
- unsigned OpLo = AVR::STDPtrQRr;
- unsigned OpHi = AVR::STDPtrQRr;
- TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- // Since we add 1 to the Imm value for the high byte below, and 63 is the
- // highest Imm value allowed for the instruction, 62 is the limit here.
- assert(Imm <= 62 && "Offset is out of range");
+ // STD's maximum displacement is 63, so larger stores have to be split into a
+ // set of operations
+ if (Imm >= 63) {
+ if (!DstIsKill) {
+ buildMI(MBB, MBBI, AVR::PUSHWRr).addReg(DstReg);
+ }
- auto MIBLO = buildMI(MBB, MBBI, OpLo)
- .addReg(DstReg)
- .addImm(Imm)
- .addReg(SrcLoReg, getKillRegState(SrcIsKill));
+ buildMI(MBB, MBBI, AVR::SUBIWRdK)
+ .addReg(DstReg, RegState::Define)
+ .addReg(DstReg, RegState::Kill)
+ .addImm(-Imm);
- auto MIBHI = buildMI(MBB, MBBI, OpHi)
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addImm(Imm + 1)
- .addReg(SrcHiReg, getKillRegState(SrcIsKill));
+ buildMI(MBB, MBBI, AVR::STWPtrRr)
+ .addReg(DstReg, RegState::Kill)
+ .addReg(SrcReg, getKillRegState(SrcIsKill));
- MIBLO.setMemRefs(MI.memoperands());
- MIBHI.setMemRefs(MI.memoperands());
+ if (!DstIsKill) {
+ buildMI(MBB, MBBI, AVR::POPWRd).addDef(DstReg, RegState::Define);
+ }
+ } else {
+ unsigned OpLo = AVR::STDPtrQRr;
+ unsigned OpHi = AVR::STDPtrQRr;
+ Register SrcLoReg, SrcHiReg;
+ TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
+
+ auto MIBLO = buildMI(MBB, MBBI, OpLo)
+ .addReg(DstReg)
+ .addImm(Imm)
+ .addReg(SrcLoReg, getKillRegState(SrcIsKill));
+
+ auto MIBHI = buildMI(MBB, MBBI, OpHi)
+ .addReg(DstReg, getKillRegState(DstIsKill))
+ .addImm(Imm + 1)
+ .addReg(SrcHiReg, getKillRegState(SrcIsKill));
+
+ MIBLO.setMemRefs(MI.memoperands());
+ MIBHI.setMemRefs(MI.memoperands());
+ }
MI.eraseFromParent();
return true;
}
template <>
+bool AVRExpandPseudo::expand<AVR::STDSPQRr>(Block &MBB, BlockIt MBBI) {
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
+
+ assert(MI.getOperand(0).getReg() == AVR::SP &&
+ "SP is expected as base pointer");
+
+ assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
+ "unexpected STDSPQRr pseudo instruction");
+ (void)STI;
+
+ MI.setDesc(TII->get(AVR::STDPtrQRr));
+ MI.getOperand(0).setReg(AVR::R29R28);
+
+ return true;
+}
+
+template <>
+bool AVRExpandPseudo::expand<AVR::STDWSPQRr>(Block &MBB, BlockIt MBBI) {
+ MachineInstr &MI = *MBBI;
+ const MachineFunction &MF = *MBB.getParent();
+ const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
+
+ assert(MI.getOperand(0).getReg() == AVR::SP &&
+ "SP is expected as base pointer");
+
+ assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
+ "unexpected STDWSPQRr pseudo instruction");
+ (void)STI;
+
+ MI.setDesc(TII->get(AVR::STDWPtrQRr));
+ MI.getOperand(0).setReg(AVR::R29R28);
+
+ return true;
+}
+
+template <>
bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
Register DstLoReg, DstHiReg;
@@ -1378,6 +1363,7 @@ bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) {
unsigned OpShift, OpCarry;
Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
+ bool DstIsKill = MI.getOperand(1).isKill();
OpShift = AVR::ADDRdRr;
OpCarry = AVR::ADCRdRr;
@@ -1387,13 +1373,13 @@ bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) {
// Shift part
buildMI(MBB, MBBI, OpShift)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg)
- .addReg(DstReg);
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
// Add the carry bit
auto MIB = buildMI(MBB, MBBI, OpCarry)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg)
+ .addReg(DstReg, getKillRegState(DstIsKill))
.addReg(ZERO_REGISTER);
// SREG is always implicitly killed
@@ -1446,13 +1432,13 @@ bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
// Low part
buildMI(MBB, MBBI, OpLo)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstLoReg)
+ .addReg(DstLoReg, getKillRegState(DstIsKill))
.addReg(DstLoReg, getKillRegState(DstIsKill));
auto MIBHI =
buildMI(MBB, MBBI, OpHi)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg)
+ .addReg(DstHiReg, getKillRegState(DstIsKill))
.addReg(DstHiReg, getKillRegState(DstIsKill));
if (ImpIsDead)
@@ -1478,7 +1464,7 @@ bool AVRExpandPseudo::expand<AVR::LSLWHiRd>(Block &MBB, BlockIt MBBI) {
// add hireg, hireg <==> lsl hireg
auto MILSL =
buildMI(MBB, MBBI, AVR::ADDRdRr)
- .addReg(DstHiReg, RegState::Define, getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
.addReg(DstHiReg, getKillRegState(DstIsKill))
.addReg(DstHiReg, getKillRegState(DstIsKill));
@@ -1502,16 +1488,16 @@ bool AVRExpandPseudo::expandLSLW4Rd(Block &MBB, BlockIt MBBI) {
// swap Rl
buildMI(MBB, MBBI, AVR::SWAPRd)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill));
+ .addReg(DstHiReg, RegState::Kill);
buildMI(MBB, MBBI, AVR::SWAPRd)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstLoReg, getKillRegState(DstIsKill));
+ .addReg(DstLoReg, RegState::Kill);
// andi Rh, 0xf0
auto MI0 =
buildMI(MBB, MBBI, AVR::ANDIRdK)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill))
+ .addReg(DstHiReg, RegState::Kill)
.addImm(0xf0);
// SREG is implicitly dead.
MI0->getOperand(3).setIsDead();
@@ -1520,7 +1506,7 @@ bool AVRExpandPseudo::expandLSLW4Rd(Block &MBB, BlockIt MBBI) {
auto MI1 =
buildMI(MBB, MBBI, AVR::EORRdRr)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill))
+ .addReg(DstHiReg, RegState::Kill)
.addReg(DstLoReg);
// SREG is implicitly dead.
MI1->getOperand(3).setIsDead();
@@ -1591,7 +1577,7 @@ bool AVRExpandPseudo::expandLSLW12Rd(Block &MBB, BlockIt MBBI) {
// swap Rh
buildMI(MBB, MBBI, AVR::SWAPRd)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill));
+ .addReg(DstHiReg, RegState::Kill);
// andi Rh, 0xf0
auto MI0 =
@@ -1700,16 +1686,16 @@ bool AVRExpandPseudo::expandLSRW4Rd(Block &MBB, BlockIt MBBI) {
// swap Rl
buildMI(MBB, MBBI, AVR::SWAPRd)
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill));
+ .addReg(DstHiReg, RegState::Kill);
buildMI(MBB, MBBI, AVR::SWAPRd)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstLoReg, getKillRegState(DstIsKill));
+ .addReg(DstLoReg, RegState::Kill);
// andi Rl, 0xf
auto MI0 =
buildMI(MBB, MBBI, AVR::ANDIRdK)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstLoReg, getKillRegState(DstIsKill))
+ .addReg(DstLoReg, RegState::Kill)
.addImm(0xf);
// SREG is implicitly dead.
MI0->getOperand(3).setIsDead();
@@ -1718,7 +1704,7 @@ bool AVRExpandPseudo::expandLSRW4Rd(Block &MBB, BlockIt MBBI) {
auto MI1 =
buildMI(MBB, MBBI, AVR::EORRdRr)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstLoReg, getKillRegState(DstIsKill))
+ .addReg(DstLoReg, RegState::Kill)
.addReg(DstHiReg);
// SREG is implicitly dead.
MI1->getOperand(3).setIsDead();
@@ -1789,7 +1775,7 @@ bool AVRExpandPseudo::expandLSRW12Rd(Block &MBB, BlockIt MBBI) {
// swap Rl
buildMI(MBB, MBBI, AVR::SWAPRd)
.addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstLoReg, getKillRegState(DstIsKill));
+ .addReg(DstLoReg, RegState::Kill);
// andi Rl, 0xf
auto MI0 =
@@ -1897,6 +1883,53 @@ bool AVRExpandPseudo::expand<AVR::ASRWLoRd>(Block &MBB, BlockIt MBBI) {
return true;
}
+bool AVRExpandPseudo::expandASRW7Rd(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(3).isDead();
+ TRI->splitReg(DstReg, DstLoReg, DstHiReg);
+
+ // lsl r24
+ // mov r24,r25
+ // rol r24
+ // sbc r25,r25
+
+ // lsl r24 <=> add r24, r24
+ buildMI(MBB, MBBI, AVR::ADDRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstLoReg, RegState::Kill)
+ .addReg(DstLoReg, RegState::Kill);
+
+ // mov r24, r25
+ buildMI(MBB, MBBI, AVR::MOVRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg);
+
+ // rol r24 <=> adc r24, r24
+ buildMI(MBB, MBBI, AVR::ADCRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstLoReg, getKillRegState(DstIsKill))
+ .addReg(DstLoReg, getKillRegState(DstIsKill));
+
+ // sbc r25, r25
+ auto MISBC =
+ buildMI(MBB, MBBI, AVR::SBCRdRr)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, getKillRegState(DstIsKill))
+ .addReg(DstHiReg, getKillRegState(DstIsKill));
+
+ if (ImpIsDead)
+ MISBC->getOperand(3).setIsDead();
+ // SREG is always implicitly killed
+ MISBC->getOperand(4).setIsKill();
+
+ MI.eraseFromParent();
+ return true;
+}
+
bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
Register DstLoReg, DstHiReg;
@@ -1913,9 +1946,9 @@ bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {
// Move the sign bit to the C flag.
buildMI(MBB, MBBI, AVR::ADDRdRr)
- .addReg(DstHiReg, RegState::Define, getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill) | getDeadRegState(DstIsDead))
- .addReg(DstHiReg, getKillRegState(DstIsKill));
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, RegState::Kill)
+ .addReg(DstHiReg, RegState::Kill);
// Set upper byte to 0 or -1.
auto MIBHI =
@@ -1923,8 +1956,102 @@ bool AVRExpandPseudo::expandASRW8Rd(Block &MBB, BlockIt MBBI) {
.addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
.addReg(DstHiReg, getKillRegState(DstIsKill))
.addReg(DstHiReg, getKillRegState(DstIsKill));
+
if (ImpIsDead)
MIBHI->getOperand(3).setIsDead();
+ // SREG is always implicitly killed
+ MIBHI->getOperand(4).setIsKill();
+
+ MI.eraseFromParent();
+ return true;
+}
+bool AVRExpandPseudo::expandASRW14Rd(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(3).isDead();
+ TRI->splitReg(DstReg, DstLoReg, DstHiReg);
+
+ // lsl r25
+ // sbc r24, r24
+ // lsl r25
+ // mov r25, r24
+ // rol r24
+
+ // lsl r25 <=> add r25, r25
+ buildMI(MBB, MBBI, AVR::ADDRdRr)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, RegState::Kill)
+ .addReg(DstHiReg, RegState::Kill);
+
+ // sbc r24, r24
+ buildMI(MBB, MBBI, AVR::SBCRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstLoReg, RegState::Kill)
+ .addReg(DstLoReg, RegState::Kill);
+
+ // lsl r25 <=> add r25, r25
+ buildMI(MBB, MBBI, AVR::ADDRdRr)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, RegState::Kill)
+ .addReg(DstHiReg, RegState::Kill);
+
+ // mov r25, r24
+ buildMI(MBB, MBBI, AVR::MOVRdRr)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstLoReg);
+
+ // rol r24 <=> adc r24, r24
+ auto MIROL =
+ buildMI(MBB, MBBI, AVR::ADCRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstLoReg, getKillRegState(DstIsKill))
+ .addReg(DstLoReg, getKillRegState(DstIsKill));
+
+ if (ImpIsDead)
+ MIROL->getOperand(3).setIsDead();
+ // SREG is always implicitly killed
+ MIROL->getOperand(4).setIsKill();
+
+ MI.eraseFromParent();
+ return false;
+}
+
+bool AVRExpandPseudo::expandASRW15Rd(Block &MBB, BlockIt MBBI) {
+ MachineInstr &MI = *MBBI;
+ Register DstLoReg, DstHiReg;
+ Register DstReg = MI.getOperand(0).getReg();
+ bool DstIsDead = MI.getOperand(0).isDead();
+ bool ImpIsDead = MI.getOperand(3).isDead();
+ TRI->splitReg(DstReg, DstLoReg, DstHiReg);
+
+ // lsl r25
+ // sbc r25, r25
+ // mov r24, r25
+
+ // lsl r25 <=> add r25, r25
+ buildMI(MBB, MBBI, AVR::ADDRdRr)
+ .addReg(DstHiReg, RegState::Define)
+ .addReg(DstHiReg, RegState::Kill)
+ .addReg(DstHiReg, RegState::Kill);
+
+ // sbc r25, r25
+ auto MISBC =
+ buildMI(MBB, MBBI, AVR::SBCRdRr)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, RegState::Kill)
+ .addReg(DstHiReg, RegState::Kill);
+ if (ImpIsDead)
+ MISBC->getOperand(3).setIsDead();
+ // SREG is always implicitly killed
+ MISBC->getOperand(4).setIsKill();
+
+ // mov r24, r25
+ buildMI(MBB, MBBI, AVR::MOVRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg);
MI.eraseFromParent();
return true;
@@ -1935,8 +2062,14 @@ bool AVRExpandPseudo::expand<AVR::ASRWNRd>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
unsigned Imm = MI.getOperand(2).getImm();
switch (Imm) {
+ case 7:
+ return expandASRW7Rd(MBB, MBBI);
case 8:
return expandASRW8Rd(MBB, MBBI);
+ case 14:
+ return expandASRW14Rd(MBB, MBBI);
+ case 15:
+ return expandASRW15Rd(MBB, MBBI);
default:
llvm_unreachable("unimplemented asrwn");
return false;
@@ -1956,14 +2089,14 @@ bool AVRExpandPseudo::expandLSLB7Rd(Block &MBB, BlockIt MBBI) {
buildMI(MBB, MBBI, AVR::RORRd)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
+ .addReg(DstReg, RegState::Kill)
->getOperand(3)
.setIsUndef(true);
buildMI(MBB, MBBI, AVR::EORRdRr)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addReg(DstReg, getKillRegState(DstIsKill));
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
auto MIRRC =
buildMI(MBB, MBBI, AVR::RORRd)
@@ -2006,15 +2139,15 @@ bool AVRExpandPseudo::expandLSRB7Rd(Block &MBB, BlockIt MBBI) {
buildMI(MBB, MBBI, AVR::ADCRdRr)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addReg(DstReg, getKillRegState(DstIsKill))
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill)
->getOperand(4)
.setIsUndef(true);
buildMI(MBB, MBBI, AVR::EORRdRr)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addReg(DstReg, getKillRegState(DstIsKill));
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
auto MIRRC =
buildMI(MBB, MBBI, AVR::ADCRdRr)
@@ -2064,13 +2197,13 @@ bool AVRExpandPseudo::expandASRB6Rd(Block &MBB, BlockIt MBBI) {
buildMI(MBB, MBBI, AVR::ADDRdRr) // LSL Rd <==> ADD Rd, Rd
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addReg(DstReg, getKillRegState(DstIsKill));
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
buildMI(MBB, MBBI, AVR::SBCRdRr)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addReg(DstReg, getKillRegState(DstIsKill));
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
buildMI(MBB, MBBI, AVR::BLD)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
@@ -2095,8 +2228,8 @@ bool AVRExpandPseudo::expandASRB7Rd(Block &MBB, BlockIt MBBI) {
buildMI(MBB, MBBI, AVR::ADDRdRr)
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(DstReg, getKillRegState(DstIsKill))
- .addReg(DstReg, getKillRegState(DstIsKill));
+ .addReg(DstReg, RegState::Kill)
+ .addReg(DstReg, RegState::Kill);
auto MIRRC =
buildMI(MBB, MBBI, AVR::SBCRdRr)
@@ -2152,26 +2285,22 @@ template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
bool ImpIsDead = MI.getOperand(2).isDead();
TRI->splitReg(DstReg, DstLoReg, DstHiReg);
- if (SrcReg != DstLoReg) {
- auto MOV =
- buildMI(MBB, MBBI, AVR::MOVRdRr)
- .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
- .addReg(SrcReg);
-
- if (SrcReg == DstHiReg) {
- MOV->getOperand(1).setIsKill();
- }
- }
+ if (SrcReg != DstLoReg)
+ buildMI(MBB, MBBI, AVR::MOVRdRr)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(SrcReg);
if (SrcReg != DstHiReg) {
- buildMI(MBB, MBBI, AVR::MOVRdRr)
- .addReg(DstHiReg, RegState::Define)
- .addReg(SrcReg, getKillRegState(SrcIsKill));
+ auto MOV = buildMI(MBB, MBBI, AVR::MOVRdRr)
+ .addReg(DstHiReg, RegState::Define)
+ .addReg(SrcReg);
+ if (SrcReg != DstLoReg && SrcIsKill)
+ MOV->getOperand(1).setIsKill();
}
buildMI(MBB, MBBI, AVR::ADDRdRr) // LSL Rd <==> ADD Rd, Rr
.addReg(DstHiReg, RegState::Define)
- .addReg(DstHiReg)
+ .addReg(DstHiReg, RegState::Kill)
.addReg(DstHiReg, RegState::Kill);
auto SBC =
@@ -2256,6 +2385,7 @@ bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
+ const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
MachineInstr &MI = *MBBI;
Register SrcLoReg, SrcHiReg;
Register SrcReg = MI.getOperand(1).getReg();
@@ -2265,7 +2395,7 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
buildMI(MBB, MBBI, AVR::INRdA)
.addReg(AVR::R0, RegState::Define)
- .addImm(SREG_ADDR)
+ .addImm(STI.getIORegSREG())
.setMIFlags(Flags);
buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
@@ -2276,7 +2406,7 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
.setMIFlags(Flags);
buildMI(MBB, MBBI, AVR::OUTARr)
- .addImm(SREG_ADDR)
+ .addImm(STI.getIORegSREG())
.addReg(AVR::R0, RegState::Kill)
.setMIFlags(Flags);
@@ -2330,22 +2460,14 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
EXPAND(AVR::AtomicLoad16);
EXPAND(AVR::AtomicStore8);
EXPAND(AVR::AtomicStore16);
- EXPAND(AVR::AtomicLoadAdd8);
- EXPAND(AVR::AtomicLoadAdd16);
- EXPAND(AVR::AtomicLoadSub8);
- EXPAND(AVR::AtomicLoadSub16);
- EXPAND(AVR::AtomicLoadAnd8);
- EXPAND(AVR::AtomicLoadAnd16);
- EXPAND(AVR::AtomicLoadOr8);
- EXPAND(AVR::AtomicLoadOr16);
- EXPAND(AVR::AtomicLoadXor8);
- EXPAND(AVR::AtomicLoadXor16);
EXPAND(AVR::AtomicFence);
EXPAND(AVR::STSWKRr);
EXPAND(AVR::STWPtrRr);
EXPAND(AVR::STWPtrPiRr);
EXPAND(AVR::STWPtrPdRr);
EXPAND(AVR::STDWPtrQRr);
+ EXPAND(AVR::STDSPQRr);
+ EXPAND(AVR::STDWSPQRr);
EXPAND(AVR::INWRdA);
EXPAND(AVR::OUTWARr);
EXPAND(AVR::PUSHWRr);