}
template <>
+bool AVRExpandPseudo::expand<AVR::NEGWRd>(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);
+
+ // Do NEG on the upper byte.
+ auto MIBHI =
+ buildMI(MBB, MBBI, AVR::NEGRd)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, getKillRegState(DstIsKill));
+ // SREG is always implicitly dead
+ MIBHI->getOperand(2).setIsDead();
+
+ // Do NEG on the lower byte.
+ buildMI(MBB, MBBI, AVR::NEGRd)
+ .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstLoReg, getKillRegState(DstIsKill));
+
+ // Do an extra SBCI.
+ auto MISBCI =
+ buildMI(MBB, MBBI, AVR::SBCIRdK)
+ .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
+ .addReg(DstHiReg, getKillRegState(DstIsKill))
+ .addImm(0);
+ if (ImpIsDead)
+ MISBCI->getOperand(3).setIsDead();
+ // SREG is always implicitly killed
+ MISBCI->getOperand(4).setIsKill();
+
+ MI.eraseFromParent();
+ return true;
+}
+
+template <>
bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {
MachineInstr &MI = *MBBI;
Register SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
EXPAND(AVR::ORIWRdK);
EXPAND(AVR::EORWRdRr);
EXPAND(AVR::COMWRd);
+ EXPAND(AVR::NEGWRd);
EXPAND(AVR::CPWRdRr);
EXPAND(AVR::CPCWRdRr);
EXPAND(AVR::LDIWRdK);
"comw\t$rd",
[(set i16:$rd, (not i16:$src)), (implicit SREG)]>;
- //:TODO: optimize NEG for wider types
def NEGRd : FRd<0b1001,
0b0100001,
(outs GPR8:$rd),
(ins GPR8:$src),
"neg\t$rd",
[(set i8:$rd, (ineg i8:$src)), (implicit SREG)]>;
+
+ // NEGW Rd+1:Rd
+ //
+ // Expands to:
+ // neg Rd+1
+ // neg Rd
+ // sbci Rd+1, 0
+ def NEGWRd : Pseudo<(outs DREGS:$rd),
+ (ins DREGS:$src),
+ "negw\t$rd",
+ [(set i16:$rd, (ineg i16:$src)), (implicit SREG)]>;
}
// TST Rd
--- /dev/null
+# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s
+
+# This test checks the expansion of the 16-bit NEG pseudo instruction.
+
+--- |
+ target triple = "avr--"
+ define void @test_negwrd() {
+ entry:
+ ret void
+ }
+...
+
+---
+name: test_negwrd
+body: |
+ bb.0.entry:
+
+ ; CHECK-LABEL: test_negwrd
+
+ ; CHECK: $r15 = NEGRd $r15, implicit-def dead $sreg
+ ; CHECK-NEXT: $r14 = NEGRd $r14
+ ; CHECK-NEXT: $r15 = SBCIRdK $r15, 0, implicit-def $sreg, implicit killed $sreg
+
+ $r15r14 = NEGWRd $r15r14, implicit-def $sreg
+...