[llvm] [AVR] No cli for SPWRITE on XMEGA (PR #147210)
Tom Vijlbrief via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 6 12:48:34 PDT 2025
https://github.com/tomtor created https://github.com/llvm/llvm-project/pull/147210
>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.
This will save 6! instructions in every function with an FP on ALL Xmega devices and it
is compatible with gcc code generation for all those devices. It is also not very modern, because the first devices are from 2013. So this is really significant and it is a small change.
@benshi001 Note that I could not find any existing (SPWRITE) unit tests to which this variant could be added.
>From a0088b4bd3ccd93c0eeae9cbfdf355dea825d22c Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Sun, 6 Jul 2025 21:34:20 +0200
Subject: [PATCH] [AVR] No cli for SPWRITE on XMEGA
---
llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp | 25 ++++++++++++++++----
1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
index 440d852fa4bc8..1c00010c76ff8 100644
--- a/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -2531,27 +2531,42 @@ bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
unsigned Flags = MI.getFlags();
TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
- buildMI(MBB, MBBI, AVR::INRdA)
+ // 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(0x3d)
+ .addReg(SrcLoReg, getKillRegState(SrcIsKill))
+ .setMIFlags(Flags);
+ buildMI(MBB, MBBI, AVR::OUTARr)
+ .addImm(0x3e)
+ .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);
+ buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
- buildMI(MBB, MBBI, AVR::OUTARr)
+ buildMI(MBB, MBBI, AVR::OUTARr)
.addImm(0x3e)
.addReg(SrcHiReg, getKillRegState(SrcIsKill))
.setMIFlags(Flags);
- buildMI(MBB, MBBI, AVR::OUTARr)
+ buildMI(MBB, MBBI, AVR::OUTARr)
.addImm(STI.getIORegSREG())
.addReg(STI.getTmpRegister(), RegState::Kill)
.setMIFlags(Flags);
- buildMI(MBB, MBBI, AVR::OUTARr)
+ buildMI(MBB, MBBI, AVR::OUTARr)
.addImm(0x3d)
.addReg(SrcLoReg, getKillRegState(SrcIsKill))
.setMIFlags(Flags);
+ }
MI.eraseFromParent();
return true;
More information about the llvm-commits
mailing list