[llvm] 60b168c - [AVR] Simplify SPWRITE on XMEGA (#147210)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 13 18:40:40 PDT 2025


Author: Tom Vijlbrief
Date: 2025-07-14T09:40:37+08:00
New Revision: 60b168c1469730a6db915d0ece38bc9088e2034b

URL: https://github.com/llvm/llvm-project/commit/60b168c1469730a6db915d0ece38bc9088e2034b
DIFF: https://github.com/llvm/llvm-project/commit/60b168c1469730a6db915d0ece38bc9088e2034b.diff

LOG: [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.
```

Added: 
    llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir

Modified: 
    llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 440d852fa4bc8..90505aa82aa46 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -2531,27 +2531,47 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
   unsigned Flags = MI.getFlags();
   TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
 
-  buildMI(MBB, MBBI, AVR::INRdA)
-      .addReg(STI.getTmpRegister(), RegState::Define)
-      .addImm(STI.getIORegSREG())
-      .setMIFlags(Flags);
-
-  buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
-
-  buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(0x3e)
-      .addReg(SrcHiReg, getKillRegState(SrcIsKill))
-      .setMIFlags(Flags);
+  // From the XMEGA series manual:
+  // 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.
+  if (STI.getELFArch() >= 102) { // An XMEGA device
+
+    buildMI(MBB, MBBI, AVR::OUTARr)
+        .addImm(STI.getIORegSPL())
+        .addReg(SrcLoReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
+
+    buildMI(MBB, MBBI, AVR::OUTARr)
+        .addImm(STI.getIORegSPH())
+        .addReg(SrcHiReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
+
+  } else { // Disable interrupts for older devices (3 extra instructions)
+
+    buildMI(MBB, MBBI, AVR::INRdA)
+        .addReg(STI.getTmpRegister(), RegState::Define)
+        .addImm(STI.getIORegSREG())
+        .setMIFlags(Flags);
+
+    buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
+
+    if (STI.getIORegSPH() != -1)
+      buildMI(MBB, MBBI, AVR::OUTARr)
+          .addImm(STI.getIORegSPH())
+          .addReg(SrcHiReg, getKillRegState(SrcIsKill))
+          .setMIFlags(Flags);
 
-  buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(STI.getIORegSREG())
-      .addReg(STI.getTmpRegister(), RegState::Kill)
-      .setMIFlags(Flags);
+    buildMI(MBB, MBBI, AVR::OUTARr)
+        .addImm(STI.getIORegSREG())
+        .addReg(STI.getTmpRegister(), RegState::Kill)
+        .setMIFlags(Flags);
 
-  buildMI(MBB, MBBI, AVR::OUTARr)
-      .addImm(0x3d)
-      .addReg(SrcLoReg, getKillRegState(SrcIsKill))
-      .setMIFlags(Flags);
+    buildMI(MBB, MBBI, AVR::OUTARr)
+        .addImm(STI.getIORegSPL())
+        .addReg(SrcLoReg, getKillRegState(SrcIsKill))
+        .setMIFlags(Flags);
+  }
 
   MI.eraseFromParent();
   return true;

diff  --git a/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir b/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir
new file mode 100644
index 0000000000000..ed6e39c641b11
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/pseudo/SPWRITE.mir
@@ -0,0 +1,47 @@
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny11 %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
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny817 %s -o - \
+# RUN:     | FileCheck --check-prefix=XMEGA %s
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega64a1 %s -o - \
+# RUN:     | FileCheck --check-prefix=XMEGA %s
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=atxmega256a3u %s -o - \
+# RUN:     | FileCheck --check-prefix=XMEGA %s
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=attiny1614 %s -o - \
+# RUN:     | FileCheck --check-prefix=XMEGA %s
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mtriple=avr -mcpu=avr128db28 %s -o - \
+# RUN:     | FileCheck --check-prefix=XMEGA %s
+
+--- |
+  target triple = "avr--"
+  define void @test() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test
+body: |
+  bb.0.entry:
+
+    ; CHECK-LABEL: test
+    ; CHECK:       $r0 = INRdA 63
+    ; CHECK:       BCLRs 7, implicit-def $sreg
+    ; CHECK:       OUTARr 62, $r15
+    ; CHECK:       OUTARr 63, killed $r0
+    ; CHECK:       OUTARr 61, $r14
+
+    ; NOSPH-LABEL: test
+    ; NOSPH:       $r0 = INRdA 63
+    ; NOSPH:       BCLRs 7, implicit-def $sreg
+    ; NOSPH:       OUTARr 63, killed $r0
+    ; NOSPH:       OUTARr 61, $r14
+
+    ; XMEGA-LABEL: test
+    ; XMEGA-LABEL: OUTARr 61, $r14
+    ; XMEGA-LABEL: OUTARr 62, $r15
+
+    $sp = SPWRITE implicit-def $sp, implicit $sp, $r15r14
+...


        


More information about the llvm-commits mailing list