Skip to content

Commit 60b168c

Browse files
authored
[AVR] Simplify SPWRITE on XMEGA (#147210)
It is unnecessary to disable/restore interrupt when writing to the SPH/SPL pair on XMEGA devices, as the manual indicates: ``` To prevent corruption when updating the stack pointer from software, a write to SPL will automatically disable interrupts for up to four instructions or until the next I/O memory write. ```
1 parent 2886d30 commit 60b168c

File tree

2 files changed

+86
-19
lines changed

2 files changed

+86
-19
lines changed

llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,27 +2531,47 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
25312531
unsigned Flags = MI.getFlags();
25322532
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
25332533

2534-
buildMI(MBB, MBBI, AVR::INRdA)
2535-
.addReg(STI.getTmpRegister(), RegState::Define)
2536-
.addImm(STI.getIORegSREG())
2537-
.setMIFlags(Flags);
2538-
2539-
buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
2540-
2541-
buildMI(MBB, MBBI, AVR::OUTARr)
2542-
.addImm(0x3e)
2543-
.addReg(SrcHiReg, getKillRegState(SrcIsKill))
2544-
.setMIFlags(Flags);
2534+
// From the XMEGA series manual:
2535+
// To prevent corruption when updating the stack pointer from software,
2536+
// a write to SPL will automatically disable interrupts
2537+
// for up to four instructions or until the next I/O memory write.
2538+
if (STI.getELFArch() >= 102) { // An XMEGA device
2539+
2540+
buildMI(MBB, MBBI, AVR::OUTARr)
2541+
.addImm(STI.getIORegSPL())
2542+
.addReg(SrcLoReg, getKillRegState(SrcIsKill))
2543+
.setMIFlags(Flags);
2544+
2545+
buildMI(MBB, MBBI, AVR::OUTARr)
2546+
.addImm(STI.getIORegSPH())
2547+
.addReg(SrcHiReg, getKillRegState(SrcIsKill))
2548+
.setMIFlags(Flags);
2549+
2550+
} else { // Disable interrupts for older devices (3 extra instructions)
2551+
2552+
buildMI(MBB, MBBI, AVR::INRdA)
2553+
.addReg(STI.getTmpRegister(), RegState::Define)
2554+
.addImm(STI.getIORegSREG())
2555+
.setMIFlags(Flags);
2556+
2557+
buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
2558+
2559+
if (STI.getIORegSPH() != -1)
2560+
buildMI(MBB, MBBI, AVR::OUTARr)
2561+
.addImm(STI.getIORegSPH())
2562+
.addReg(SrcHiReg, getKillRegState(SrcIsKill))
2563+
.setMIFlags(Flags);
25452564

2546-
buildMI(MBB, MBBI, AVR::OUTARr)
2547-
.addImm(STI.getIORegSREG())
2548-
.addReg(STI.getTmpRegister(), RegState::Kill)
2549-
.setMIFlags(Flags);
2565+
buildMI(MBB, MBBI, AVR::OUTARr)
2566+
.addImm(STI.getIORegSREG())
2567+
.addReg(STI.getTmpRegister(), RegState::Kill)
2568+
.setMIFlags(Flags);
25502569

2551-
buildMI(MBB, MBBI, AVR::OUTARr)
2552-
.addImm(0x3d)
2553-
.addReg(SrcLoReg, getKillRegState(SrcIsKill))
2554-
.setMIFlags(Flags);
2570+
buildMI(MBB, MBBI, AVR::OUTARr)
2571+
.addImm(STI.getIORegSPL())
2572+
.addReg(SrcLoReg, getKillRegState(SrcIsKill))
2573+
.setMIFlags(Flags);
2574+
}
25552575

25562576
MI.eraseFromParent();
25572577
return true;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny11 %s -o - \
2+
# RUN: | FileCheck --check-prefix=NOSPH %s
3+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atmega328 %s -o - \
4+
# RUN: | FileCheck %s
5+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny817 %s -o - \
6+
# RUN: | FileCheck --check-prefix=XMEGA %s
7+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega64a1 %s -o - \
8+
# RUN: | FileCheck --check-prefix=XMEGA %s
9+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega256a3u %s -o - \
10+
# RUN: | FileCheck --check-prefix=XMEGA %s
11+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny1614 %s -o - \
12+
# RUN: | FileCheck --check-prefix=XMEGA %s
13+
# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=avr128db28 %s -o - \
14+
# RUN: | FileCheck --check-prefix=XMEGA %s
15+
16+
--- |
17+
target triple = "avr--"
18+
define void @test() {
19+
entry:
20+
ret void
21+
}
22+
...
23+
24+
---
25+
name: test
26+
body: |
27+
bb.0.entry:
28+
29+
; CHECK-LABEL: test
30+
; CHECK: $r0 = INRdA 63
31+
; CHECK: BCLRs 7, implicit-def $sreg
32+
; CHECK: OUTARr 62, $r15
33+
; CHECK: OUTARr 63, killed $r0
34+
; CHECK: OUTARr 61, $r14
35+
36+
; NOSPH-LABEL: test
37+
; NOSPH: $r0 = INRdA 63
38+
; NOSPH: BCLRs 7, implicit-def $sreg
39+
; NOSPH: OUTARr 63, killed $r0
40+
; NOSPH: OUTARr 61, $r14
41+
42+
; XMEGA-LABEL: test
43+
; XMEGA-LABEL: OUTARr 61, $r14
44+
; XMEGA-LABEL: OUTARr 62, $r15
45+
46+
$sp = SPWRITE implicit-def $sp, implicit $sp, $r15r14
47+
...

0 commit comments

Comments
 (0)