Skip to content

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Jun 28, 2024

This patch folds the following pattern (I don't know what to call this):

bb0:
  br i1 %cond1, label %bb1, label %bb2
bb1:
  br i1 %cond2, label %bb3, label %bb4
bb2:
  br i1 %cond2, label %bb4, label %bb3
bb3:
  ...
bb4:
  ...

into

bb0:
  %cond = xor i1 %cond1, %cond2
  br i1 %cond, label %bb4, label %bb3
bb3:
  ...
bb4:
  ...

Alive2: https://alive2.llvm.org/ce/z/5iOJEL
Closes #97022.
Closes #83417.

I found this pattern in some verilator-generated code, which is widely used in RTL simulation. This fold will reduces branches and improves the performance of CPU frontend. To my surprise, this pattern is also common in C/C++ code base.
Affected libraries/applications: cmake/cvc5/freetype/git/gromacs/jq/linux/openblas/openmpi/openssl/php/postgres/ruby/sqlite/wireshark/z3/...

@llvmbot
Copy link
Member

llvmbot commented Jun 28, 2024

@llvm/pr-subscribers-backend-arm

@llvm/pr-subscribers-llvm-transforms

Author: Yingwei Zheng (dtcxzyw)

Changes

This patch folds the following pattern (I don't know what to call this):

bb0:
   br i1 %cond1, label %bb1, label %bb2
bb1:
  br i1 %cond2, label %bb3, label %bb4
bb2:
  br i1 %cond2, label %bb4, label %bb3
bb3:
  ...
bb4:
  ...

into

bb0:
  %cond = xor i1 %cond1, %cond2
  br i1 %cond, label %bb4, label %bb3
bb3:
  ...
bb4:
  ...

Alive2: https://alive2.llvm.org/ce/z/5iOJEL
Closes #97022.

I found this pattern in some verilator-generated code, which is widely used in RTL simulation. This fold will reduces branches and improves the performance of CPU frontend. To my surprise, this pattern is also common in C/C++ code base.
Affected libraries/applications: cmake/cvc5/freetype/git/gromacs/jq/linux/openblas/openmpi/openssl/php/postgres/ruby/sqlite/wireshark/z3/...


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+85)
  • (modified) llvm/test/Transforms/SimplifyCFG/branch-fold.ll (+291)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 6847bb7502429..092ac3d5e5087 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7468,6 +7468,91 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
           if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
             return requestResimplify();
 
+  {
+    // Fold the following pattern:
+    // bb0:
+    //   br i1 %cond1, label %bb1, label %bb2
+    // bb1:
+    //   br i1 %cond2, label %bb3, label %bb4
+    // bb2:
+    //   br i1 %cond2, label %bb4, label %bb3
+    // bb3:
+    //   ...
+    // bb4:
+    //   ...
+    // into
+    // bb0:
+    //   %cond = xor i1 %cond1, %cond2
+    //   br i1 %cond, label %bb4, label %bb3
+    // bb3:
+    //   ...
+    // bb4:
+    //   ...
+    // NOTE: %cond2 always dominates the terminator of bb0.
+
+    BasicBlock *BB1 = BI->getSuccessor(0);
+    BasicBlock *BB2 = BI->getSuccessor(1);
+    auto IsSimpleSuccessor = [BB](BasicBlock *Succ, BranchInst *&SuccBI) {
+      if (Succ == BB)
+        return false;
+      if (Succ->sizeWithoutDebug() > 1)
+        return false;
+      SuccBI = dyn_cast<BranchInst>(Succ->getTerminator());
+      if (!SuccBI || !SuccBI->isConditional())
+        return false;
+      BasicBlock *Succ1 = SuccBI->getSuccessor(0);
+      BasicBlock *Succ2 = SuccBI->getSuccessor(1);
+      return Succ1 != Succ && Succ2 != Succ && Succ1 != BB && Succ2 != BB &&
+             !isa<PHINode>(Succ1->front()) && !isa<PHINode>(Succ2->front());
+    };
+    BranchInst *BB1BI, *BB2BI;
+    if (IsSimpleSuccessor(BB1, BB1BI) && IsSimpleSuccessor(BB2, BB2BI) &&
+        BB1BI->getCondition() == BB2BI->getCondition() &&
+        BB1BI->getSuccessor(0) == BB2BI->getSuccessor(1) &&
+        BB1BI->getSuccessor(1) == BB2BI->getSuccessor(0)) {
+      BasicBlock *BB3 = BB1BI->getSuccessor(0);
+      BasicBlock *BB4 = BB1BI->getSuccessor(1);
+      IRBuilder<> Builder(BI);
+      BI->setCondition(
+          Builder.CreateXor(BI->getCondition(), BB1BI->getCondition()));
+      BB1->removePredecessor(BB);
+      BI->setSuccessor(0, BB4);
+      BB2->removePredecessor(BB);
+      BI->setSuccessor(1, BB3);
+      if (DTU) {
+        SmallVector<DominatorTree::UpdateType, 4> Updates;
+        Updates.push_back({DominatorTree::Delete, BB, BB1});
+        Updates.push_back({DominatorTree::Insert, BB, BB4});
+        Updates.push_back({DominatorTree::Delete, BB, BB2});
+        Updates.push_back({DominatorTree::Insert, BB, BB3});
+
+        DTU->applyUpdates(Updates);
+      }
+      bool HasWeight = false;
+      uint64_t BBTWeight, BBFWeight;
+      if (extractBranchWeights(*BI, BBTWeight, BBFWeight))
+        HasWeight = true;
+      else
+        BBTWeight = BBFWeight = 1;
+      uint64_t BB1TWeight, BB1FWeight;
+      if (extractBranchWeights(*BB1BI, BB1TWeight, BB1FWeight))
+        HasWeight = true;
+      else
+        BB1TWeight = BB1FWeight = 1;
+      uint64_t BB2TWeight, BB2FWeight;
+      if (extractBranchWeights(*BB2BI, BB2TWeight, BB2FWeight))
+        HasWeight = true;
+      else
+        BB2TWeight = BB2FWeight = 1;
+      uint64_t Weights[2] = {BBTWeight * BB1FWeight + BBFWeight * BB2TWeight,
+                             BBTWeight * BB1TWeight + BBFWeight * BB2FWeight};
+      if (HasWeight) {
+        FitWeights(Weights);
+        setBranchWeights(BI, Weights[0], Weights[1], /*IsExpected=*/false);
+      }
+    }
+  }
+
   return false;
 }
 
