diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp index 73b842daca6a..393b556c9b21 100644 --- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp @@ -2496,26 +2496,36 @@ template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { template <> bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { + const AVRSubtarget &STI = MBB.getParent()->getSubtarget(); MachineInstr &MI = *MBBI; Register DstLoReg, DstHiReg; Register DstReg = MI.getOperand(0).getReg(); bool DstIsDead = MI.getOperand(0).isDead(); unsigned Flags = MI.getFlags(); - unsigned OpLo = AVR::INRdA; - unsigned OpHi = AVR::INRdA; TRI->splitReg(DstReg, DstLoReg, DstHiReg); // Low part - buildMI(MBB, MBBI, OpLo) + buildMI(MBB, MBBI, AVR::INRdA) .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead)) - .addImm(0x3d) + .addImm(STI.getIORegSPL()) .setMIFlags(Flags); // High part - buildMI(MBB, MBBI, OpHi) - .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead)) - .addImm(0x3e) - .setMIFlags(Flags); + if (STI.getIORegSPH() != -1) { + buildMI(MBB, MBBI, AVR::INRdA) + .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead)) + .addImm(STI.getIORegSPH()) + .setMIFlags(Flags); + } else { + // Clear the upper byte if there is no SPH. + auto MI0 = + buildMI(MBB, MBBI, AVR::EORRdRr) + .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstHiReg, RegState::Kill) + .addReg(DstHiReg); + // SREG is implicitly dead. + MI0->getOperand(3).setIsDead(); + } MI.eraseFromParent(); return true; @@ -2536,7 +2546,6 @@ bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { // a write to SPL will automatically disable interrupts // for up to four instructions or until the next I/O memory write. if (STI.getELFArch() >= 102) { // An XMEGA device - buildMI(MBB, MBBI, AVR::OUTARr) .addImm(STI.getIORegSPL()) .addReg(SrcLoReg, getKillRegState(SrcIsKill)) @@ -2546,12 +2555,9 @@ bool AVRExpandPseudo::expand(Block &MBB, BlockIt MBBI) { .addImm(STI.getIORegSPH()) .addReg(SrcHiReg, getKillRegState(SrcIsKill)) .setMIFlags(Flags); - } else { // Disable interrupts for older devices with SPH (3 extra // instructions) - if (STI.getIORegSPH() != -1) { - buildMI(MBB, MBBI, AVR::INRdA) .addReg(STI.getTmpRegister(), RegState::Define) .addImm(STI.getIORegSREG()) diff --git a/llvm/test/CodeGen/AVR/calling-conv/c/tiny.ll b/llvm/test/CodeGen/AVR/calling-conv/c/tiny.ll index ab1035d08602..7257eab8e12a 100644 --- a/llvm/test/CodeGen/AVR/calling-conv/c/tiny.ll +++ b/llvm/test/CodeGen/AVR/calling-conv/c/tiny.ll @@ -46,7 +46,7 @@ define i16 @foo3(i16 %a, i16 %b, i16 %c, i16 %d) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: in r16, 63 ; CHECK-NEXT: subi r28, 251 ; CHECK-NEXT: sbci r29, 255 @@ -79,7 +79,7 @@ define i32 @foo4(i32 %a, i32 %b) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: in r16, 63 ; CHECK-NEXT: subi r28, 251 ; CHECK-NEXT: sbci r29, 255 @@ -122,7 +122,7 @@ define i8 @foo5([5 x i8] %0, i8 %1) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: mov r26, r28 ; CHECK-NEXT: mov r27, r29 ; CHECK-NEXT: subi r26, 251 @@ -157,7 +157,7 @@ define i8 @foo7([3 x i8] %0, [3 x i8] %1) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: mov r26, r28 ; CHECK-NEXT: mov r27, r29 ; CHECK-NEXT: subi r26, 251 @@ -181,7 +181,7 @@ define i8 @foo8([3 x i8] %0, i8 %1, i8 %2) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: add r22, r20 ; CHECK-NEXT: mov r26, r28 ; CHECK-NEXT: mov r27, r29 @@ -205,7 +205,7 @@ define i8 @foo9([7 x i8] %0) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: mov r26, r28 ; CHECK-NEXT: mov r27, r29 ; CHECK-NEXT: subi r26, 250 @@ -233,7 +233,7 @@ define i8 @fooa([6 x i8] %0, i8 %1, i8 %2) { ; CHECK-NEXT: push r28 ; CHECK-NEXT: push r29 ; CHECK-NEXT: in r28, 61 -; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: clr r29 ; CHECK-NEXT: mov r26, r28 ; CHECK-NEXT: mov r27, r29 ; CHECK-NEXT: subi r26, 251 diff --git a/llvm/test/CodeGen/AVR/pseudo/SPREAD.mir b/llvm/test/CodeGen/AVR/pseudo/SPREAD.mir new file mode 100644 index 000000000000..dfa6358d7667 --- /dev/null +++ b/llvm/test/CodeGen/AVR/pseudo/SPREAD.mir @@ -0,0 +1,28 @@ +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny13 %s -o - \ +# RUN: | FileCheck --check-prefix=NOSPH %s +# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atmega328 %s -o - \ +# RUN: | FileCheck %s + +--- | + target triple = "avr--" + define void @test() { + entry: + ret void + } +... + +--- +name: test +body: | + bb.0.entry: + + ; CHECK-LABEL: test + ; CHECK: $r14 = INRdA 61 + ; CHECK: $r15 = INRdA 62 + + ; NOSPH-LABEL: test + ; NOSPH: $r14 = INRdA 61 + ; NOSPH: $r15 = EORRdRr killed $r15, $r15, implicit-def dead $sreg + + $r15r14 = SPREAD $sp, implicit $sp +... diff --git a/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir b/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir index 4e6f8eb148a2..8be3589b564b 100644 --- a/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir +++ b/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir @@ -40,5 +40,5 @@ body: | ; XMEGA-LABEL: OUTARr 61, $r14 ; XMEGA-LABEL: OUTARr 62, $r15 - $sp = SPWRITE implicit-def $sp, implicit $sp, $r15r14 + $sp = SPWRITE implicit-def $sp, $r15r14, implicit $sp ... diff --git a/llvm/test/CodeGen/AVR/return.ll b/llvm/test/CodeGen/AVR/return.ll index 93dfa257c4b3..455cf75a7159 100644 --- a/llvm/test/CodeGen/AVR/return.ll +++ b/llvm/test/CodeGen/AVR/return.ll @@ -135,7 +135,7 @@ define i32 @return32_arg2(i32 %x, i32 %y, i32 %z) { ; TINY-NEXT: push r28 ; TINY-NEXT: push r29 ; TINY-NEXT: in r28, 61 -; TINY-NEXT: in r29, 62 +; TINY-NEXT: clr r29 ; TINY-NEXT: in r16, 63 ; TINY-NEXT: subi r28, 247 ; TINY-NEXT: sbci r29, 255 @@ -221,7 +221,7 @@ define i64 @return64_arg(i64 %x) { ; TINY-NEXT: push r28 ; TINY-NEXT: push r29 ; TINY-NEXT: in r28, 61 -; TINY-NEXT: in r29, 62 +; TINY-NEXT: clr r29 ; TINY-NEXT: in r16, 63 ; TINY-NEXT: subi r28, 245 ; TINY-NEXT: sbci r29, 255 @@ -314,7 +314,7 @@ define i64 @return64_arg2(i64 %x, i64 %y, i64 %z) { ; TINY-NEXT: push r28 ; TINY-NEXT: push r29 ; TINY-NEXT: in r28, 61 -; TINY-NEXT: in r29, 62 +; TINY-NEXT: clr r29 ; TINY-NEXT: in r16, 63 ; TINY-NEXT: subi r28, 229 ; TINY-NEXT: sbci r29, 255 @@ -403,7 +403,7 @@ define i32 @return64_trunc(i32 %a, i32 %b, i32 %c, i64 %d) { ; TINY-NEXT: push r28 ; TINY-NEXT: push r29 ; TINY-NEXT: in r28, 61 -; TINY-NEXT: in r29, 62 +; TINY-NEXT: clr r29 ; TINY-NEXT: in r16, 63 ; TINY-NEXT: subi r28, 243 ; TINY-NEXT: sbci r29, 255