From ab7b98f418b63999e05eb657666514e477fd55ac Mon Sep 17 00:00:00 2001 From: Koakuma Date: Mon, 29 Sep 2025 08:45:17 +0700 Subject: [PATCH 1/3] [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 Date: Fri, 3 Oct 2025 14:01:09 +0700 Subject: [PATCH 2/3] 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(...) From 1b209d80ca996d4a80a5160fa39232a1345d634a Mon Sep 17 00:00:00 2001 From: Koakuma Date: Fri, 3 Oct 2025 14:27:15 +0700 Subject: [PATCH 3/3] Remove redundant debug check --- llvm/lib/Target/Sparc/DelaySlotFiller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/Sparc/DelaySlotFiller.cpp b/llvm/lib/Target/Sparc/DelaySlotFiller.cpp index 5fdf6ace604ed..024030d196ee3 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 meta instructions. - if (I->isDebugInstr() || I->isMetaInstruction()) + // Skip meta instructions. + if (I->isMetaInstruction()) continue; if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isPosition() ||