diff --git a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
index 2f5fb4f33013d..491eb52feafc7 100644
--- a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
+++ b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
@@ -146,3 +146,294 @@ Succ:
 }
 
 declare void @dummy()
+
+define void @fold_nested_branch1(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @fold_nested_branch1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND1:%.*]], [[COND2:%.*]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB4:%.*]], label [[BB3:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define void @fold_nested_branch2(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @fold_nested_branch2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[COMMON_RET:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 [[COND2]], label [[BB4:%.*]], label [[BB3]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb5
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+
+bb5:
+  ret void
+}
+
+define void @fold_nested_branch3(i1 %cond1, i1 %cond2, i1 %cond3) {
+; CHECK-LABEL: @fold_nested_branch3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[BB4]], label [[BB3]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond3, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define void @fold_nested_branch4(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @fold_nested_branch4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 [[COND2]], label [[BB4]], label [[BB3]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  call void @sideeffect1()
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define i32 @fold_nested_branch5(i1 %cond1, i1 %cond2, i32 %x) {
+; CHECK-LABEL: @fold_nested_branch5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[COMMON_RET:%.*]], label [[BB4:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 [[COND2]], label [[BB4]], label [[COMMON_RET]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, [[BB4]] ], [ 0, [[BB1]] ], [ [[X:%.*]], [[BB2]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  %ret = phi i32 [ 0, %bb1 ], [ %x, %bb2 ]
+  ret i32 %ret
+
+bb4:
+  call void @sideeffect2()
+  ret i32 0
+}
+
+define void @fold_nested_branch6(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @fold_nested_branch6(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND1_NOT:%.*]] = xor i1 [[COND1:%.*]], true
+; CHECK-NEXT:    [[BRMERGE:%.*]] = select i1 [[COND1_NOT]], i1 true, i1 [[COND2:%.*]]
+; CHECK-NEXT:    br i1 [[BRMERGE]], label [[BB3:%.*]], label [[BB4:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb1, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define void @fold_nested_branch7(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @fold_nested_branch7(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[BB0:%.*]]
+; CHECK:       bb0:
+; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
+; CHECK:       bb1:
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
+; CHECK:       bb2:
+; CHECK-NEXT:    br i1 [[COND2]], label [[BB0]], label [[BB3]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br label %bb0
+
+bb0:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb0, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+; freq(bb4) = 1 * 4 + 2 * 5 = 14
+; freq(bb3) = 1 * 3 + 2 * 6 = 15
+define void @fold_nested_branch_prof(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @fold_nested_branch_prof(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND1:%.*]], [[COND2:%.*]]
+; CHECK-NEXT:    br i1 [[TMP0]], label [[BB4:%.*]], label [[BB3:%.*]], !prof ![[PROF0:[0-9]+]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       bb3:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
+; CHECK:       bb4:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2, !prof !0 ; 1:2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4, !prof !1 ; 3:4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3, !prof !2 ; 5:6
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+!0 = !{!"branch_weights", i32 1, i32 2}
+!1 = !{!"branch_weights", i32 3, i32 4}
+!2 = !{!"branch_weights", i32 5, i32 6}
+
+;CHECK: ![[PROF0]] = !{!"branch_weights", i32 14, i32 15}
+
+declare void @sideeffect1()
+declare void @sideeffect2()

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Jun 28, 2024
@XChy
Copy link
Member

XChy commented Jun 28, 2024

seem like #83417 ?

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

Looks reasonable, some nits.

@nikic
Copy link
Contributor

nikic commented Jun 28, 2024

There is a test failure in CodeGen/ARM/and-cmp0-sink.ll.

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Jun 29, 2024

seem like #83417 ?

Yeah. @elhewaty Do you have better solutions?

@dtcxzyw dtcxzyw force-pushed the perf/simplify-nested-branch branch from d1debff to f9d7f5f Compare June 29, 2024 09:13
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM

@dtcxzyw dtcxzyw merged commit 4997af9 into llvm:main Jun 30, 2024
@dtcxzyw dtcxzyw deleted the perf/simplify-nested-branch branch June 30, 2024 19:35
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jun 30, 2024

LLVM Buildbot has detected a new failure on builder sanitizer-x86_64-linux running on sanitizer-buildbot1 while building llvm at step 2 "annotate".

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

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

Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/i386-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m32', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-Wthread-safety', '-Wthread-safety-reference', '-Wthread-safety-beta', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 9980 tests, 80 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.
FAIL: libFuzzer-x86_64-static-libcxx-Linux :: reduce_inputs.test (1564 of 9980)
******************** TEST 'libFuzzer-x86_64-static-libcxx-Linux :: reduce_inputs.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 3: rm -rf /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
+ rm -rf /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
RUN: at line 4: mkdir -p /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
+ mkdir -p /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
RUN: at line 5: /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowSimpleTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest
+ /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowSimpleTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest
RUN: at line 6: /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowTest
+ /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowTest
RUN: at line 7: /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest  -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60   -runs=1000000 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C 2>&1 | FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test
+ FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test
+ /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
RUN: at line 11: /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest -runs=0 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C 2>&1 | FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test --check-prefix=COUNT
+ /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest -runs=0 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
+ FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test --check-prefix=COUNT
/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test:12:8: error: COUNT: expected string not found in input
COUNT: seed corpus: files: 4
       ^
<stdin>:1:1: note: scanning from here
INFO: Running with entropic power schedule (0xFF, 100).
^
<stdin>:7:7: note: possible intended match here
INFO: seed corpus: files: 3 min: 2b max: 3b total: 7b rss: 31Mb
      ^

Input file: <stdin>
Check file: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: INFO: Running with entropic power schedule (0xFF, 100). 
check:12'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
Step 9 (test compiler-rt gcc) failure: test compiler-rt gcc (failure)
...
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/i386-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m32', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-Wthread-safety', '-Wthread-safety-reference', '-Wthread-safety-beta', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/lit.common.cfg.py:60: warning: Path reported by clang does not exist: "/b/sanitizer-x86_64-linux/build/build_gcc/lib/clang/19/lib/x86_64-unknown-linux-gnu". This path was found by running ['/b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang', '--target=x86_64-unknown-linux-gnu', '-m64', '-print-runtime-dir'].
llvm-lit: /b/sanitizer-x86_64-linux/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 9980 tests, 80 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.
FAIL: libFuzzer-x86_64-static-libcxx-Linux :: reduce_inputs.test (1564 of 9980)
******************** TEST 'libFuzzer-x86_64-static-libcxx-Linux :: reduce_inputs.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 3: rm -rf /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
+ rm -rf /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
RUN: at line 4: mkdir -p /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
+ mkdir -p /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
RUN: at line 5: /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowSimpleTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest
+ /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowSimpleTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest
RUN: at line 6: /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang    -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta   --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowTest
+ /b/sanitizer-x86_64-linux/build/build_gcc/./bin/clang -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta --driver-mode=g++ -O2 -gline-tables-only -fsanitize=address,fuzzer -I/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/lib/fuzzer -m64 /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/ShrinkControlFlowTest.cpp -o /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowTest
RUN: at line 7: /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest  -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60   -runs=1000000 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C 2>&1 | FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test
+ FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test
+ /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
RUN: at line 11: /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest -runs=0 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C 2>&1 | FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test --check-prefix=COUNT
+ /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp-ShrinkControlFlowSimpleTest -runs=0 /b/sanitizer-x86_64-linux/build/build_gcc/runtimes/runtimes-bins/compiler-rt/test/fuzzer/X86_64StaticLibcxxLinuxConfig/Output/reduce_inputs.test.tmp/C
+ FileCheck /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test --check-prefix=COUNT
/b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test:12:8: error: COUNT: expected string not found in input
COUNT: seed corpus: files: 4
       ^
<stdin>:1:1: note: scanning from here
INFO: Running with entropic power schedule (0xFF, 100).
^
<stdin>:7:7: note: possible intended match here
INFO: seed corpus: files: 3 min: 2b max: 3b total: 7b rss: 31Mb
      ^

Input file: <stdin>
Check file: /b/sanitizer-x86_64-linux/build/llvm-project/compiler-rt/test/fuzzer/reduce_inputs.test

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: INFO: Running with entropic power schedule (0xFF, 100). 
check:12'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found

cpiaseque pushed a commit to cpiaseque/llvm-project that referenced this pull request Jul 3, 2024
This patch folds the following pattern (I don't know what to call this):
```
bb0:
  br i1 %cond1, label %bb1, label %bb2
bb1:
  br i1 %cond2, label %bb3, label %bb4
bb2:
  br i1 %cond2, label %bb4, label %bb3
bb3:
  ...
bb4:
  ...
```
into
```
bb0:
  %cond = xor i1 %cond1, %cond2
  br i1 %cond, label %bb4, label %bb3
bb3:
  ...
bb4:
  ...
```

Alive2: https://alive2.llvm.org/ce/z/5iOJEL
Closes llvm#97022.
Closes llvm#83417.

I found this pattern in some verilator-generated code, which is widely
used in RTL simulation. This fold will reduces branches and improves the
performance of CPU frontend. To my surprise, this pattern is also common
in C/C++ code base.
Affected libraries/applications:
cmake/cvc5/freetype/git/gromacs/jq/linux/openblas/openmpi/openssl/php/postgres/ruby/sqlite/wireshark/z3/...
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.

[SimplifyCFG] Missed optimization with nested branches [SimplifyCFG] Missed optimization: simplify if-else BBs that share common destinations
8 participants