[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