[AVR] Improve expansion of pseudo instruction SPREAD (#186780)

It would be better to set the higher register to zero for devices
without `SPH`.
This commit is contained in:
Ben Shi 2026-03-17 04:24:20 +08:00 committed by GitHub
parent 81841b722b
commit 297d52ba7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 58 additions and 24 deletions

View File

@ -2496,26 +2496,36 @@ template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
template <>
bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
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<AVR::SPWRITE>(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<AVR::SPWRITE>(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())

View File

@ -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

View File

@ -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
...

View File

@ -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
...

View File

@ -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