[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