diff options
Diffstat (limited to 'llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp')
| -rw-r--r-- | llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 446 |
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); |
