Skip to content

[BranchFolding] Fix assertion failure in HoistCommonCodeInSuccs #141028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 22, 2025

Conversation

OCHyams
Copy link
Contributor

@OCHyams OCHyams commented May 22, 2025

Assertion failure introduced in #140063, which didn't account for TBB and FBB being the same block.

Assertion failure introduced in llvm#140063, which didn't account for TBB and FBB
being the same block.
@llvmbot
Copy link
Member

llvmbot commented May 22, 2025

@llvm/pr-subscribers-backend-arm

Author: Orlando Cazalet-Hyams (OCHyams)

Changes

Assertion failure introduced in #140063, which didn't account for TBB and FBB being the same block.


Full diff: https://github.com/llvm/llvm-project/pull/141028.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/BranchFolding.cpp (+6-4)
  • (added) llvm/test/CodeGen/ARM/branch-folder-single-bb-crash.mir (+80)
diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp
index d10e6722f4548..41e66bb82650e 100644
--- a/llvm/lib/CodeGen/BranchFolding.cpp
+++ b/llvm/lib/CodeGen/BranchFolding.cpp
@@ -2072,9 +2072,11 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
     return false;
 
   // Hoist the instructions from [T.begin, TIB) and then delete [F.begin, FIB).
-  // Merge the debug locations. FIXME: We should do something with the
-  // debug instructions too (from BOTH branches).
-  {
+  // If we're hoisting from a single block then just splice. Else step through
+  // and merge the debug locations.
+  if (TBB == FBB) {
+    MBB->splice(Loc, TBB, TBB->begin(), TIB);
+  } else {
     // TIB and FIB point to the end of the regions to hoist/merge in TBB and
     // FBB.
     MachineBasicBlock::iterator FE = FIB;
@@ -2083,7 +2085,7 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
          make_early_inc_range(make_range(TBB->begin(), TIB))) {
       // Move debug instructions and pseudo probes without modifying them.
       // FIXME: This is the wrong thing to do for debug locations, which
-      // should at least be killed.
+      // should at least be killed (and hoisted from BOTH blocks).
       if (TI->isDebugOrPseudoInstr()) {
         TI->moveBefore(&*Loc);
         continue;
diff --git a/llvm/test/CodeGen/ARM/branch-folder-single-bb-crash.mir b/llvm/test/CodeGen/ARM/branch-folder-single-bb-crash.mir
new file mode 100644
index 0000000000000..56bcd3d73d616
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/branch-folder-single-bb-crash.mir
@@ -0,0 +1,80 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=armv7-apple-ios --run-pass=branch-folder %s -o - | FileCheck %s
+
+## Don't crash in branch-folder's HoistCommonCodeInSuccs when TBB and FBB are
+## the same block.
+
+...
+---
+name:            f_1418_2054
+tracksRegLiveness: true
+noPhis:          true
+isSSA:           false
+noVRegs:         true
+body:             |
+  ; CHECK-LABEL: name: f_1418_2054
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $r0 = MOVr undef $r0, 14 /* CC::al */, $noreg, $noreg
+  ; CHECK-NEXT:   Bcc %bb.1, 1 /* CC::ne */, undef $cpsr
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.3(0x40000000), %bb.4(0x40000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $r0 = MOVr undef $r0, 14 /* CC::al */, $noreg, $noreg
+  ; CHECK-NEXT:   Bcc %bb.4, 1 /* CC::ne */, undef $cpsr
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   BX_RET 14 /* CC::al */, $noreg
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4:
+  ; CHECK-NEXT:   TRAP
+  bb.0:
+    successors: %bb.1
+
+  bb.1:
+    successors: %bb.3, %bb.2
+
+    Bcc %bb.3, 1, undef $cpsr
+    B %bb.2
+
+  bb.2:
+    successors: %bb.5, %bb.6
+
+    Bcc %bb.5, 1, undef $cpsr
+    B %bb.6
+
+  bb.3:
+    successors: %bb.4
+
+    $r0 = MOVr undef $r0, 14, $noreg, $noreg
+
+  bb.4:
+    successors: %bb.1
+
+    B %bb.1
+
+  bb.5:
+    successors: %bb.6
+
+  bb.6:
+    successors: %bb.8, %bb.7
+
+    $r0 = MOVr undef $r0, 14, $noreg, $noreg
+    $r0 = MOVr undef $r0, 14, $noreg, $noreg
+
+    Bcc %bb.7, 1, undef $cpsr
+    B %bb.8
+
+  bb.7:
+    successors:
+
+    TRAP
+
+  bb.8:
+    BX_RET 14, _
+...

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good; however I'm not familiar with ARM assembly for the test, @mikaelholmen would you be able to confirm the output is alright?

@mikaelholmen
Copy link
Collaborator

Looks good; however I'm not familiar with ARM assembly for the test, @mikaelholmen would you be able to confirm the output is alright?

I've no idea about ARM either, but I can confirm that the patch fixes the crash I saw for our downstream target.

The ARM reproducer was just something I crafted from a minimal mir-reproducer for our target to have an in-tree reproducer for the crash.

@OCHyams
Copy link
Contributor Author

OCHyams commented May 22, 2025

Also cannot interpret the ARM very well. I just grabbed the reproducer from @mikaelholmen :D I can try to find an x86 reproducer that we can all read if needed but the test is just there to detect a crash regression quickly more than anything. (Thanks again for the reproducer)

Copy link
Member

@jmorse jmorse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/me squints -- I think it's merging the load-to-r0 from bb.3 and bb.6 into bb.1, and leaving the second load-to-r0 in bb.6. It also simplifies away the self-loop into being a single-block-self-loop. This seems alright. It should be fine to land, but @OCHyams could you confirm that it produces the same output as before #140063 before landing?

Comment on lines 4 to 5
## Don't crash in branch-folder's HoistCommonCodeInSuccs when TBB and FBB are
## the same block.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment needs to be detached from the implementation details and made broader -- "We hoist code from successor blocks, and in abnormal circumstances we can have control flow that branches to the same block -- test that we handle this correctly". Or something.

@OCHyams
Copy link
Contributor Author

OCHyams commented May 22, 2025

/me squints -- I think it's merging the load-to-r0 from bb.3 and bb.6 into bb.1, and leaving the second load-to-r0 in bb.6. It also simplifies away the self-loop into being a single-block-self-loop. This seems alright. It should be fine to land, but @OCHyams could you confirm that it produces the same output as before #140063 before landing?

Confirmed that the output is the same before as before #140063. For additional confidence, you can see the splice I've added here is just a copy+paste of the one removed in #140063.

I've improved the test comment.

@OCHyams OCHyams merged commit 34a55c9 into llvm:main May 22, 2025
6 of 10 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 22, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/22936

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/interactive_crashlog_invalid_target.test (2945 of 2956)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/bindings.test (2946 of 2956)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/fail_breakpoint_oneline.test (2947 of 2956)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/nested_sessions.test (2948 of 2956)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/no-args.test (2949 of 2956)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/json.test (2950 of 2956)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/breakpoint_callback.test (2951 of 2956)
PASS: lldb-api :: api/multithreaded/TestMultithreaded.py (2952 of 2956)
PASS: lldb-api :: terminal/TestEditlineCompletions.py (2953 of 2956)
UNRESOLVED: lldb-api :: tools/lldb-dap/launch/TestDAP_launch.py (2954 of 2956)
******************** TEST 'lldb-api :: tools/lldb-dap/launch/TestDAP_launch.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/launch -p TestDAP_launch.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 34a55c937673c67e634e018af40c0c569c5a2b79)
  clang revision 34a55c937673c67e634e018af40c0c569c5a2b79
  llvm revision 34a55c937673c67e634e018af40c0c569c5a2b79
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/launch
runCmd: settings clear --all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 

runCmd: settings set target.auto-apply-fixits false

@OCHyams
Copy link
Contributor Author

OCHyams commented May 22, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/22936

Here is the relevant piece of the build log for the reference

Seems like a flaky test (prev and next are green)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants