[llvm-branch-commits] [compiler-rt] [compiler-rt][ARM] Optimized single-precision FP comparisons (PR #179925)

Saleem Abdulrasool via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Feb 24 12:57:07 PST 2026


================
@@ -0,0 +1,193 @@
+//===-- fcmp.h - shared code for single-precision FP comparison functions -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This code is the skeleton of a double-precision FP compare, with two details
+// left out: which input value is in which register, and how to make the return
+// value. It allows the main comparison logic to be shared between (for
+// example) __lesf2 and __gesf2, varying only those details.
+//
+//===----------------------------------------------------------------------===//
+
+// How to use this header file:
+//
+// This header file is expected to be #included from inside a function
+// definition in a .S file. The source file including this header should
+// provide the following:
+//
+// op0 and op1: register aliases (via .req) for the registers containing the
+// input operands.
+//  - For most comparisons, op0 will correspond to r0 and op1 to r1.
+//  - But a function with the reversed semantics of __aeabi_cfrcmple wil define
+//    them the other way round.
+//
+// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up
+// an appropriate return value in r0, for the cases that do *not* involve NaN.
+//  - On entry to this macro, the condition codes LO, EQ and HI indicate that
+//    op0 < op1, op0 == op1 or op0 > op1 respectively.
+//  - For functions that return a result in the flags, this macro can be empty,
+//    because those are the correct flags to return anyway.
+//  - Functions that return a boolean in r0 should set it up by checking the
+//    flags.
+//
+// LOCAL_LABEL(NaN): a label defined within the compare function, after the
+// #include of this header. Called when at least one input is a NaN, and sets
+// up the appropriate return value for that case.
+
+// --------------------------------------------------
+// The actual entry point of the compare function.
+//
+// The basic plan is to start by ORing together the two inputs. This tells us
+// two things:
+//  - the top bit of the output tells us whether both inputs are positive, or
+//    whether at least one is negative
+//  - if the 8 exponent bits of the output are not all 1, then there are
+//    definitely no NaNs, so a fast path can handle most non-NaN cases.
+
+// clang-format off
+
+  // Set up the constant 1 << 23 in a register, which we'll need on all
+  // branches.
+  movs    r3, #1
+  lsls    r3, r3, #23
+
+  // Diverge control for the negative-numbers case.
+  movs    r2, op0
+  orrs    r2, r2, op1
+  bmi     LOCAL_LABEL(negative)         // high bit set => at least one negative input
+
+  // Here, both inputs are positive. Try adding 1<<23 to their bitwise OR in
+  // r2. This will carry all the way into the top bit, setting the N flag, if
+  // all 8 exponent bits were set.
+  cmn     r2, r3
+  bmi     LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs
+
+  // The fastest fast path: both inputs positive and we could easily tell there
+  // were no NaNs. So we just compare op0 and op1 as unsigned integers.
+  cmp     op0, op1
+  SetReturnRegister
+  bx      lr
----------------
compnerd wrote:

This should never be executed right?

https://github.com/llvm/llvm-project/pull/179925


More information about the llvm-branch-commits mailing list