[llvm] [StructurizeCFG] Fix a crash caused by not updating `Predicates` properly (PR #124051)

Shilei Tian via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 22 19:03:55 PST 2025


https://github.com/shiltian created https://github.com/llvm/llvm-project/pull/124051

A very simple IR could crash the pass at `assert(BB != Parent);`.

```
define void @foo() {
entry:
  br i1 false, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  br label %cond.end

cond.false:                                       ; preds = %entry
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %cond.true
  ret void
}
```

TBH I'm not sure if my fix is right. I don't know why we don't update
`Predicates` after we replace a conditional branch with a branch, given the one
not taken will no longer be a sucessor of the current BB. There are many test
cases need to be updated but I'd like to update them after I fix this properly.
Any help would be appreciated.

>From 8fbba30d42eb58ad17cec03b90f5c79390444ea9 Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Wed, 22 Jan 2025 21:54:29 -0500
Subject: [PATCH] [StructurizeCFG] Fix a crash caused by not updating
 `Predicates` properly

A very simple IR could crash the pass at `assert(BB != Parent);`.

```
define void @foo() {
entry:
  br i1 false, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  br label %cond.end

cond.false:                                       ; preds = %entry
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %cond.true
  ret void
}
```

TBH I'm not sure if my fix is right. I don't know why we don't update
`Predicates` after we replace a conditional branch with a branch, given the one
not taken will no longer be a sucessor of the current BB. There are many test
cases need to be updated but I'd like to update them after I fix this properly.
Any help would be appreciated.
---
 llvm/lib/Transforms/Scalar/StructurizeCFG.cpp |  4 +++
 .../simple-structurizecfg-crash.ll            | 26 +++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 llvm/test/Transforms/StructurizeCFG/simple-structurizecfg-crash.ll

diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
index b1f742b838f2a1..eaeb6ca4f3e04a 100644
--- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
+++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp
@@ -971,6 +971,10 @@ void StructurizeCFG::changeExit(RegionNode *Node, BasicBlock *NewExit,
     SubRegion->replaceExit(NewExit);
   } else {
     BasicBlock *BB = Node->getNodeAs<BasicBlock>();
+    for (BasicBlock *Succ : successors(BB)) {
+      if (Succ != NewExit)
+        Predicates[Succ].erase(BB);
+    }
     killTerminator(BB);
     BranchInst *Br = BranchInst::Create(NewExit, BB);
     Br->setDebugLoc(TermDL[BB]);
diff --git a/llvm/test/Transforms/StructurizeCFG/simple-structurizecfg-crash.ll b/llvm/test/Transforms/StructurizeCFG/simple-structurizecfg-crash.ll
new file mode 100644
index 00000000000000..15983c448588b3
--- /dev/null
+++ b/llvm/test/Transforms/StructurizeCFG/simple-structurizecfg-crash.ll
@@ -0,0 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=structurizecfg %s -o - | FileCheck %s
+
+define void @foo() {
+; CHECK-LABEL: define void @foo() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[COND_FALSE:.*]]
+; CHECK:       [[COND_TRUE:.*]]:
+; CHECK-NEXT:    br label %[[COND_END:.*]]
+; CHECK:       [[COND_FALSE]]:
+; CHECK-NEXT:    br i1 false, label %[[COND_TRUE]], label %[[COND_END]]
+; CHECK:       [[COND_END]]:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br i1 false, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %entry
+  br label %cond.end
+
+cond.false:                                       ; preds = %entry
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %cond.true
+  ret void
+}



More information about the llvm-commits mailing list