[llvm] [Xtensa] Fix S32C1I instruction encoding and copyPhysReg. (PR #165174)

Andrei Safronov via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 2 17:57:21 PST 2025


https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/165174

>From 373d80fb8fffea26eedb68ec945a99d7ca306895 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Mon, 27 Oct 2025 00:11:19 +0300
Subject: [PATCH 1/3] [Xtensa] Fix S32C1I instruction encoding and copyPhysReg.

Fix S21C1I instruction encoding.Fix special registers parsing for S32C1I
feature. Fix copyPhysReg function for f32 registers copy.
---
 .../MCTargetDesc/XtensaMCCodeEmitter.cpp      |  2 +-
 .../MCTargetDesc/XtensaMCTargetDesc.cpp       |  2 +-
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp    | 20 ++++++++++++++++---
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index bd4d4ebd2a729..5977a276b1236 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -320,7 +320,7 @@ XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
   case Xtensa::SSIP:
   case Xtensa::LSI:
   case Xtensa::LSIP:
-
+  case Xtensa::S32C1I:
     if (Res & 0x3) {
       report_fatal_error("Unexpected operand value!");
     }
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
index 080a9c0bdd9e0..5feb0838da9e4 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp
@@ -202,7 +202,7 @@ bool Xtensa::checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits,
     return FeatureBits[Xtensa::FeatureWindowed];
   case Xtensa::ATOMCTL:
   case Xtensa::SCOMPARE1:
-    return FeatureBits[Xtensa::FeatureWindowed];
+    return FeatureBits[Xtensa::FeatureS32C1I];
   case Xtensa::NoRegister:
     return false;
   }
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index b0f924f2cd58e..30976be3f33c9 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -114,14 +114,28 @@ void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                                   const DebugLoc &DL, Register DestReg,
                                   Register SrcReg, bool KillSrc,
                                   bool RenamableDest, bool RenamableSrc) const {
-  // The MOV instruction is not present in core ISA,
-  // so use OR instruction.
-  if (Xtensa::ARRegClass.contains(DestReg, SrcReg))
+  unsigned Opcode;
+
+  // when we are copying a phys reg we want the bits for fp
+  if (Xtensa::ARRegClass.contains(DestReg, SrcReg)) {
     BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg)
         .addReg(SrcReg, getKillRegState(KillSrc))
         .addReg(SrcReg, getKillRegState(KillSrc));
+    return;
+  } else if (STI.hasSingleFloat() && Xtensa::FPRRegClass.contains(SrcReg) &&
+             Xtensa::FPRRegClass.contains(DestReg))
+    Opcode = Xtensa::MOV_S;
+  else if (STI.hasSingleFloat() && Xtensa::FPRRegClass.contains(SrcReg) &&
+           Xtensa::ARRegClass.contains(DestReg))
+    Opcode = Xtensa::RFR;
+  else if (STI.hasSingleFloat() && Xtensa::ARRegClass.contains(SrcReg) &&
+           Xtensa::FPRRegClass.contains(DestReg))
+    Opcode = Xtensa::WFR;
   else
     report_fatal_error("Impossible reg-to-reg copy");
+
+  BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
+      .addReg(SrcReg, getKillRegState(KillSrc));
 }
 
 void XtensaInstrInfo::storeRegToStackSlot(

>From cf86faa46043537966e592635e3f58ec8486f69b Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 30 Oct 2025 20:22:00 +0300
Subject: [PATCH 2/3] [Xtensa] Minor fix and added tests.

---
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp |  6 ++++--
 llvm/test/CodeGen/Xtensa/s32c1i.ll         |  7 +++++++
 llvm/test/MC/Xtensa/s32c1i.s               | 13 +++++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/Xtensa/s32c1i.ll
 create mode 100644 llvm/test/MC/Xtensa/s32c1i.s

diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 30976be3f33c9..21da759528532 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -122,8 +122,10 @@ void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
         .addReg(SrcReg, getKillRegState(KillSrc))
         .addReg(SrcReg, getKillRegState(KillSrc));
     return;
-  } else if (STI.hasSingleFloat() && Xtensa::FPRRegClass.contains(SrcReg) &&
-             Xtensa::FPRRegClass.contains(DestReg))
+  }
+
+  if (STI.hasSingleFloat() && Xtensa::FPRRegClass.contains(SrcReg) &&
+      Xtensa::FPRRegClass.contains(DestReg))
     Opcode = Xtensa::MOV_S;
   else if (STI.hasSingleFloat() && Xtensa::FPRRegClass.contains(SrcReg) &&
            Xtensa::ARRegClass.contains(DestReg))
diff --git a/llvm/test/CodeGen/Xtensa/s32c1i.ll b/llvm/test/CodeGen/Xtensa/s32c1i.ll
new file mode 100644
index 0000000000000..aad738abe6a4c
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/s32c1i.ll
@@ -0,0 +1,7 @@
+; RUN: llc -mtriple=xtensa -mattr=+s32c1i  -filetype=obj %s -o - | llvm-objdump --arch=xtensa --mattr=s32c1i -d - | FileCheck %s -check-prefix=XTENSA
+
+define i32 @constraint_i(i32 %a) {
+; XTENSA: 0: 22 e2 01    s32c1i  a2, a2, 4
+  %res = tail call i32 asm "s32c1i $0, $1, $2", "=r,r,i"(i32 %a, i32 4)
+  ret i32 %res
+}
diff --git a/llvm/test/MC/Xtensa/s32c1i.s b/llvm/test/MC/Xtensa/s32c1i.s
new file mode 100644
index 0000000000000..218a86dd56752
--- /dev/null
+++ b/llvm/test/MC/Xtensa/s32c1i.s
@@ -0,0 +1,13 @@
+# RUN: llvm-mc %s -triple=xtensa -show-encoding --mattr=+s32c1i \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-INST %s
+
+.align	4
+LBL0:
+
+# CHECK-INST: xsr a3, atomctl
+# CHECK: # encoding: [0x30,0x63,0x61]
+xsr a3, atomctl
+
+# CHECK-INST: xsr a3, scompare1
+# CHECK: # encoding: [0x30,0x0c,0x61]
+xsr a3, scompare1

>From 51e7b49ea8615cbb7488ecbaa69d7c9e1d157d16 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Mon, 3 Nov 2025 04:50:33 +0300
Subject: [PATCH 3/3] [PATCH] [Xtensa] Fix comment

---
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 21da759528532..be69cefb5b78f 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -116,7 +116,8 @@ void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                                   bool RenamableDest, bool RenamableSrc) const {
   unsigned Opcode;
 
-  // when we are copying a phys reg we want the bits for fp
+  // The MOV instruction is not present in core ISA for AR registers,
+  // so use OR instruction.
   if (Xtensa::ARRegClass.contains(DestReg, SrcReg)) {
     BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg)
         .addReg(SrcReg, getKillRegState(KillSrc))



More information about the llvm-commits mailing list