[libc-commits] [libc] d723ad9 - [libc][stdlib] Optimize bsearch() by reordering comparison branches (#230823)

via libc-commits libc-commits at lists.llvm.org
Tue Oct 13 00:56:23 PDT 2026


Author: Kuan-Wei Chiu
Date: 2026-10-13T08:56:18+01:00
New Revision: d723ad9b4f45be448cd4d55ede39573bef3a279d

URL: https://github.com/llvm/llvm-project/commit/d723ad9b4f45be448cd4d55ede39573bef3a279d
DIFF: https://github.com/llvm/llvm-project/commit/d723ad9b4f45be448cd4d55ede39573bef3a279d.diff

LOG: [libc][stdlib] Optimize bsearch() by reordering comparison branches (#230823)

During a binary search, compare_result == 0 is triggered at most once,
or 0 times when the key is not found, whereas compare_result < 0 and
compare_result > 0 are triggered multiple times across loop iterations.
Check < 0 and > 0 before the equality case so the loop does not test for
== 0 first on every iteration.

With clang -O2, the loop body changes as follows:

x86-64:
```diff
        movq    %rbp, %rsi
        callq   *(%rsp)
        testl   %eax, %eax
-       je      .LBB0_7
        js      .LBB0_5
+       je      .LBB0_7
        notq    %r13
        addq    %rbx, %r13
        addq    %r14, %rbp
```

riscv64:
```diff
        mv      a0, s3
        mv      a1, s6
        jalr    s2
-       beqz    a0, .LBB0_10
        bltz    a0, .LBB0_5
+       beqz    a0, .LBB0_10
        not     s0, s0
        add     s0, s0, s1
        add     s5, s6, s4
```

The generated code now branches on < 0 first, then checks == 0 to exit,
and falls through to the > 0 update.

Added: 
    

Modified: 
    libc/src/stdlib/bsearch.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/stdlib/bsearch.cpp b/libc/src/stdlib/bsearch.cpp
index f0848051173ef..7e76f3112bfc2 100644
--- a/libc/src/stdlib/bsearch.cpp
+++ b/libc/src/stdlib/bsearch.cpp
@@ -26,19 +26,18 @@ LLVM_LIBC_FUNCTION(void *, bsearch,
     const void *elem =
         reinterpret_cast<const uint8_t *>(array) + mid * elem_size;
     int compare_result = compare(key, elem);
-    if (compare_result == 0)
-      return const_cast<void *>(elem);
-
     if (compare_result < 0) {
       // This means that key is less than the element at |mid|.
       // So, in the next iteration, we only compare elements less
       // than mid.
       array_size = mid;
-    } else {
+    } else if (compare_result > 0) {
       // |mid| is strictly less than |array_size|. So, the below
       // decrement in |array_size| will not lead to a wrap around.
       array_size -= (mid + 1);
       array = reinterpret_cast<const uint8_t *>(elem) + elem_size;
+    } else {
+      return const_cast<void *>(elem);
     }
   }
 


        


More information about the libc-commits mailing list