[llvm] [SPARC] Prevent generic opcodes from being inserted into delay slots (PR #161111)

via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 3 00:02:05 PDT 2025


https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/161111

>From ab7b98f418b63999e05eb657666514e477fd55ac Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Mon, 29 Sep 2025 08:45:17 +0700
Subject: [PATCH 1/2] [SPARC] Prevent generic opcodes from being inserted into
 delay slots

Do not move instructions with generic opcodes like `FAKE_USE`/`@llvm.fake.use`
into delay slots, as they are not real machine instructions.

This should fix crashes when running `clang -Og`.
---
 llvm/lib/Target/Sparc/DelaySlotFiller.cpp     |  4 +--
 .../CodeGen/SPARC/2011-01-19-DelaySlot.ll     | 26 +++++++++++++++++++
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
index 6c19049a001cf..73d03fc271100 100644
--- a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
+++ b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
@@ -206,8 +206,8 @@ Filler::findDelayInstr(MachineBasicBlock &MBB,
     if (!done)
       --I;
 
-    // skip debug instruction
-    if (I->isDebugInstr())
+    // Skip debug and generic instructions.
+    if (I->isDebugInstr() || (I->getOpcode() <= TargetOpcode::GENERIC_OP_END))
       continue;
 
     if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() ||
diff --git a/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll b/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
index 9ccd4f1c0ac9a..d4b21b248d60d 100644
--- a/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
+++ b/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
@@ -184,4 +184,30 @@ entry:
   ret i32 %2
 }
 
+define i32 @test_generic_inst(i32 %a) #0 {
+;CHECK-LABEL: test_generic_inst:
+;CHECK: ! fake_use: {{.*}}
+;CHECK: bne {{.*}}
+;CHECK-NEXT: nop
+
+%2 = call i32 @bar(i32 %a)
+  %3 = and i32 %2, 1
+  %4 = icmp eq i32 %3, 0
+  ; This shouldn't get reordered into a delay slot
+  call void (...) @llvm.fake.use(i32 %a)
+  br i1 %4, label %5, label %7
+5:
+  %6 = call i32 @bar(i32 %2)
+  br label %9
+
+7:
+  %8 = add nsw i32 %2, 1
+  br label %9
+
+9:
+  %10 = phi i32 [ %6, %5 ], [ %8, %7 ]
+  ret i32 %10
+}
+
+declare void @llvm.fake.use(...)
 attributes #0 = { nounwind "disable-tail-calls"="true" }

>From 43a45db6689d71cabaf0fa7d1fd6c7fcc01883c9 Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Fri, 3 Oct 2025 14:01:09 +0700
Subject: [PATCH 2/2] Apply feedback

---
 llvm/lib/Target/Sparc/DelaySlotFiller.cpp     |  4 +--
 .../CodeGen/SPARC/2011-01-19-DelaySlot.ll     | 35 +++++++++----------
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
index 73d03fc271100..5fdf6ace604ed 100644
--- a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
+++ b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp
@@ -206,8 +206,8 @@ Filler::findDelayInstr(MachineBasicBlock &MBB,
     if (!done)
       --I;
 
-    // Skip debug and generic instructions.
-    if (I->isDebugInstr() || (I->getOpcode() <= TargetOpcode::GENERIC_OP_END))
+    // Skip debug and meta instructions.
+    if (I->isDebugInstr() || I->isMetaInstruction())
       continue;
 
     if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() ||
diff --git a/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll b/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
index d4b21b248d60d..767ef7eb510e6 100644
--- a/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
+++ b/llvm/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
@@ -184,29 +184,28 @@ entry:
   ret i32 %2
 }
 
-define i32 @test_generic_inst(i32 %a) #0 {
+define i32 @test_generic_inst(i32 %arg) #0 {
 ;CHECK-LABEL: test_generic_inst:
 ;CHECK: ! fake_use: {{.*}}
 ;CHECK: bne {{.*}}
 ;CHECK-NEXT: nop
-
-%2 = call i32 @bar(i32 %a)
-  %3 = and i32 %2, 1
-  %4 = icmp eq i32 %3, 0
+  %bar1 = call i32 @bar(i32 %arg)
+  %even = and i32 %bar1, 1
+  %cmp = icmp eq i32 %even, 0
   ; This shouldn't get reordered into a delay slot
-  call void (...) @llvm.fake.use(i32 %a)
-  br i1 %4, label %5, label %7
-5:
-  %6 = call i32 @bar(i32 %2)
-  br label %9
-
-7:
-  %8 = add nsw i32 %2, 1
-  br label %9
-
-9:
-  %10 = phi i32 [ %6, %5 ], [ %8, %7 ]
-  ret i32 %10
+  call void (...) @llvm.fake.use(i32 %arg)
+  br i1 %cmp, label %true, label %false
+true:
+  %bar2 = call i32 @bar(i32 %bar1)
+  br label %cont
+
+false:
+  %inc = add nsw i32 %bar1, 1
+  br label %cont
+
+cont:
+  %ret = phi i32 [ %bar2, %true ], [ %inc, %false ]
+  ret i32 %ret
 }
 
 declare void @llvm.fake.use(...)



More information about the llvm-commits mailing list