[llvm] [Sparc] Handle two new cases in the GRLIB-TN-0010 workaround pass (PR #205780)

Daniel Cederman via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 1 00:02:29 PDT 2026


https://github.com/doac updated https://github.com/llvm/llvm-project/pull/205780

>From 23813e1671a01c15951fa877a522cecbc91cc8d6 Mon Sep 17 00:00:00 2001
From: Daniel Cederman <cederman at gaisler.com>
Date: Wed, 24 Jun 2026 11:02:19 +0200
Subject: [PATCH 1/2] [Sparc] Handle two new cases in the GRLIB-TN-0010
 workaround pass

Handle the case of an empty block or an indirect branch.
---
 llvm/lib/Target/Sparc/LeonPasses.cpp |  4 +++-
 llvm/test/CodeGen/SPARC/tn0010.ll    | 23 +++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/SPARC/tn0010.ll

diff --git a/llvm/lib/Target/Sparc/LeonPasses.cpp b/llvm/lib/Target/Sparc/LeonPasses.cpp
index 018d8126f7a7e..73ab19a940f6d 100644
--- a/llvm/lib/Target/Sparc/LeonPasses.cpp
+++ b/llvm/lib/Target/Sparc/LeonPasses.cpp
@@ -155,7 +155,7 @@ bool ErrataWorkaround::checkSeqTN0010(MachineBasicBlock::iterator I) {
     return false;
 
   // Check for branch to atomic instruction with load in delay slot
-  if (I->isBranch()) {
+  if (I->isBranch() && I->getOperand(0).isMBB()) {
     MachineBasicBlock *TargetMBB = I->getOperand(0).getMBB();
     MachineBasicBlock::iterator MI = TargetMBB->begin();
 
@@ -198,6 +198,8 @@ bool ErrataWorkaround::checkSeqTN0010First(MachineBasicBlock &MBB) {
   MachineBasicBlock::iterator I = MBB.begin();
   while (I != MBB.end() && I->isMetaInstruction())
     I++;
+  if (I == MBB.end())
+    return false;
   switch (I->getOpcode()) {
   case SP::SWAPrr:
   case SP::SWAPri:
diff --git a/llvm/test/CodeGen/SPARC/tn0010.ll b/llvm/test/CodeGen/SPARC/tn0010.ll
new file mode 100644
index 0000000000000..ee138845706bb
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/tn0010.ll
@@ -0,0 +1,23 @@
+; RUN: llc < %s -mtriple=sparc -mattr=fix-tn0010 | FileCheck %s
+
+; CHECK-LABEL: empty_bb:
+define i32 @empty_bb() {
+  unreachable
+}
+
+; CHECK-LABEL: simulator_kernel:
+define i32 @simulator_kernel() {
+entry:
+  %v = load i32, ptr null, align 4
+  br label %dispatch
+
+dispatch:
+  br label %indirectgoto
+
+store_block:
+  store i32 %v, ptr null, align 4
+  br label %indirectgoto
+
+indirectgoto:
+  indirectbr ptr null, [label %dispatch, label %store_block]
+}

>From f39d5ca2bfb9e796dba7cb8fd73ccdd1d592b874 Mon Sep 17 00:00:00 2001
From: Daniel Cederman <cederman at gaisler.com>
Date: Wed, 1 Jul 2026 08:32:26 +0200
Subject: [PATCH 2/2] [Sparc] Update with ldstuba and new isAtomic function

Extend tests and add more assertions
---
 llvm/lib/Target/Sparc/LeonPasses.cpp | 38 ++++++++++++----------------
 llvm/lib/Target/Sparc/LeonPasses.h   |  1 +
 llvm/test/CodeGen/SPARC/tn0010.ll    | 17 +++++++++++++
 llvm/test/CodeGen/SPARC/tn0010.mir   | 15 +++++++++++
 4 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/Sparc/LeonPasses.cpp b/llvm/lib/Target/Sparc/LeonPasses.cpp
index 73ab19a940f6d..e1b7d22bfd483 100644
--- a/llvm/lib/Target/Sparc/LeonPasses.cpp
+++ b/llvm/lib/Target/Sparc/LeonPasses.cpp
@@ -79,6 +79,19 @@ bool ErrataWorkaround::isDivSqrt(MachineBasicBlock::iterator I) {
   return false;
 }
 
+bool ErrataWorkaround::isAtomic(MachineBasicBlock::iterator I) {
+  switch (I->getOpcode()) {
+  case SP::SWAPrr:
+  case SP::SWAPri:
+  case SP::CASArr:
+  case SP::LDSTUBrr:
+  case SP::LDSTUBri:
+  case SP::LDSTUBArr:
+    return true;
+  }
+  return false;
+}
+
 // Prevents the following code sequence from being generated:
 // (stb/sth/st/stf) -> (single non-store/load instruction) -> (any store)
 // If the sequence is detected a NOP instruction is inserted after
@@ -165,15 +178,8 @@ bool ErrataWorkaround::checkSeqTN0010(MachineBasicBlock::iterator I) {
     if (MI == TargetMBB->end())
       return false;
 
-    switch (MI->getOpcode()) {
-    case SP::SWAPrr:
-    case SP::SWAPri:
-    case SP::CASArr:
+    if (isAtomic(MI))
       insertNop(MI);
-      break;
-    default:
-      break;
-    }
   }
 
   // Check for load followed by atomic instruction
@@ -181,14 +187,8 @@ bool ErrataWorkaround::checkSeqTN0010(MachineBasicBlock::iterator I) {
   if (!moveNext(MI))
     return false;
 
-  switch (MI->getOpcode()) {
-  case SP::SWAPrr:
-  case SP::SWAPri:
-  case SP::CASArr:
-    break;
-  default:
+  if (!isAtomic(MI))
     return false;
-  }
   insertNop(MI);
   return true;
 }
@@ -200,14 +200,8 @@ bool ErrataWorkaround::checkSeqTN0010First(MachineBasicBlock &MBB) {
     I++;
   if (I == MBB.end())
     return false;
-  switch (I->getOpcode()) {
-  case SP::SWAPrr:
-  case SP::SWAPri:
-  case SP::CASArr:
-    break;
-  default:
+  if (!isAtomic(I))
     return false;
-  }
   insertNop(I);
   return true;
 }
diff --git a/llvm/lib/Target/Sparc/LeonPasses.h b/llvm/lib/Target/Sparc/LeonPasses.h
index 261b283fadaeb..32271b30420ee 100644
--- a/llvm/lib/Target/Sparc/LeonPasses.h
+++ b/llvm/lib/Target/Sparc/LeonPasses.h
@@ -53,6 +53,7 @@ class LLVM_LIBRARY_VISIBILITY ErrataWorkaround : public MachineFunctionPass {
   bool moveNext(MachineBasicBlock::iterator &I);
   bool isFloat(MachineBasicBlock::iterator I);
   bool isDivSqrt(MachineBasicBlock::iterator I);
+  bool isAtomic(MachineBasicBlock::iterator I);
   void insertNop(MachineBasicBlock::iterator I);
 
 public:
diff --git a/llvm/test/CodeGen/SPARC/tn0010.ll b/llvm/test/CodeGen/SPARC/tn0010.ll
index ee138845706bb..5fe9dd495a5dd 100644
--- a/llvm/test/CodeGen/SPARC/tn0010.ll
+++ b/llvm/test/CodeGen/SPARC/tn0010.ll
@@ -1,12 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc < %s -mtriple=sparc -mattr=fix-tn0010 | FileCheck %s
 
 ; CHECK-LABEL: empty_bb:
 define i32 @empty_bb() {
+; CHECK-LABEL: empty_bb:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ! %bb.0:
   unreachable
 }
 
 ; CHECK-LABEL: simulator_kernel:
 define i32 @simulator_kernel() {
+; CHECK-LABEL: simulator_kernel:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  ! %bb.0: ! %entry
+; CHECK-NEXT:    jmp %g0
+; CHECK-NEXT:    ld [%g0], %o0
+; CHECK-NEXT:  .LBB1_1: ! %dispatch
+; CHECK-NEXT:    ! =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    jmp %g0
+; CHECK-NEXT:    nop
+; CHECK-NEXT:  .LBB1_2: ! %store_block
+; CHECK-NEXT:    ! =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    jmp %g0
+; CHECK-NEXT:    st %o0, [%g0]
 entry:
   %v = load i32, ptr null, align 4
   br label %dispatch
diff --git a/llvm/test/CodeGen/SPARC/tn0010.mir b/llvm/test/CodeGen/SPARC/tn0010.mir
index 5792c7ce244f2..bc7f4e1e72d83 100644
--- a/llvm/test/CodeGen/SPARC/tn0010.mir
+++ b/llvm/test/CodeGen/SPARC/tn0010.mir
@@ -11,6 +11,15 @@
 # CHECK:      LDrr
 # CHECK-NEXT: NOP
 # CHECK-NEXT: SWAPri
+# CHECK:      LDrr
+# CHECK-NEXT: NOP
+# CHECK-NEXT: LDSTUBrr
+# CHECK:      LDrr
+# CHECK-NEXT: NOP
+# CHECK-NEXT: LDSTUBri
+# CHECK:      LDrr
+# CHECK-NEXT: NOP
+# CHECK-NEXT: LDSTUBArr
 name:            er-5-1
 registers:
   - { id: 0, class: intregs }
@@ -22,6 +31,12 @@ body:             |
     %0 = SWAPrr $o2, $o3, %0
     %0 = LDrr $g0, $o0
     %0 = SWAPri $o2, 10, %0
+    %0 = LDrr $g0, $o0
+    %0 = LDSTUBrr $o2, 10, %0, 10
+    %0 = LDrr $g0, $o0
+    %0 = LDSTUBri $o2, 10, %0, 10
+    %0 = LDrr $g0, $o0
+    %0 = LDSTUBArr $o2, 10, %0, 10
 
 ---
 # CHECK:      bb.2:



More information about the llvm-commits mailing list