[llvm-branch-commits] [compiler-rt] [compiler-rt][ARM] Optimized FP -> integer conversions (PR #179927)
Simon Tatham via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Feb 24 09:02:15 PST 2026
https://github.com/statham-arm updated https://github.com/llvm/llvm-project/pull/179927
>From 481231a3964c2d5cb4fb28ce3532549a441c7244 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 29 Jan 2026 16:14:09 +0000
Subject: [PATCH 1/3] [compiler-rt][ARM] Optimized FP -> integer conversions
This commit adds a total of 8 new functions, all converting a
floating-point number to an integer, varying in 3 independent choices:
* input float format (32-bit or 64-bit)
* output integer size (32-bit or 64-bit)
* output integer type (signed or unsigned)
---
compiler-rt/lib/builtins/CMakeLists.txt | 8 +
compiler-rt/lib/builtins/arm/fixdfdi.S | 211 +++++++++++++++
compiler-rt/lib/builtins/arm/fixdfsi.S | 132 +++++++++
compiler-rt/lib/builtins/arm/fixsfdi.S | 137 ++++++++++
compiler-rt/lib/builtins/arm/fixsfsi.S | 98 +++++++
compiler-rt/lib/builtins/arm/fixunsdfdi.S | 159 +++++++++++
compiler-rt/lib/builtins/arm/fixunsdfsi.S | 129 +++++++++
compiler-rt/lib/builtins/arm/fixunssfdi.S | 103 +++++++
compiler-rt/lib/builtins/arm/fixunssfsi.S | 90 +++++++
.../test/builtins/Unit/fixdfdinew_test.c | 121 +++++++++
.../test/builtins/Unit/fixdfsinew_test.c | 96 +++++++
.../test/builtins/Unit/fixsfdinew_test.c | 100 +++++++
.../test/builtins/Unit/fixsfsinew_test.c | 99 +++++++
.../test/builtins/Unit/fixunsdfdinew_test.c | 96 +++++++
.../test/builtins/Unit/fixunsdfsinew_test.c | 251 ++++++++++++++++++
.../test/builtins/Unit/fixunssfdinew_test.c | 86 ++++++
.../test/builtins/Unit/fixunssfsinew_test.c | 85 ++++++
17 files changed, 2001 insertions(+)
create mode 100644 compiler-rt/lib/builtins/arm/fixdfdi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixdfsi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixsfdi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixsfsi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixunsdfdi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixunsdfsi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixunssfdi.S
create mode 100644 compiler-rt/lib/builtins/arm/fixunssfsi.S
create mode 100644 compiler-rt/test/builtins/Unit/fixdfdinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixdfsinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixsfdinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixsfsinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
create mode 100644 compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index 6b392c8eb22f0..5cf754135908b 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -457,6 +457,14 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm")
arm/unorddf2.S
arm/unordsf2.S
arm/extendsfdf2.S
+ arm/fixdfdi.S
+ arm/fixdfsi.S
+ arm/fixsfdi.S
+ arm/fixsfsi.S
+ arm/fixunsdfdi.S
+ arm/fixunsdfsi.S
+ arm/fixunssfdi.S
+ arm/fixunssfsi.S
arm/truncdfsf2.S
)
set_source_files_properties(${assembly_files}
diff --git a/compiler-rt/lib/builtins/arm/fixdfdi.S b/compiler-rt/lib/builtins/arm/fixdfdi.S
new file mode 100644
index 0000000000000..c93c3cc3d80a4
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixdfdi.S
@@ -0,0 +1,211 @@
+//===-- fixdfdi.S - double-precision FP to 64-bit signed int conversion ---===//
+//
+// 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 file implements the __fixdfdi function (double precision floating point
+// to 64-bit signed integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixdfdi)
+ push {r4, lr}
+ VMOV_FROM_DOUBLE(r0, r1, d0)
+ bl __aeabi_d2lz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixdfdi, __aeabi_d2lz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_d2lz)
+
+ // The fast path: deliver an answer as quickly as possible for positive cases
+ // that don't overflow, and branch out of line to handle everything else more
+ // slowly, including negative numbers, overflows, and NaNs.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ // Shift the exponent down to the bottom of the word. Using ASR here in place
+ // of LSR means the sign bit keeps its original value, and therefore as a
+ // side effect the N flag will tell us whether the input was negative. On the
+ // positive path the output is the same anyway.
+ asrs r2, xh, #20
+
+ // Make the 64-bit mantissa word, with its top half in r3 and the bottom half
+ // in r12, and set the leading mantissa bit at the top of r3.
+ //
+ // (In principle, the leading mantissa bit shouldn't be set at all if the
+ // input exponent is zero, because then the input is either 0 or a denormal.
+ // But since we're always rounding towards zero and not delivering any output
+ // indicating whether the result is inexact, it makes no difference - all
+ // denormals will round down to 0 anyway, and will still do so even if we
+ // imagine that their leading mantissa bit was set.)
+ lsl r3, xh, #11 // shift top word left to discard sign+exponent
+ orr r3, r3, xl, lsr #21 // combine with bits from bottom word
+ orr r3, r3, #1<<31 // set the leading bit
+ lsl r12, xl, #11 // shift bottom word left
+
+ // Branch out of line for negative cases, using the N flag set by the ASRS at
+ // the start of the function.
+ //
+ // For 64-bit outputs it's difficult to handle both signs in a shared code
+ // path. Converting to a 32-bit integer you can finish up with an RSBMI to
+ // conditionally negate it, but negating a 64-bit number requires two
+ // instructions and clobbers the flags in between, so you can't
+ // conditionalize both instructions on the same prior state of the flags.
+ bmi LOCAL_LABEL(neg)
+
+ // Convert the mantissa into a right shift count, indicating how many bits we
+ // want to shift the 64-bit mantissa in r3:r12 right by.
+ //
+ // If that's negative or zero, that means the input is too big, or the
+ // exponent is 0x7FF (so we might have a NaN), so branch out of line again.
+ //
+ // Another possibility is that if the number is very small, the right shift
+ // count might not fit in a byte, in which case the AArch32 shift semantics
+ // might do the wrong thing, since they only look at the low byte.
+ //
+ // To spot this efficiently, we do the conversion in two steps, arranged so
+ // that the first step detects massive underflow and the second detects
+ // overflow. We needed two steps anyway, because we need to subtract the
+ // input exponent from 0x43e (the exponent of input numbers between 2^63 and
+ // 2^64), and that value doesn't fit in an immediate field. So the first step
+ // subtracts 0x340, which makes r2 become negative if the exponent is very
+ // small; then the second step subtracts from 0xfe, giving 0xfe-(exp-0x340))
+ // = 0x43e-exp.
+ //
+ // The input is tiny if r2 is negative after the first subtraction. In that
+ // situation we set r2 to 0 before the second step, treating all exponents
+ // smaller than 0x340 as if they had been 0x340. We do this by ASR+BIC, which
+ // avoids needing an IT instruction in Thumb.
+ sub r2, r2, #0x340 // first stage: r2 is negative for underflow
+ bic r2, r2, r2, asr #31 // if so, saturate by clearing all bits of r2
+ rsbs r2, r2, #0xfe // second step: r2 is now the right shift count
+ ble LOCAL_LABEL(invalid) // if it was negative or zero, overflow
+
+ // Make the top word of the result, which is the easy part: it's a
+ // shifted-right version of the top word of the mantissa, which will be zero
+ // if the shift count is 32 or more.
+ lsrs xh, r3, r2
+
+ // Make the bottom word of the result. If the shift count is less than 32,
+ // this will be (ml >> n) | (mh << (32-n)), where 'mh' and 'ml' denote the
+ // high and low words of the mantissa (in r3 and r12 respectively). Otherwise
+ // the whole high output word is zero, and the low mantissa word contributes
+ // nothing to the output, so we just need mh >> (n-32).
+ lsr xl, r12, r2 // start by setting it to ml >> n
+ rsbs r2, r2, #32 // compute 32-n, and find which case we're in
+#if !__thumb__
+ orrhi xl, xl, r3, lsl r2 // shift count < 32, so OR in ml << (32-n)
+#else
+ // In Thumb we must separate the register-controlled shift and the OR into
+ // two instructions.
+ lslhi r3, r3, r2
+ orrhi xl, xl, r3
+#endif
+ rsbls r2, r2, #0 // shift count > 32, so compute n-32
+ lsrls xl, r3, r2 // replace xl with mh >> (n-32)
+
+ // We're done: the result is already rounded towards zero.
+ bx lr
+
+LOCAL_LABEL(neg):
+ // Handle negative numbers. We come here with the mantissa already prepared
+ // in r3 and r12, and the exponent in the bottom 11 bits of r2 with all 1s
+ // above it (because it was shifted down via ASR and the sign bit was set).
+ // In other words, r2 = exponent - 0x800.
+
+ // Convert the exponent into a shift count, exactly as on the positive path
+ // except that the initial subtraction of 0x340 is adjusted to cancel out the
+ // offset of 0x800 in r2, so that it becomes an addition.
+ add r2, r2, #0x800-0x340 // first stage: r2 is negative for underflow
+ bic r2, r2, r2, asr #31 // if so, saturate by clearing all bits of r2
+ rsbs r2, r2, #0xfe // second step: r2 is now the right shift count
+ ble LOCAL_LABEL(invalid) // if it was negative or zero, overflow
+
+ // Shift the mantissa down to create the absolute value of the result in
+ // xh:xl, exactly as on the positive path above.
+ lsrs xh, r3, r2 // make high word of mantissa
+ lsr xl, r12, r2 // initially set low word to ml >> n
+ rsbs r2, r2, #32 // compute 32-n, and find which case we're in
+#if !__thumb__
+ orrhi xl, xl, r3, lsl r2 // shift count < 32, so OR in ml << (32-n)
+#else
+ // In Thumb we must separate the register-controlled shift and the OR into
+ // two instructions.
+ lslhi r3, r3, r2
+ orrhi xl, xl, r3
+#endif
+ rsbls r2, r2, #0 // shift count > 32, so compute n-32
+ lsrls xl, r3, r2 // and replace xl with mh >> that
+
+ // All of that was almost exactly the same as the positive code path, but now
+ // we must negate the answer before returning it.
+ rsbs xl, xl, #0 // negate low word, setting carry flag
+#if !__thumb__
+ rsc xh, xh, #0 // negate high word
+#else
+ // Thumb has no RSC, so substitute MVN + ADC.
+ mvn xh, xh
+ adc xh, xh, #0
+#endif
+
+ // We're done.
+ bx lr
+
+LOCAL_LABEL(invalid):
+ // We come here if the exponent field of the number is large enough that it's
+ // either a NaN or infinity, or a finite number of absolute value at least
+ // 2^63.
+ //
+ // For out-of-range positive values, we return the maximum positive signed
+ // integer 0x7fffffffffffffff. For out-of-range negative values, we return
+ // the minimum negative signed integer 0x8000000000000000. For NaNs, we
+ // return zero.
+ //
+ // Not _every_ number of this kind is actually an invalid input. The exact
+ // value -2^63 is perfectly valid. If this implementation supported FP
+ // exceptions, we'd have to detect that one case and return
+ // 0x8000000000000000 with no exception, while raising an Invalid Operation
+ // exception for everything else. But since we don't support exceptions, we
+ // don't have to tell the difference here: -2^63 and negative overflows both
+ // return 0x8000000000000000, and it doesn't matter that one is the right
+ // answer and the other a best-effort error response.
+
+ // Check for NaNs and branch out of line.
+ cmp xl, #1 // set C if any bit of xl is nonzero
+ adc r2, xh, xh // shift that bit into xh, discarding sign
+ cmn r2, #1 << 21 // then greater than 0xFFE00000 means NaN
+ bhi LOCAL_LABEL(nan)
+
+ // The remaining case is a too-large exponent. Return either INT_MAX or
+ // INT_MIN depending on sign, using the fact that (xh ASR 31) is 0 for a
+ // positive input or 0xFFFFFFFF for a negative input, so it's exactly the
+ // bitwise inverse of the correct low word of the output.
+ mvn xl, xh, asr #31 // make the low word of the output
+ eor xh, xl, #0x80000000 // make the high word by flipping sign bit
+ bx lr
+
+LOCAL_LABEL(nan):
+ // Return zero, for use when the input was a NaN.
+ movs xh, #0
+ movs xl, #0
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_d2lz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixdfsi.S b/compiler-rt/lib/builtins/arm/fixdfsi.S
new file mode 100644
index 0000000000000..c567a3690235a
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixdfsi.S
@@ -0,0 +1,132 @@
+//===-- fixdfsi.S - double-precision FP to 32-bit signed int conversion ---===//
+//
+// 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 file implements the __fixdfsi function (double precision floating point
+// to 32-bit signed integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixdfsi)
+ push {r4, lr}
+ VMOV_FROM_DOUBLE(r0, r1, d0)
+ bl __aeabi_d2iz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixdfsi, __aeabi_d2iz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_d2iz)
+
+ // The fast path: deliver an answer as quickly as possible for cases that
+ // don't overflow or involve a NaN, and branch out of line to handle
+ // everything else more slowly.
+ //
+ // The basic idea is to make a bare version of the top 32 bits of the
+ // mantissa, with its leading 1 bit explicit at the top of the word, and
+ // shift it right by an amount derived from the exponent.
+
+ // Separate out the exponent of the input.
+ lsls r3, xh, #1 // everything but the sign bit
+ lsrs r3, r3, #21 // just the exponent
+
+ // Convert the exponent into a right shift count. This involves subtracting
+ // from 0x41e (which is the exponent of 2^31, so the largest that doesn't
+ // overflow). We can't do that in one instruction, so do it in two.
+ sub r3, r3, #0x400
+ rsbs r3, r3, #0x1e
+
+ // That RSB instruction also set the flags, which tell us whether the shift
+ // count went below zero: we subtracted an adjusted input exponent from 0x1e,
+ // so the LE condition is met if 0x1e ≤ that adjusted exponent, i.e. if the
+ // shift count is negative or zero, i.e. if the input float has absolute
+ // value at least 2^31.
+ //
+ // Now check if the shift count exceeds 0xFF, so that the AArch32 shift
+ // semantics would reduce it mod 0x100. We can do that in a way that also
+ // sets the GT condition, saving an instruction on the fast path at the cost
+ // of having to re-test which condition happened once we branch out of line.
+ rsbsgt r12, r3, #0x100 // also set LE if shift count ≥ 0x100
+ ble LOCAL_LABEL(uncommon)
+
+ // Construct a word containing the top 32 bits of the mantissa. We do this in
+ // such a way that the initial ORRS also sets the N flag based on the sign
+ // bit in xh, so that we can use that for a conditional negation later.
+ orrs r2, xh, #1 << 20 // put on the leading 1 and test sign
+ lsl r2, r2, #11 // shift mantissa part of xh up to top of word
+ orr r2, r2, xl, lsr #21 // the top 11 mantissa bits from xl
+
+ // Now shift the mantissa down to its output position, moving it into the
+ // output register r0 in the process, and negate the result if the input was
+ // negative.
+ //
+ // We're rounding towards zero, so bits shifted off the bottom can just be
+ // ignored.
+ lsr r0, r2, r3 // construct the rounded-down result
+ rsbmi r0, r0, #0 // negate it if input < 0
+ bx lr // and return
+
+LOCAL_LABEL(uncommon):
+ // We come here if the exponent field of the number is either too large or
+ // too small, so that the number is one of
+ // - a NaN
+ // - an infinity
+ // - a finite number of absolute value at least 2^31
+ // - a finite nonzero number small enough to underflow to zero (and so small
+ // that the shift instruction in the fast path couldn't handle it)
+ // - zero.
+ //
+ // For out-of-range positive values, we return the maximum positive signed
+ // integer 0x7fffffff. For out-of-range negative values, we return the
+ // minimum negative signed integer 0x80000000. For everything else - NaNs,
+ // underflows and true zero inputs - we return zero.
+ //
+ // (Not _every_ out-of-range finite number is actually an invalid input. The
+ // exact value -2^31 is perfectly valid. If this implementation supported FP
+ // exceptions, we'd have to detect that one case and return 0x80000000 with
+ // no exception, while raising an Invalid Operation exception for everything
+ // else. But since we don't support exceptions, we don't have to tell the
+ // difference here: -2^31 and negative overflows both return 0x80000000, and
+ // it doesn't matter that one is the right answer and the other a best-effort
+ // error response.)
+
+ // Check for a too-large shift count (too-small exponent) first, because that
+ // includes the case of an exact zero, which is probably one of the more
+ // common inputs and should be handled fast if we can.
+ cmp r3, #0xFF
+ movgt r0, #0
+ bxgt lr
+
+ // Now check for NaNs.
+ lsls r2, xh, #1 // shift exponent of x to top of word
+ cmn r2, #1 << 21 // set HI if xh proves it's a NaN by itself
+ cmpeq xl, #0 // now HI is set if it's a NaN
+ bhi LOCAL_LABEL(nan)
+
+ // The remaining case is a too-large exponent. Return either INT_MAX or
+ // INT_MIN depending on sign.
+ mov r2, #0x7FFFFFFF // start with INT_MAX
+ eor r0, r2, xh, asr #31 // flip all its bits if xh bit 31 is set
+ bx lr
+
+LOCAL_LABEL(nan):
+ // Out-of-line path that returns zero for NaN inputs.
+ mov r0, #0
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_d2iz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixsfdi.S b/compiler-rt/lib/builtins/arm/fixsfdi.S
new file mode 100644
index 0000000000000..6736c9f21aaa8
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixsfdi.S
@@ -0,0 +1,137 @@
+//===-- fixsfdi.S - single-precision FP to 64-bit signed int conversion ---===//
+//
+// 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 file implements the __fixsfdi function (single precision floating point
+// to 64-bit signed integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixsfdi)
+ push {r4, lr}
+ vmov r0, s0
+ bl __aeabi_f2lz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixsfdi, __aeabi_f2lz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_f2lz)
+
+ // The fast path: deliver an answer as quickly as possible for positive cases
+ // that don't overflow, and branch out of line to handle everything else more
+ // slowly, including negative numbers, overflows, and NaNs.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ // Shift the exponent down to the bottom of the word. Using ASR here in place
+ // of LSR means the sign bit keeps its original value, and therefore as a
+ // side effect the N flag will tell us whether the input was negative. On the
+ // positive path the output is the same anyway.
+ asrs r2, r0, #23
+
+ // Shift the mantissa to the top of the word, and put on the leading 1 bit.
+ mov r3, r0, lsl #8
+ orrne r3, r3, #1 << 31
+
+ // If the value was negative, branch out of line to handle that.
+ bmi LOCAL_LABEL(negative)
+
+ // Convert the mantissa into a shift count. If that's negative or zero, that
+ // means the input is too big, or the exponent is 0xFF (so we might have a
+ // NaN), so branch out of line again.
+ rsbs r2, r2, #63 + 0x7f
+ bls LOCAL_LABEL(invalid)
+
+ // Make the top word of the result, which is the easy part: if the shift
+ // count is too big, nothing goes wrong, we just end up with whatever part of
+ // the mantissa remained in this word.
+ mov xh, r3, lsr r2
+
+ // Make the bottom word of the result. This might involve shifting the
+ // mantissa either left or right, depending on the exponent.
+ subs r12, r2, #32 // r12 = how far to shift mantissa down
+ movhs xl, r3, lsr r12 // if that's positive, just do it
+ rsblo r12, r12, #0 // otherwise, negate it
+ movlo xl, r3, lsl r12 // and shift left by that much instead
+ bx lr
+
+LOCAL_LABEL(negative):
+ // Handle negative numbers. We come here with the mantissa already prepared
+ // in r3, and the exponent in the bottom 8 bits of r2 with all 1s above it
+ // (because it was shifted down via ASR and the sign bit was set).
+
+ // Start by clearing the top 24 bits of r2, left set by the ASR above,
+ // leaving just the bare exponent.
+ and r2, r2, #0xff
+
+ // Now do exactly the same processing as on the positive path.
+ rsbs r2, r2, #63 + 0x7f // make the shift count
+ bls LOCAL_LABEL(invalid) // branch out of line if shift count < 0
+ mov xh, r3, lsr r2 // top word of result
+ subs r12, r2, #32 // right-shift required for bottom word
+ movhs xl, r3, lsr r12 // bottom word, if shift count >= 0
+ rsblo r12, r2, #32 // otherwise, turn into a left-shift count
+ movlo xl, r3, lsl r12 // bottom word, if it needed a left shift
+
+ // Finally, negate the answer.
+ rsbs xl, xl, #0 // negate bottom word
+#if !__thumb__
+ rsc xh, xh, #0 // negate top word
+#else
+ // Thumb has no RSC, so simulate it by bitwise inversion and then ADC
+ mvn xh, xh
+ adc xh, xh, #0
+#endif
+
+ bx lr
+
+LOCAL_LABEL(invalid):
+ // We come here if the exponent field of the number is large enough that it's
+ // either a NaN or infinity, or a finite number of absolute value at least
+ // 2^63.
+ //
+ // For out-of-range positive values, we return the maximum positive signed
+ // integer 0x7fffffffffffffff. For out-of-range negative values, we return
+ // the minimum negative signed integer 0x8000000000000000. For NaNs, we
+ // return zero.
+ //
+ // Not _every_ number of this kind is actually an invalid input. The exact
+ // value -2^63 is perfectly valid. If this implementation supported FP
+ // exceptions, we'd have to detect that one case and return
+ // 0x8000000000000000 with no exception, while raising an Invalid Operation
+ // exception for everything else. But since we don't support exceptions, we
+ // don't have to tell the difference here: -2^63 and negative overflows both
+ // return 0x8000000000000000, and it doesn't matter that one is the right
+ // answer and the other a best-effort error response.
+ mov r1, #0xFF000000
+ cmp r1, r0, lsl #1 // 0xFF000000 < (input << 1) means a NaN
+ blo LOCAL_LABEL(return_zero) // so branch out of line to return zero
+ mov r2, #0x7FFFFFFF // set up to return INT_MAX
+ eor xh, r2, r0, asr #31 // flip top half to 80000000 if input < 0
+ mvn xl, r0, asr #31 // and bottom half is FFFFFFFF or 00000000
+ bx lr
+
+LOCAL_LABEL(return_zero):
+ mov xl, #0
+ mov xh, #0
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_f2lz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixsfsi.S b/compiler-rt/lib/builtins/arm/fixsfsi.S
new file mode 100644
index 0000000000000..582463df41320
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixsfsi.S
@@ -0,0 +1,98 @@
+//===-- fixsfsi.S - single-precision FP to 32-bit signed int conversion ---===//
+//
+// 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 file implements the __fixsfsi function (single precision floating point
+// to 32-bit signed integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixsfsi)
+ push {r4, lr}
+ vmov r0, s0
+ bl __aeabi_f2iz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixsfsi, __aeabi_f2iz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_f2iz)
+
+ // The fast path: deliver an answer as quickly as possible for cases that
+ // don't overflow or involve a NaN, and branch out of line to handle
+ // everything else more slowly.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ lsls r1, r0, #1 // r1 = everything but the sign bit
+ lsrs r2, r1, #24 // r2 = just the exponent
+ rsbs r3, r2, #31 + 0x7f // r3 = how much to shift the mantissa right
+
+ // If the shift count is negative, that means the input is too big, or else
+ // the exponent is 0xFF (so we might have a NaN). Branch out of line to
+ // handle both cases.
+ bls LOCAL_LABEL(invalid)
+
+ // OR the leading 1 into the mantissa and shift it up to the top of the word.
+ //
+ // We do it in _that_ order, because that way, the OR operates on the
+ // original r0 and doesn't touch the top bit. So if we make it set the flags
+ // too, it also tests the sign of the input, leaving the result in the N
+ // flag, saving us a separate sign test instruction.
+ orrs r2, r0, #1 << 23 // put on the leading 1 and test sign
+ lsl r2, r2, #8 // shift mantissa up to top of word
+
+ // Now shift the mantissa down to its output position, and negate the result
+ // if the input was negative.
+ //
+ // We're rounding towards zero, so bits shifted off the bottom can just be
+ // ignored.
+ lsr r0, r2, r3 // construct the rounded-down result
+ rsbmi r0, r0, #0 // negate it if input < 0
+ bx lr // and return
+
+LOCAL_LABEL(invalid):
+ // We come here if the exponent field of the number is large enough that it's
+ // either a NaN or infinity, or a finite number of absolute value at least
+ // 2^31.
+ //
+ // For out-of-range positive values, we return the maximum positive signed
+ // integer 0x7fffffff. For out-of-range negative values, we return the
+ // minimum negative signed integer 0x80000000. For NaNs, we return zero.
+ //
+ // Not _every_ number of this kind is actually an invalid input. The exact
+ // value -2^31 is perfectly valid. If this implementation supported FP
+ // exceptions, we'd have to detect that one case and return 0x80000000 with
+ // no exception, while raising an Invalid Operation exception for everything
+ // else. But since we don't support exceptions, we don't have to tell the
+ // difference here: -2^31 and negative overflows both return 0x80000000, and
+ // it doesn't matter that one is the right answer and the other a best-effort
+ // error response.
+ mov r1, #0xFF000000
+ cmp r1, r0, lsl #1 // 0xFF000000 < (input << 1) means a NaN
+ blo LOCAL_LABEL(return_zero) // so branch out of line to return zero
+ mov r2, #0x7FFFFFFF // set up to return INT_MAX
+ eor r0, r2, r0, asr #31 // turn it into INT_MIN if input was negative
+ bx lr
+
+LOCAL_LABEL(return_zero):
+ mov r0, #0
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_f2iz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixunsdfdi.S b/compiler-rt/lib/builtins/arm/fixunsdfdi.S
new file mode 100644
index 0000000000000..f27521df3421a
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixunsdfdi.S
@@ -0,0 +1,159 @@
+//===-- fixunsdfdi.S - double-precision FP to 64-bit unsigned int conversion==//
+//
+// 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 file implements the __fixunsdfdi function (double precision floating
+// point to 64-bit unsigned integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixunsdfdi)
+ push {r4, lr}
+ VMOV_FROM_DOUBLE(r0, r1, d0)
+ bl __aeabi_d2ulz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixunsdfdi, __aeabi_d2ulz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_d2ulz)
+
+ // The fast path: deliver an answer as quickly as possible for positive cases
+ // that don't overflow, and branch out of line to handle everything else more
+ // slowly, including negative numbers, overflows, and NaNs.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ // Shift the exponent down to the bottom of the word. We keep the sign bit,
+ // which will cause negative inputs to be treated like positive numbers with
+ // extra-enormous exponent. This is good enough to trigger a branch out of
+ // line later without needing an extra instruction, and then we can handle
+ // negative inputs properly after that branch.
+ asrs r2, xh, #20
+
+ // Make the 64-bit mantissa word, with its top half in r3 and the bottom half
+ // in r12, and set the leading mantissa bit at the top of r3.
+ //
+ // (In principle, the leading mantissa bit shouldn't be set at all if the
+ // input exponent is zero, because then the input is either 0 or a denormal.
+ // But since we're always rounding towards zero and not delivering any output
+ // indicating whether the result is inexact, it makes no difference - all
+ // denormals will round down to 0 anyway, and will still do so even if we
+ // imagine that their leading mantissa bit was set.)
+ lsl r3, xh, #11 // shift top word left to discard sign+exponent
+ orr r3, r3, xl, lsr #21 // combine with bits from bottom word
+ orr r3, r3, #1<<31 // set the leading bit
+ lsl r12, xl, #11 // shift bottom word left
+
+ // Convert the mantissa into a right shift count, indicating how many bits we
+ // want to shift the 64-bit mantissa in r3:r12 right by.
+ //
+ // If that's negative, that means the input is too big, or the exponent is
+ // 0x7FF (so we might have a NaN), or the value in r2 was 0x800 or more
+ // because the input was negative, so branch out of line again.
+ //
+ // Another possibility is that if the number is very small, the right shift
+ // count might not fit in a byte, in which case the AArch32 shift semantics
+ // might do the wrong thing, since they only look at the low byte.
+ //
+ // To spot this efficiently, we do the conversion in two steps, arranged so
+ // that the first step detects massive underflow and the second detects
+ // overflow. We needed two steps anyway, because we need to subtract the
+ // input exponent from 0x43e (the exponent of input numbers between 2^63 and
+ // 2^64), and that value doesn't fit in an immediate field. So the first step
+ // subtracts 0x340, which makes r2 become negative if the exponent is very
+ // small; then the second step subtracts from 0xfe, giving 0xfe-(exp-0x340))
+ // = 0x43e-exp.
+ //
+ // The input is tiny if r2 is negative after the first subtraction. In that
+ // situation we set r2 to 0 before the second step, treating all exponents
+ // smaller than 0x340 as if they had been 0x340. We do this by ASR+BIC, which
+ // avoids needing an IT instruction in Thumb.
+ sub r2, r2, #0x340 // first stage: r2 is negative for underflow
+ bic r2, r2, r2, asr #31 // if so, saturate by clearing all bits of r2
+ rsbs r2, r2, #0xfe // second step: r2 is now the right shift count
+ blt LOCAL_LABEL(uncommon) // if it was negative, overflow
+
+ // Make the top word of the result, which is the easy part: it's a
+ // shifted-right version of the top word of the mantissa, which will be zero
+ // if the shift count is 32 or more.
+ lsrs xh, r3, r2
+
+ // Make the bottom word of the result. If the shift count is less than 32,
+ // this will be (ml >> n) | (mh << (32-n)), where 'mh' and 'ml' denote the
+ // high and low words of the mantissa (in r3 and r12 respectively). Otherwise
+ // the whole high output word is zero, and the low mantissa word contributes
+ // nothing to the output, so we just need mh >> (n-32).
+ lsr xl, r12, r2 // start by setting it to ml >> n
+ rsbs r2, r2, #32 // compute 32-n, and find which case we're in
+#if !__thumb__
+ orrhi xl, xl, r3, lsl r2 // shift count < 32, so OR in ml << (32-n)
+#else
+ // In Thumb we must separate the register-controlled shift and the OR into
+ // two instructions.
+ lslhi r3, r3, r2
+ orrhi xl, xl, r3
+#endif
+ rsbls r2, r2, #0 // shift count > 32, so compute n-32
+ lsrls xl, r3, r2 // replace xl with mh >> (n-32)
+
+ // We're done: the result is already rounded towards zero.
+ bx lr
+
+LOCAL_LABEL(uncommon):
+ // We come here if the exponent field of the number is either too large or
+ // too small, or if the sign bit is set, so that the number is one of
+ // - a NaN
+ // - an infinity
+ // - a positive finite number of absolute value at least 2^31
+ // - any negative number at all.
+
+ // Test the sign bit first, and branch out of line for positive values, on
+ // the theory that reasonably sensible negative values (like -0.5) are more
+ // likely than the overflow, infinity or NaN cases, and want to be handled as
+ // quickly as possible.
+ tst xh, xh
+ bpl LOCAL_LABEL(positive_invalid)
+
+ // Now we have either a negative finite value, -inf, or a NaN (with the sign
+ // bit set). Conveniently, _all_ of those just return 0, so we don't have to
+ // bother checking which.
+ //
+ // If we were reporting exceptions, then inputs in the range (-1,0] would
+ // _legally_ return 0 (after rounding toward zero), whereas -1 and below
+ // would raise the IEEE Invalid Operation exception.
+LOCAL_LABEL(return_zero):
+ movs xh, #0
+ movs xl, #0
+ bx lr
+
+LOCAL_LABEL(positive_invalid):
+ // Here we have a positive value causing an invalid operation exception. If
+ // it's a NaN, we return zero; otherwise we return UINT_MAX.
+ cmp xl, #1 // set C if any bit of xl is nonzero
+ adc r2, xh, xh // shift that bit into xh, discarding sign
+ cmn r2, #1 << 21 // then greater than 0xFFE00000 means NaN
+ bhi LOCAL_LABEL(return_zero) // so we go back to the case above
+
+ mov xh, #0xFFFFFFFF
+ mov xl, #0xFFFFFFFF
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_d2ulz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixunsdfsi.S b/compiler-rt/lib/builtins/arm/fixunsdfsi.S
new file mode 100644
index 0000000000000..cefa2d615b055
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixunsdfsi.S
@@ -0,0 +1,129 @@
+//===-- fixunsdfsi.S - double-precision FP to 32-bit unsigned int conversion==//
+//
+// 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 file implements the __fixunsdfsi function (double precision floating
+// point to 32-bit unsigned integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixunsdfsi)
+ push {r4, lr}
+ VMOV_FROM_DOUBLE(r0, r1, d0)
+ bl __aeabi_d2uiz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixunsdfsi, __aeabi_d2uiz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_d2uiz)
+
+ // The fast path: deliver an answer as quickly as possible for positive
+ // inputs that don't overflow, and branch out of line to handle everything
+ // else (negative numbers, overflows and NaNs) more slowly.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ lsrs r3, xh, #20 // exponent, or >=0x800 if input is negative
+
+ // Convert the exponent into a right shift count. This involves subtracting
+ // from 0x41e (which is the exponent of 2^31, so the largest that doesn't
+ // overflow). We can't do that in one instruction, so do it in two.
+ sub r3, r3, #0x400
+ rsbs r3, r3, #0x1e
+
+ // That RSB instruction also set the flags, which tell us whether the shift
+ // count went below zero: we subtracted an adjusted input exponent from 0x1e,
+ // so the LT condition is met if 0x1e < that adjusted exponent, i.e. if the
+ // shift count is negative, i.e. if the input float has absolute value at
+ // least 2^32.
+ //
+ // We didn't bother removing the sign bit when we shifted right to get the
+ // exponent. So negative numbers will be treated the same as overlarge
+ // positive numbers and NaNs, i.e. will branch out of line, and we can sort
+ // out which is which later.
+ //
+ // Now check if the shift count exceeds 0xFF, so that the AArch32 shift
+ // semantics would reduce it mod 0x100. We can do that in a way that also
+ // sets the GT condition, saving an instruction on the fast path at the cost
+ // of having to re-test which condition happened once we branch out of line.
+ rsbsge r12, r3, #0xFF // also set LT if shift count > 0xFF
+ blt LOCAL_LABEL(uncommon)
+
+ // Construct a word containing the top 32 bits of the mantissa.
+ orr r2, xh, #1 << 20 // put on the leading 1
+ lsls r2, r2, #11 // shift mantissa part of xh up to top of word
+ orr r2, r2, xl, lsr #21 // the top 11 mantissa bits from xl
+
+ // Now shift the mantissa down to its output position, moving it into the
+ // output register r0 in the process.
+ //
+ // We're rounding towards zero, so bits shifted off the bottom can just be
+ // ignored.
+ lsrs r0, r2, r3 // construct the rounded-down result
+ bx lr // and return
+
+LOCAL_LABEL(uncommon):
+ // We come here if the exponent field of the number is either too large or
+ // too small, or if the sign bit is set, so that the number is one of
+ // - a NaN
+ // - an infinity
+ // - a positive finite number of absolute value at least 2^31
+ // - a positive finite nonzero number small enough to underflow to zero (and
+ // so small that the shift instruction in the fast path couldn't handle
+ // it)
+ // - zero
+ // - any negative number at all.
+
+ // Check for a too-large shift count (too-small exponent) first, because that
+ // includes the case of an exact zero, which is probably one of the more
+ // common inputs and should be handled fast if we can.
+ cmp r3, #0xFF
+ movgt r0, #0
+ bxgt lr
+
+ // Next test the sign bit. Branch out of line for positive values, again on
+ // the theory that reasonably sensible negative values (like -0.5) are more
+ // likely than any of the remaining positive cases.
+ tst xh, xh
+ bpl LOCAL_LABEL(positive_invalid)
+
+ // Now we have either a negative finite value, -inf, or a NaN (with the sign
+ // bit set). Conveniently, _all_ of those just return 0, so we don't have to
+ // bother checking which.
+ //
+ // If we were reporting exceptions, then inputs in the range (-1,0] would
+ // _legally_ return 0 (after rounding toward zero), whereas -1 and below
+ // would raise the IEEE Invalid Operation exception.
+LOCAL_LABEL(return_zero):
+ mov r0, #0
+ bx lr
+
+LOCAL_LABEL(positive_invalid):
+ // Here we have a positive value causing an invalid operation exception. If
+ // it's a NaN, we return zero; otherwise we return UINT_MAX.
+ lsls r2, xh, #1 // shift exponent of x to top of word
+ cmn r2, #1 << 21 // set HI if xh proves it's a NaN by itself
+ cmpeq xl, #0 // now HI is set if it's a NaN
+ bhi LOCAL_LABEL(return_zero)
+ mov r0, #0xFFFFFFFF
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_d2uiz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixunssfdi.S b/compiler-rt/lib/builtins/arm/fixunssfdi.S
new file mode 100644
index 0000000000000..00068077d2cc1
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixunssfdi.S
@@ -0,0 +1,103 @@
+//===-- fixunssfdi.S - single-precision FP to 64-bit unsigned int conversion==//
+//
+// 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 file implements the __fixunssfdi function (single precision floating
+// point to 64-bit unsigned integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+#include "endian.h"
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixunssfdi)
+ push {r4, lr}
+ vmov r0, s0
+ bl __aeabi_f2ulz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixunssfdi, __aeabi_f2ulz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_f2ulz)
+
+ // The fast path: deliver an answer as quickly as possible for positive
+ // inputs that don't overflow, and branch out of line to handle everything
+ // else (negative numbers, overflows and NaNs) more slowly.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ // Shift the exponent down to the bottom of the word.
+ lsrs r2, r0, #23 // r2 = exponent, or >=256 if input is negative
+ rsbs r2, r2, #63 + 0x7f // r2 = how much to shift the mantissa right
+
+ // If the shift count is negative, that means the input is too big, or the
+ // exponent is 0xFF (so we might have a NaN), or the sign bit was set (so the
+ // input is negative). Branch out of line to handle all those cases.
+ blo LOCAL_LABEL(uncommon)
+
+ // Shift the mantissa to the top of the word, and put on the leading 1 bit.
+ lsl r3, r0, #8
+ orr r3, r3, #0x80000000
+
+ // Make the top word of the result, which is the easy part: if the shift
+ // count is too big, nothing goes wrong, we just end up with whatever part of
+ // the mantissa remained in this word.
+ mov xh, r3, lsr r2
+
+ // Make the bottom word of the result. This might involve shifting the
+ // mantissa either left or right, depending on the exponent.
+ //
+ // We're rounding towards zero, so bits shifted off the bottom can just be
+ // ignored.
+ subs r12, r2, #32 // r12 = how far to shift mantissa down
+ movhs xl, r3, lsr r12 // if that's positive, just do it
+ rsblo r12, r12, #0 // otherwise, negate it
+ movlo xl, r3, lsl r12 // and shift left by that much instead
+ bx lr
+
+LOCAL_LABEL(uncommon):
+ // We come here for positive overflows, positive infinity, NaNs, and anything
+ // with the sign bit set.
+ //
+ // Start by testing the sign bit. Branch out of line for positive values.
+ tst r0, r0
+ bpl LOCAL_LABEL(positive_invalid)
+
+ // Now we have either a negative finite value, -inf, or a NaN (with the sign
+ // bit set). Conveniently, _all_ of those just return 0, so we don't have to
+ // bother checking which.
+ //
+ // If we were reporting exceptions, then inputs in the range (-1,0] would
+ // _legally_ return 0 (after rounding toward zero), whereas -1 and below
+ // would raise the IEEE Invalid Operation exception.
+LOCAL_LABEL(return_zero):
+ mov xl, #0
+ mov xh, #0
+ bx lr
+
+LOCAL_LABEL(positive_invalid):
+ // Here we have a positive value causing an invalid operation exception. If
+ // it's a NaN, we return zero; otherwise we return UINT_MAX.
+ mov r1, #0xFF000000
+ cmp r1, r0, lsl #1
+ blo LOCAL_LABEL(return_zero)
+ mov xl, #0xFFFFFFFF
+ mov xh, #0xFFFFFFFF
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_f2ulz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/lib/builtins/arm/fixunssfsi.S b/compiler-rt/lib/builtins/arm/fixunssfsi.S
new file mode 100644
index 0000000000000..1594a132801bb
--- /dev/null
+++ b/compiler-rt/lib/builtins/arm/fixunssfsi.S
@@ -0,0 +1,90 @@
+//===-- fixunssfsi.S - single-precision FP to 32-bit unsigned int conversion==//
+//
+// 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 file implements the __fixunssfsi function (single precision floating
+// point to 32-bit unsigned integer conversion), with the C rounding semantics
+// (rounding towards zero), for the Arm and Thumb2 ISAs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../assembly.h"
+
+
+ .syntax unified
+ .text
+ .p2align 2
+
+#if __ARM_PCS_VFP
+DEFINE_COMPILERRT_FUNCTION(__fixunssfsi)
+ push {r4, lr}
+ vmov r0, s0
+ bl __aeabi_f2uiz
+ pop {r4, pc}
+#else
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__fixunssfsi, __aeabi_f2uiz)
+#endif
+
+DEFINE_COMPILERRT_FUNCTION(__aeabi_f2uiz)
+
+ // The fast path: deliver an answer as quickly as possible for positive
+ // inputs that don't overflow, and branch out of line to handle everything
+ // else (negative numbers, overflows and NaNs) more slowly.
+ //
+ // The basic idea is to make a bare version of the mantissa, with its leading
+ // 1 bit explicit at the top of the word, and shift it right by an amount
+ // derived from the exponent.
+
+ lsrs r1, r0, #23 // r1 = exponent, or >=256 if input is negative
+ rsbs r2, r1, #31 + 0x7f // r2 = how much to shift the mantissa right
+
+ // If the shift count is negative, that means the input is too big, or the
+ // exponent is 0xFF (so we might have a NaN), or the sign bit was set (so the
+ // input is negative). Branch out of line to handle all those cases.
+ blt LOCAL_LABEL(uncommon) // negative, infinite or NaN
+
+ // Shift the mantissa up to the top of the word, OR in the leading 1, and
+ // then shift it back down to make the result.
+ //
+ // We're rounding towards zero, so bits shifted off the bottom can just be
+ // ignored.
+ lsl r3, r0, #8 // shift mantissa up
+ orr r3, r3, #0x80000000 // add leading 1
+ mov r0, r3, lsr r2 // shift down again
+ bx lr
+
+LOCAL_LABEL(uncommon):
+ // We come here for positive overflows, positive infinity, NaNs, and anything
+ // with the sign bit set.
+ //
+ // Start by testing the sign bit. Branch out of line for positive values.
+ tst r0, r0
+ bpl LOCAL_LABEL(positive_invalid)
+
+ // Now we have either a negative finite value, -inf, or a NaN (with the sign
+ // bit set). Conveniently, _all_ of those just return 0, so we don't have to
+ // bother checking which.
+ //
+ // If we were reporting exceptions, then inputs in the range (-1,0] would
+ // _legally_ return 0 (after rounding toward zero), whereas -1 and below
+ // would raise the IEEE Invalid Operation exception.
+LOCAL_LABEL(return_zero):
+ mov r0, #0
+ bx lr
+
+LOCAL_LABEL(positive_invalid):
+ // Here we have a positive value causing an invalid operation exception. If
+ // it's a NaN, we return zero; otherwise we return UINT_MAX.
+ mov r1, #0xFF000000
+ cmp r1, r0, lsl #1
+ blo LOCAL_LABEL(return_zero)
+ mov r0, #0xFFFFFFFF
+ bx lr
+
+END_COMPILERRT_FUNCTION(__aeabi_f2uiz)
+
+NO_EXEC_STACK_DIRECTIVE
diff --git a/compiler-rt/test/builtins/Unit/fixdfdinew_test.c b/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
new file mode 100644
index 0000000000000..a8bcbf72fd349
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
@@ -0,0 +1,121 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixdfdi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from double to int64_t
+COMPILER_RT_ABI int64_t __fixdfdi(double a);
+
+int test__fixdfdi(int line, uint64_t a_rep, uint64_t expected) {
+ double a = fromRep64(a_rep);
+ uint64_t x = (uint64_t)__fixdfdi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixdfdi(%016" PRIx64 ") = %016" PRIx64
+ ", expected %016" PRIx64 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixdfdi(a,x) test__fixdfdi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixdfdi(0x0000000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0x0000000000000001, 0x0000000000000000);
+ status |= test__fixdfdi(0x0000000000500000, 0x0000000000000000);
+ status |= test__fixdfdi(0x3fd0000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0x3fe0000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0x3fe8000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0x3ff0000000000000, 0x0000000000000001);
+ status |= test__fixdfdi(0x3ff4000000000000, 0x0000000000000001);
+ status |= test__fixdfdi(0x3ff8000000000000, 0x0000000000000001);
+ status |= test__fixdfdi(0x3ffc000000000000, 0x0000000000000001);
+ status |= test__fixdfdi(0x4000000000000000, 0x0000000000000002);
+ status |= test__fixdfdi(0x4002000000000000, 0x0000000000000002);
+ status |= test__fixdfdi(0x4004000000000000, 0x0000000000000002);
+ status |= test__fixdfdi(0x4006000000000000, 0x0000000000000002);
+ status |= test__fixdfdi(0x41f0000000040000, 0x0000000100000000);
+ status |= test__fixdfdi(0x41f0000000080000, 0x0000000100000000);
+ status |= test__fixdfdi(0x41f00000000c0000, 0x0000000100000000);
+ status |= test__fixdfdi(0x41f0000000140000, 0x0000000100000001);
+ status |= test__fixdfdi(0x41f0000000180000, 0x0000000100000001);
+ status |= test__fixdfdi(0x41f00000001c0000, 0x0000000100000001);
+ status |= test__fixdfdi(0x41f0000000240000, 0x0000000100000002);
+ status |= test__fixdfdi(0x41f0000000280000, 0x0000000100000002);
+ status |= test__fixdfdi(0x41f00000002c0000, 0x0000000100000002);
+ status |= test__fixdfdi(0x41fffffffff40000, 0x00000001ffffffff);
+ status |= test__fixdfdi(0x41fffffffff80000, 0x00000001ffffffff);
+ status |= test__fixdfdi(0x41fffffffffc0000, 0x00000001ffffffff);
+ status |= test__fixdfdi(0x42a0468ace000000, 0x0000082345670000);
+ status |= test__fixdfdi(0x43dfffffffffffff, 0x7ffffffffffffc00);
+ status |= test__fixdfdi(0x8000000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0x8000000000000001, 0x0000000000000000);
+ status |= test__fixdfdi(0x8000000000500000, 0x0000000000000000);
+ status |= test__fixdfdi(0xbfd0000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0xbfe0000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0xbfe8000000000000, 0x0000000000000000);
+ status |= test__fixdfdi(0xbff0000000000000, 0xffffffffffffffff);
+ status |= test__fixdfdi(0xbff4000000000000, 0xffffffffffffffff);
+ status |= test__fixdfdi(0xbff8000000000000, 0xffffffffffffffff);
+ status |= test__fixdfdi(0xbffc000000000000, 0xffffffffffffffff);
+ status |= test__fixdfdi(0xc000000000000000, 0xfffffffffffffffe);
+ status |= test__fixdfdi(0xc002000000000000, 0xfffffffffffffffe);
+ status |= test__fixdfdi(0xc004000000000000, 0xfffffffffffffffe);
+ status |= test__fixdfdi(0xc006000000000000, 0xfffffffffffffffe);
+ status |= test__fixdfdi(0xc1f0000000040000, 0xffffffff00000000);
+ status |= test__fixdfdi(0xc1f0000000080000, 0xffffffff00000000);
+ status |= test__fixdfdi(0xc1f00000000c0000, 0xffffffff00000000);
+ status |= test__fixdfdi(0xc1f0000000140000, 0xfffffffeffffffff);
+ status |= test__fixdfdi(0xc1f0000000180000, 0xfffffffeffffffff);
+ status |= test__fixdfdi(0xc1f00000001c0000, 0xfffffffeffffffff);
+ status |= test__fixdfdi(0xc1f0000000240000, 0xfffffffefffffffe);
+ status |= test__fixdfdi(0xc1f0000000280000, 0xfffffffefffffffe);
+ status |= test__fixdfdi(0xc1f00000002c0000, 0xfffffffefffffffe);
+ status |= test__fixdfdi(0xc1fffffffff40000, 0xfffffffe00000001);
+ status |= test__fixdfdi(0xc1fffffffff80000, 0xfffffffe00000001);
+ status |= test__fixdfdi(0xc1fffffffffc0000, 0xfffffffe00000001);
+ status |= test__fixdfdi(0xc3dfffffffffffff, 0x8000000000000400);
+ status |= test__fixdfdi(0xc3e0000000000000, 0x8000000000000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixdfdi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible signed integer value
+ //
+ // - too-large negative inputs, including -infinity, return the
+ // minimum possible signed integer value
+ //
+ // - NaN inputs return 0
+ status |= test__fixdfdi(0x43e0000000000000, 0x7fffffffffffffff);
+ status |= test__fixdfdi(0x7ff0000000000000, 0x7fffffffffffffff);
+ status |= test__fixdfdi(0x7ff6d1ebdfe15ee3, 0x0000000000000000);
+ status |= test__fixdfdi(0x7ff9a4da74944a09, 0x0000000000000000);
+ status |= test__fixdfdi(0xc3e0000000000001, 0x8000000000000000);
+ status |= test__fixdfdi(0xfff0000000000000, 0x8000000000000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixdfsinew_test.c b/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
new file mode 100644
index 0000000000000..bf3944ea616a0
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
@@ -0,0 +1,96 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixdfsi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from double to int32_t
+COMPILER_RT_ABI int32_t __fixdfsi(double a);
+
+int test__fixdfsi(int line, uint64_t a_rep, uint32_t expected) {
+ double a = fromRep64(a_rep);
+ uint32_t x = (uint32_t)__fixdfsi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixdfsi(%016" PRIx64 ") = %08" PRIx32
+ ", expected %08" PRIx32 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixdfsi(a,x) test__fixdfsi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixdfsi(0x0000000000000000, 0x00000000);
+ status |= test__fixdfsi(0x0000000000000001, 0x00000000);
+ status |= test__fixdfsi(0x380a000000000000, 0x00000000);
+ status |= test__fixdfsi(0x3fd0000000000000, 0x00000000);
+ status |= test__fixdfsi(0x3fe0000000000000, 0x00000000);
+ status |= test__fixdfsi(0x3fe8000000000000, 0x00000000);
+ status |= test__fixdfsi(0x3ff0000000000000, 0x00000001);
+ status |= test__fixdfsi(0x3ff4000000000000, 0x00000001);
+ status |= test__fixdfsi(0x3ff8000000000000, 0x00000001);
+ status |= test__fixdfsi(0x3ffc000000000000, 0x00000001);
+ status |= test__fixdfsi(0x4000000000000000, 0x00000002);
+ status |= test__fixdfsi(0x4002000000000000, 0x00000002);
+ status |= test__fixdfsi(0x4004000000000000, 0x00000002);
+ status |= test__fixdfsi(0x4006000000000000, 0x00000002);
+ status |= test__fixdfsi(0x8000000000000000, 0x00000000);
+ status |= test__fixdfsi(0x8000000000000001, 0x00000000);
+ status |= test__fixdfsi(0xb80a000000000000, 0x00000000);
+ status |= test__fixdfsi(0xbfd0000000000000, 0x00000000);
+ status |= test__fixdfsi(0xbfe0000000000000, 0x00000000);
+ status |= test__fixdfsi(0xbfe8000000000000, 0x00000000);
+ status |= test__fixdfsi(0xbff0000000000000, 0xffffffff);
+ status |= test__fixdfsi(0xbff4000000000000, 0xffffffff);
+ status |= test__fixdfsi(0xbff8000000000000, 0xffffffff);
+ status |= test__fixdfsi(0xbffc000000000000, 0xffffffff);
+ status |= test__fixdfsi(0xc000000000000000, 0xfffffffe);
+ status |= test__fixdfsi(0xc002000000000000, 0xfffffffe);
+ status |= test__fixdfsi(0xc004000000000000, 0xfffffffe);
+ status |= test__fixdfsi(0xc006000000000000, 0xfffffffe);
+ status |= test__fixdfsi(0xc1e0000000000000, 0x80000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixdfsi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible signed integer value
+ //
+ // - too-large negative inputs, including -infinity, return the
+ // minimum possible signed integer value
+ //
+ // - NaN inputs return 0
+ status |= test__fixdfsi(0x41dfffffffffffff, 0x7fffffff);
+ status |= test__fixdfsi(0x41e0000000000000, 0x7fffffff);
+ status |= test__fixdfsi(0x7ff0000000000000, 0x7fffffff);
+ status |= test__fixdfsi(0x7ff6d1ebdfe15ee3, 0x00000000);
+ status |= test__fixdfsi(0x7ff9a4da74944a09, 0x00000000);
+ status |= test__fixdfsi(0xc1e00000001fffff, 0x80000000);
+ status |= test__fixdfsi(0xc1e0000000200000, 0x80000000);
+ status |= test__fixdfsi(0xfff0000000000000, 0x80000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixsfdinew_test.c b/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
new file mode 100644
index 0000000000000..6a719c3140dcc
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
@@ -0,0 +1,100 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixsfdi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from float to int64_t
+COMPILER_RT_ABI int64_t __fixsfdi(float a);
+
+int test__fixsfdi(int line, uint32_t a_rep, uint64_t expected) {
+ float a = fromRep32(a_rep);
+ uint64_t x = (uint64_t)__fixsfdi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixsfdi(%08" PRIx32 ") = %016" PRIx64
+ ", expected %016" PRIx64 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixsfdi(a,x) test__fixsfdi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixsfdi(0x00000000, 0x0000000000000000);
+ status |= test__fixsfdi(0x00000001, 0x0000000000000000);
+ status |= test__fixsfdi(0x00000001, 0x0000000000000000);
+ status |= test__fixsfdi(0x00500000, 0x0000000000000000);
+ status |= test__fixsfdi(0x00500000, 0x0000000000000000);
+ status |= test__fixsfdi(0x3e800000, 0x0000000000000000);
+ status |= test__fixsfdi(0x3f000000, 0x0000000000000000);
+ status |= test__fixsfdi(0x3f400000, 0x0000000000000000);
+ status |= test__fixsfdi(0x3f800000, 0x0000000000000001);
+ status |= test__fixsfdi(0x3fa00000, 0x0000000000000001);
+ status |= test__fixsfdi(0x3fc00000, 0x0000000000000001);
+ status |= test__fixsfdi(0x3fe00000, 0x0000000000000001);
+ status |= test__fixsfdi(0x40000000, 0x0000000000000002);
+ status |= test__fixsfdi(0x40100000, 0x0000000000000002);
+ status |= test__fixsfdi(0x40200000, 0x0000000000000002);
+ status |= test__fixsfdi(0x40300000, 0x0000000000000002);
+ status |= test__fixsfdi(0x55023450, 0x0000082345000000);
+ status |= test__fixsfdi(0x5effffff, 0x7fffff8000000000);
+ status |= test__fixsfdi(0x80000000, 0x0000000000000000);
+ status |= test__fixsfdi(0x80000001, 0x0000000000000000);
+ status |= test__fixsfdi(0x80000001, 0x0000000000000000);
+ status |= test__fixsfdi(0x80500000, 0x0000000000000000);
+ status |= test__fixsfdi(0x80500000, 0x0000000000000000);
+ status |= test__fixsfdi(0xbe800000, 0x0000000000000000);
+ status |= test__fixsfdi(0xbf000000, 0x0000000000000000);
+ status |= test__fixsfdi(0xbf400000, 0x0000000000000000);
+ status |= test__fixsfdi(0xbf800000, 0xffffffffffffffff);
+ status |= test__fixsfdi(0xbfa00000, 0xffffffffffffffff);
+ status |= test__fixsfdi(0xbfc00000, 0xffffffffffffffff);
+ status |= test__fixsfdi(0xbfe00000, 0xffffffffffffffff);
+ status |= test__fixsfdi(0xc0000000, 0xfffffffffffffffe);
+ status |= test__fixsfdi(0xc0100000, 0xfffffffffffffffe);
+ status |= test__fixsfdi(0xc0200000, 0xfffffffffffffffe);
+ status |= test__fixsfdi(0xc0300000, 0xfffffffffffffffe);
+ status |= test__fixsfdi(0xdf000000, 0x8000000000000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixsfdi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible signed integer value
+ //
+ // - too-large negative inputs, including -infinity, return the
+ // minimum possible signed integer value
+ //
+ // - NaN inputs return 0
+ status |= test__fixsfdi(0x5f000000, 0x7fffffffffffffff);
+ status |= test__fixsfdi(0x7f800000, 0x7fffffffffffffff);
+ status |= test__fixsfdi(0x7fa111d3, 0x0000000000000000);
+ status |= test__fixsfdi(0x7febfdda, 0x0000000000000000);
+ status |= test__fixsfdi(0xdf000001, 0x8000000000000000);
+ status |= test__fixsfdi(0xff800000, 0x8000000000000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixsfsinew_test.c b/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
new file mode 100644
index 0000000000000..12475a5e447ee
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
@@ -0,0 +1,99 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixsfsi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from float to int32_t
+COMPILER_RT_ABI int32_t __fixsfsi(float a);
+
+int test__fixsfsi(int line, uint32_t a_rep, uint32_t expected) {
+ float a = fromRep32(a_rep);
+ uint32_t x = (uint32_t)__fixsfsi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixsfsi(%08" PRIx32 ") = %08" PRIx32
+ ", expected %08" PRIx32 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixsfsi(a,x) test__fixsfsi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixsfsi(0x00000000, 0x00000000);
+ status |= test__fixsfsi(0x00000001, 0x00000000);
+ status |= test__fixsfsi(0x00000001, 0x00000000);
+ status |= test__fixsfsi(0x00500000, 0x00000000);
+ status |= test__fixsfsi(0x00500000, 0x00000000);
+ status |= test__fixsfsi(0x3e800000, 0x00000000);
+ status |= test__fixsfsi(0x3f000000, 0x00000000);
+ status |= test__fixsfsi(0x3f400000, 0x00000000);
+ status |= test__fixsfsi(0x3f800000, 0x00000001);
+ status |= test__fixsfsi(0x3fa00000, 0x00000001);
+ status |= test__fixsfsi(0x3fc00000, 0x00000001);
+ status |= test__fixsfsi(0x3fe00000, 0x00000001);
+ status |= test__fixsfsi(0x40000000, 0x00000002);
+ status |= test__fixsfsi(0x40100000, 0x00000002);
+ status |= test__fixsfsi(0x40200000, 0x00000002);
+ status |= test__fixsfsi(0x40300000, 0x00000002);
+ status |= test__fixsfsi(0x4effffff, 0x7fffff80);
+ status |= test__fixsfsi(0x80000000, 0x00000000);
+ status |= test__fixsfsi(0x80000001, 0x00000000);
+ status |= test__fixsfsi(0x80000001, 0x00000000);
+ status |= test__fixsfsi(0x80500000, 0x00000000);
+ status |= test__fixsfsi(0x80500000, 0x00000000);
+ status |= test__fixsfsi(0xbe800000, 0x00000000);
+ status |= test__fixsfsi(0xbf000000, 0x00000000);
+ status |= test__fixsfsi(0xbf400000, 0x00000000);
+ status |= test__fixsfsi(0xbf800000, 0xffffffff);
+ status |= test__fixsfsi(0xbfa00000, 0xffffffff);
+ status |= test__fixsfsi(0xbfc00000, 0xffffffff);
+ status |= test__fixsfsi(0xbfe00000, 0xffffffff);
+ status |= test__fixsfsi(0xc0000000, 0xfffffffe);
+ status |= test__fixsfsi(0xc0100000, 0xfffffffe);
+ status |= test__fixsfsi(0xc0200000, 0xfffffffe);
+ status |= test__fixsfsi(0xc0300000, 0xfffffffe);
+ status |= test__fixsfsi(0xcf000000, 0x80000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixsfsi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible signed integer value
+ //
+ // - too-large negative inputs, including -infinity, return the
+ // minimum possible signed integer value
+ //
+ // - NaN inputs return 0
+ status |= test__fixsfsi(0x4f000000, 0x7fffffff);
+ status |= test__fixsfsi(0x7f800000, 0x7fffffff);
+ status |= test__fixsfsi(0x7fa111d3, 0x00000000);
+ status |= test__fixsfsi(0x7febfdda, 0x00000000);
+ status |= test__fixsfsi(0xcf000001, 0x80000000);
+ status |= test__fixsfsi(0xff800000, 0x80000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c b/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
new file mode 100644
index 0000000000000..9d87469443375
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
@@ -0,0 +1,96 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixunsdfdi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from double to int64_t
+COMPILER_RT_ABI int64_t __fixunsdfdi(double a);
+
+int test__fixunsdfdi(int line, uint64_t a_rep, uint64_t expected) {
+ double a = fromRep64(a_rep);
+ uint64_t x = (uint64_t)__fixunsdfdi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixunsdfdi(%016" PRIx64 ") = %016" PRIx64
+ ", expected %016" PRIx64 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixunsdfdi(a,x) test__fixunsdfdi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixunsdfdi(0x0000000000000000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x0000000000000001, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x0000000000500000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x3fd0000000000000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x3fe0000000000000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x3fe8000000000000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x3ff0000000000000, 0x0000000000000001);
+ status |= test__fixunsdfdi(0x3ff4000000000000, 0x0000000000000001);
+ status |= test__fixunsdfdi(0x3ff8000000000000, 0x0000000000000001);
+ status |= test__fixunsdfdi(0x3ffc000000000000, 0x0000000000000001);
+ status |= test__fixunsdfdi(0x4000000000000000, 0x0000000000000002);
+ status |= test__fixunsdfdi(0x4002000000000000, 0x0000000000000002);
+ status |= test__fixunsdfdi(0x4004000000000000, 0x0000000000000002);
+ status |= test__fixunsdfdi(0x4006000000000000, 0x0000000000000002);
+ status |= test__fixunsdfdi(0x41f0000000040000, 0x0000000100000000);
+ status |= test__fixunsdfdi(0x41f0000000080000, 0x0000000100000000);
+ status |= test__fixunsdfdi(0x41f00000000c0000, 0x0000000100000000);
+ status |= test__fixunsdfdi(0x41f0000000140000, 0x0000000100000001);
+ status |= test__fixunsdfdi(0x41f0000000180000, 0x0000000100000001);
+ status |= test__fixunsdfdi(0x41f00000001c0000, 0x0000000100000001);
+ status |= test__fixunsdfdi(0x41f0000000240000, 0x0000000100000002);
+ status |= test__fixunsdfdi(0x41f0000000280000, 0x0000000100000002);
+ status |= test__fixunsdfdi(0x41f00000002c0000, 0x0000000100000002);
+ status |= test__fixunsdfdi(0x41fffffffff40000, 0x00000001ffffffff);
+ status |= test__fixunsdfdi(0x41fffffffff80000, 0x00000001ffffffff);
+ status |= test__fixunsdfdi(0x41fffffffffc0000, 0x00000001ffffffff);
+ status |= test__fixunsdfdi(0x42a0468ace000000, 0x0000082345670000);
+ status |= test__fixunsdfdi(0x43efffffffffffff, 0xfffffffffffff800);
+ status |= test__fixunsdfdi(0x8000000000000000, 0x0000000000000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixunsdfsi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible unsigned integer value
+ //
+ // - negative inputs too small to round up to 0, including
+ // -infinity, return 0
+ //
+ // - NaN inputs return 0
+ status |= test__fixunsdfdi(0x43f0000000000000, 0xffffffffffffffff);
+ status |= test__fixunsdfdi(0x7ff0000000000000, 0xffffffffffffffff);
+ status |= test__fixunsdfdi(0x7ff6d1ebdfe15ee3, 0x0000000000000000);
+ status |= test__fixunsdfdi(0x7ff9a4da74944a09, 0x0000000000000000);
+ status |= test__fixunsdfdi(0xbfefffffffffffff, 0x0000000000000000);
+ status |= test__fixunsdfdi(0xbff0000000000000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0xc000000000000000, 0x0000000000000000);
+ status |= test__fixunsdfdi(0xfff0000000000000, 0x0000000000000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c b/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
new file mode 100644
index 0000000000000..a15bda5cbecfe
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
@@ -0,0 +1,251 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixunsdfsi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from double to uint32_t
+COMPILER_RT_ABI uint32_t __fixunsdfsi(double a);
+
+int test__fixunsdfsi(int line, uint64_t a_rep, uint32_t expected) {
+ double a = fromRep64(a_rep);
+ int32_t x = __fixunsdfsi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixunsdfsi(%016" PRIx64 ") = %08" PRIx32
+ ", expected %08" PRIx32 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixunsdfsi(a,x) test__fixunsdfsi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixunsdfsi(0x0000000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0x0000000000000001, 0x00000000);
+ status |= test__fixunsdfsi(0x001fffefffffffff, 0x00000000);
+ status |= test__fixunsdfsi(0x002ffffffbffffff, 0x00000000);
+ status |= test__fixunsdfsi(0x380a000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0x3fd0000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0x3fe0000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0x3fe8000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0x3fe8000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0x3ff0000000000000, 0x00000001);
+ status |= test__fixunsdfsi(0x3ff0000000000000, 0x00000001);
+ status |= test__fixunsdfsi(0x3ff3cf3a9243d54d, 0x00000001);
+ status |= test__fixunsdfsi(0x3ff4000000000000, 0x00000001);
+ status |= test__fixunsdfsi(0x3ff8000000000000, 0x00000001);
+ status |= test__fixunsdfsi(0x3ff8000000000000, 0x00000001);
+ status |= test__fixunsdfsi(0x3ff907591158c5d8, 0x00000001);
+ status |= test__fixunsdfsi(0x3ffc000000000000, 0x00000001);
+ status |= test__fixunsdfsi(0x4000000000000000, 0x00000002);
+ status |= test__fixunsdfsi(0x4000000000000000, 0x00000002);
+ status |= test__fixunsdfsi(0x4002000000000000, 0x00000002);
+ status |= test__fixunsdfsi(0x4004000000000000, 0x00000002);
+ status |= test__fixunsdfsi(0x4004000000000000, 0x00000002);
+ status |= test__fixunsdfsi(0x4006000000000000, 0x00000002);
+ status |= test__fixunsdfsi(0x4006882d42e373c2, 0x00000002);
+ status |= test__fixunsdfsi(0x400af556280c2c53, 0x00000003);
+ status |= test__fixunsdfsi(0x400c000000000000, 0x00000003);
+ status |= test__fixunsdfsi(0x4010e2652ca3b655, 0x00000004);
+ status |= test__fixunsdfsi(0x4013752289364b88, 0x00000004);
+ status |= test__fixunsdfsi(0x4018000000000000, 0x00000006);
+ status |= test__fixunsdfsi(0x401a000000000000, 0x00000006);
+ status |= test__fixunsdfsi(0x401e000000000000, 0x00000007);
+ status |= test__fixunsdfsi(0x40213e96e6ee06b6, 0x00000008);
+ status |= test__fixunsdfsi(0x4028cdf10f8a4e54, 0x0000000c);
+ status |= test__fixunsdfsi(0x402c000000000000, 0x0000000e);
+ status |= test__fixunsdfsi(0x402d000000000000, 0x0000000e);
+ status |= test__fixunsdfsi(0x402f000000000000, 0x0000000f);
+ status |= test__fixunsdfsi(0x4030800000000000, 0x00000010);
+ status |= test__fixunsdfsi(0x4034eefd80e0249b, 0x00000014);
+ status |= test__fixunsdfsi(0x4037800000000000, 0x00000017);
+ status |= test__fixunsdfsi(0x403b000000000000, 0x0000001b);
+ status |= test__fixunsdfsi(0x403d6996adec0f09, 0x0000001d);
+ status |= test__fixunsdfsi(0x4041d25097b9ee14, 0x00000023);
+ status |= test__fixunsdfsi(0x4047c00000000000, 0x0000002f);
+ status |= test__fixunsdfsi(0x404b400000000000, 0x00000036);
+ status |= test__fixunsdfsi(0x404c0773be0cb9b7, 0x00000038);
+ status |= test__fixunsdfsi(0x404e000000000000, 0x0000003c);
+ status |= test__fixunsdfsi(0x4051e00000000000, 0x00000047);
+ status |= test__fixunsdfsi(0x4053200000000000, 0x0000004c);
+ status |= test__fixunsdfsi(0x405589958f279d42, 0x00000056);
+ status |= test__fixunsdfsi(0x4059000000000000, 0x00000064);
+ status |= test__fixunsdfsi(0x405ea94c1daf1a78, 0x0000007a);
+ status |= test__fixunsdfsi(0x40615bb017eb1476, 0x0000008a);
+ status |= test__fixunsdfsi(0x4069500000000000, 0x000000ca);
+ status |= test__fixunsdfsi(0x406a22674b8b878f, 0x000000d1);
+ status |= test__fixunsdfsi(0x406bf00000000000, 0x000000df);
+ status |= test__fixunsdfsi(0x406d800000000000, 0x000000ec);
+ status |= test__fixunsdfsi(0x4072d80000000000, 0x0000012d);
+ status |= test__fixunsdfsi(0x40757c8231fe92f1, 0x00000157);
+ status |= test__fixunsdfsi(0x4076a80000000000, 0x0000016a);
+ status |= test__fixunsdfsi(0x4077500000000000, 0x00000175);
+ status |= test__fixunsdfsi(0x407af61b26e4a441, 0x000001af);
+ status |= test__fixunsdfsi(0x4080f40000000000, 0x0000021e);
+ status |= test__fixunsdfsi(0x4081363310b2470c, 0x00000226);
+ status |= test__fixunsdfsi(0x40860c0000000000, 0x000002c1);
+ status |= test__fixunsdfsi(0x408b000000000000, 0x00000360);
+ status |= test__fixunsdfsi(0x408e9aaa9a478b59, 0x000003d3);
+ status |= test__fixunsdfsi(0x4091c67f05129ed4, 0x00000471);
+ status |= test__fixunsdfsi(0x4093a60000000000, 0x000004e9);
+ status |= test__fixunsdfsi(0x4098140000000000, 0x00000605);
+ status |= test__fixunsdfsi(0x409a5a0000000000, 0x00000696);
+ status |= test__fixunsdfsi(0x409ff99df878ad3e, 0x000007fe);
+ status |= test__fixunsdfsi(0x40a3500000000000, 0x000009a8);
+ status |= test__fixunsdfsi(0x40a5598ffcbb08ba, 0x00000aac);
+ status |= test__fixunsdfsi(0x40a956fba09be449, 0x00000cab);
+ status |= test__fixunsdfsi(0x40ab8f0000000000, 0x00000dc7);
+ status |= test__fixunsdfsi(0x40ad090000000000, 0x00000e84);
+ status |= test__fixunsdfsi(0x40b1118000000000, 0x00001111);
+ status |= test__fixunsdfsi(0x40b3bab731bb5e6d, 0x000013ba);
+ status |= test__fixunsdfsi(0x40b6de0000000000, 0x000016de);
+ status |= test__fixunsdfsi(0x40bac06eeb8b97ba, 0x00001ac0);
+ status |= test__fixunsdfsi(0x40bce28000000000, 0x00001ce2);
+ status |= test__fixunsdfsi(0x40c2870000000000, 0x0000250e);
+ status |= test__fixunsdfsi(0x40c84471c85901df, 0x00003088);
+ status |= test__fixunsdfsi(0x40c9c34000000000, 0x00003386);
+ status |= test__fixunsdfsi(0x40cd9b94b71f57ea, 0x00003b37);
+ status |= test__fixunsdfsi(0x40cdc3c000000000, 0x00003b87);
+ status |= test__fixunsdfsi(0x40d00da000000000, 0x00004036);
+ status |= test__fixunsdfsi(0x40d19f4000000000, 0x0000467d);
+ status |= test__fixunsdfsi(0x40d79d704d0443f1, 0x00005e75);
+ status |= test__fixunsdfsi(0x40db84e000000000, 0x00006e13);
+ status |= test__fixunsdfsi(0x40de81403e6071ea, 0x00007a05);
+ status |= test__fixunsdfsi(0x40e2a16f9da2ed87, 0x0000950b);
+ status |= test__fixunsdfsi(0x40e92a3000000000, 0x0000c951);
+ status |= test__fixunsdfsi(0x40e9d5d000000000, 0x0000ceae);
+ status |= test__fixunsdfsi(0x40eb548000000000, 0x0000daa4);
+ status |= test__fixunsdfsi(0x40ec19b6638d34af, 0x0000e0cd);
+ status |= test__fixunsdfsi(0x40f2d4d49a34df18, 0x00012d4d);
+ status |= test__fixunsdfsi(0x40f2de6800000000, 0x00012de6);
+ status |= test__fixunsdfsi(0x40f46b9af08e6ece, 0x000146b9);
+ status |= test__fixunsdfsi(0x40fb2fe000000000, 0x0001b2fe);
+ status |= test__fixunsdfsi(0x40fc81d800000000, 0x0001c81d);
+ status |= test__fixunsdfsi(0x4100669800000000, 0x00020cd3);
+ status |= test__fixunsdfsi(0x4104a6686f29748d, 0x000294cd);
+ status |= test__fixunsdfsi(0x410a1fc576d6489b, 0x000343f8);
+ status |= test__fixunsdfsi(0x410b997400000000, 0x0003732e);
+ status |= test__fixunsdfsi(0x410e962c00000000, 0x0003d2c5);
+ status |= test__fixunsdfsi(0x4113e47a321d351e, 0x0004f91e);
+ status |= test__fixunsdfsi(0x41159158c64c86e2, 0x00056456);
+ status |= test__fixunsdfsi(0x411ce43e00000000, 0x0007390f);
+ status |= test__fixunsdfsi(0x411eacc400000000, 0x0007ab31);
+ status |= test__fixunsdfsi(0x411ee00a00000000, 0x0007b802);
+ status |= test__fixunsdfsi(0x4120eb1f00000000, 0x0008758f);
+ status |= test__fixunsdfsi(0x4121bc002850dcff, 0x0008de00);
+ status |= test__fixunsdfsi(0x4123669100000000, 0x0009b348);
+ status |= test__fixunsdfsi(0x4125458fefa849cd, 0x000aa2c7);
+ status |= test__fixunsdfsi(0x412c5f6600000000, 0x000e2fb3);
+ status |= test__fixunsdfsi(0x41311f349fdd064e, 0x00111f34);
+ status |= test__fixunsdfsi(0x4135e3c47a5a7295, 0x0015e3c4);
+ status |= test__fixunsdfsi(0x413bb95a80000000, 0x001bb95a);
+ status |= test__fixunsdfsi(0x413dc4b980000000, 0x001dc4b9);
+ status |= test__fixunsdfsi(0x413dded700000000, 0x001dded7);
+ status |= test__fixunsdfsi(0x4143339380000000, 0x00266727);
+ status |= test__fixunsdfsi(0x4143f42f7838cebe, 0x0027e85e);
+ status |= test__fixunsdfsi(0x4148d71240000000, 0x0031ae24);
+ status |= test__fixunsdfsi(0x414f8b46986123ff, 0x003f168d);
+ status |= test__fixunsdfsi(0x414fc468c0000000, 0x003f88d1);
+ status |= test__fixunsdfsi(0x4152d16760000000, 0x004b459d);
+ status |= test__fixunsdfsi(0x41559b87ac7fd1fb, 0x00566e1e);
+ status |= test__fixunsdfsi(0x415679a847497583, 0x0059e6a1);
+ status |= test__fixunsdfsi(0x41568d0e20000000, 0x005a3438);
+ status |= test__fixunsdfsi(0x415efb4d80000000, 0x007bed36);
+ status |= test__fixunsdfsi(0x41603a2370000000, 0x0081d11b);
+ status |= test__fixunsdfsi(0x4160d14709ee668a, 0x00868a38);
+ status |= test__fixunsdfsi(0x416705f510000000, 0x00b82fa8);
+ status |= test__fixunsdfsi(0x41678a2eb167a88f, 0x00bc5175);
+ status |= test__fixunsdfsi(0x416dc05b40000000, 0x00ee02da);
+ status |= test__fixunsdfsi(0x41730fb978000000, 0x0130fb97);
+ status |= test__fixunsdfsi(0x417395a4a66fca01, 0x01395a4a);
+ status |= test__fixunsdfsi(0x41756ef08b6d5dd0, 0x0156ef08);
+ status |= test__fixunsdfsi(0x4179efdb00000000, 0x019efdb0);
+ status |= test__fixunsdfsi(0x417b4f6208000000, 0x01b4f620);
+ status |= test__fixunsdfsi(0x4180907a07f893a5, 0x02120f40);
+ status |= test__fixunsdfsi(0x41862857dc000000, 0x02c50afb);
+ status |= test__fixunsdfsi(0x4187df63b4000000, 0x02fbec76);
+ status |= test__fixunsdfsi(0x418c997fa8000000, 0x03932ff5);
+ status |= test__fixunsdfsi(0x418ee2d28aa63b87, 0x03dc5a51);
+ status |= test__fixunsdfsi(0x419306468a000000, 0x04c191a2);
+ status |= test__fixunsdfsi(0x41948b47dbc198b6, 0x0522d1f6);
+ status |= test__fixunsdfsi(0x4195be8a08000000, 0x056fa282);
+ status |= test__fixunsdfsi(0x419acb35e46baf44, 0x06b2cd79);
+ status |= test__fixunsdfsi(0x419ec43dfe000000, 0x07b10f7f);
+ status |= test__fixunsdfsi(0x41a68e6716000000, 0x0b47338b);
+ status |= test__fixunsdfsi(0x41a893264f33d251, 0x0c499327);
+ status |= test__fixunsdfsi(0x41af11d19d000000, 0x0f88e8ce);
+ status |= test__fixunsdfsi(0x41af241394ce98da, 0x0f9209ca);
+ status |= test__fixunsdfsi(0x41afb8d0b7000000, 0x0fdc685b);
+ status |= test__fixunsdfsi(0x41b1a63370800000, 0x11a63370);
+ status |= test__fixunsdfsi(0x41b23df14b800000, 0x123df14b);
+ status |= test__fixunsdfsi(0x41b6f2d50149e2d9, 0x16f2d501);
+ status |= test__fixunsdfsi(0x41ba1aa592000000, 0x1a1aa592);
+ status |= test__fixunsdfsi(0x41bf53402fd53daa, 0x1f53402f);
+ status |= test__fixunsdfsi(0x41c18548afc00000, 0x230a915f);
+ status |= test__fixunsdfsi(0x41c2e365e5345a6b, 0x25c6cbca);
+ status |= test__fixunsdfsi(0x41c4492dac400000, 0x28925b58);
+ status |= test__fixunsdfsi(0x41ca895f94000000, 0x3512bf28);
+ status |= test__fixunsdfsi(0x41ccc3e5f1e5b560, 0x3987cbe3);
+ status |= test__fixunsdfsi(0x41d01a143e200000, 0x406850f8);
+ status |= test__fixunsdfsi(0x41d01d7605400000, 0x4075d815);
+ status |= test__fixunsdfsi(0x41ddcda3abe00000, 0x77368eaf);
+ status |= test__fixunsdfsi(0x41de53dafe34e730, 0x794f6bf8);
+ status |= test__fixunsdfsi(0x41df843af68a9ef5, 0x7e10ebda);
+ status |= test__fixunsdfsi(0x41e2c728e4400000, 0x96394722);
+ status |= test__fixunsdfsi(0x41e950d535f00000, 0xca86a9af);
+ status |= test__fixunsdfsi(0x41e9afe08a500000, 0xcd7f0452);
+ status |= test__fixunsdfsi(0x41eb81ce4bd25eaa, 0xdc0e725e);
+ status |= test__fixunsdfsi(0x41ef6975dbc19d7a, 0xfb4baede);
+ status |= test__fixunsdfsi(0x8000000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0xb818000000000000, 0x00000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixunsdfsi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible unsigned integer value
+ //
+ // - negative inputs too small to round up to 0, including
+ // -infinity, return 0
+ //
+ // - NaN inputs return 0
+ status |= test__fixunsdfsi(0x41efffffffffffff, 0xffffffff);
+ status |= test__fixunsdfsi(0x41f0000000000000, 0xffffffff);
+ status |= test__fixunsdfsi(0x41f37bc9c8400000, 0xffffffff);
+ status |= test__fixunsdfsi(0x41f3c0b771e5a126, 0xffffffff);
+ status |= test__fixunsdfsi(0x41fb837587480000, 0xffffffff);
+ status |= test__fixunsdfsi(0x41fc069b87f80000, 0xffffffff);
+ status |= test__fixunsdfsi(0x41feea6325bf9a55, 0xffffffff);
+ status |= test__fixunsdfsi(0x7ff0000000000000, 0xffffffff);
+ status |= test__fixunsdfsi(0x7ff6d1ebdfe15ee3, 0x00000000);
+ status |= test__fixunsdfsi(0x7ff9a4da74944a09, 0x00000000);
+ status |= test__fixunsdfsi(0xbfefffffffffffff, 0x00000000);
+ status |= test__fixunsdfsi(0xbff0000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0xc000000000000000, 0x00000000);
+ status |= test__fixunsdfsi(0xfff0000000000000, 0x00000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c b/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
new file mode 100644
index 0000000000000..43021f4d9490c
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
@@ -0,0 +1,86 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixunssfdi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from float to int64_t
+COMPILER_RT_ABI int64_t __fixunssfdi(float a);
+
+int test__fixunssfdi(int line, uint32_t a_rep, uint64_t expected) {
+ float a = fromRep32(a_rep);
+ uint64_t x = (uint64_t)__fixunssfdi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixunssfdi(%08" PRIx32 ") = %016" PRIx64
+ ", expected %016" PRIx64 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixunssfdi(a,x) test__fixunssfdi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixunssfdi(0x00000000, 0x0000000000000000);
+ status |= test__fixunssfdi(0x00000001, 0x0000000000000000);
+ status |= test__fixunssfdi(0x00000001, 0x0000000000000000);
+ status |= test__fixunssfdi(0x00500000, 0x0000000000000000);
+ status |= test__fixunssfdi(0x00500000, 0x0000000000000000);
+ status |= test__fixunssfdi(0x3e800000, 0x0000000000000000);
+ status |= test__fixunssfdi(0x3f000000, 0x0000000000000000);
+ status |= test__fixunssfdi(0x3f400000, 0x0000000000000000);
+ status |= test__fixunssfdi(0x3f800000, 0x0000000000000001);
+ status |= test__fixunssfdi(0x3fa00000, 0x0000000000000001);
+ status |= test__fixunssfdi(0x3fc00000, 0x0000000000000001);
+ status |= test__fixunssfdi(0x3fe00000, 0x0000000000000001);
+ status |= test__fixunssfdi(0x40000000, 0x0000000000000002);
+ status |= test__fixunssfdi(0x40100000, 0x0000000000000002);
+ status |= test__fixunssfdi(0x40200000, 0x0000000000000002);
+ status |= test__fixunssfdi(0x40300000, 0x0000000000000002);
+ status |= test__fixunssfdi(0x55023450, 0x0000082345000000);
+ status |= test__fixunssfdi(0x5f7fffff, 0xffffff0000000000);
+ status |= test__fixunssfdi(0x80000000, 0x0000000000000000);
+ status |= test__fixunssfdi(0xbf7fffff, 0x0000000000000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixunssfsi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible unsigned integer value
+ //
+ // - negative inputs too small to round up to 0, including
+ // -infinity, return 0
+ //
+ // - NaN inputs return 0
+ status |= test__fixunssfdi(0x5f800000, 0xffffffffffffffff);
+ status |= test__fixunssfdi(0x7f800000, 0xffffffffffffffff);
+ status |= test__fixunssfdi(0x7fa111d3, 0x0000000000000000);
+ status |= test__fixunssfdi(0x7febfdda, 0x0000000000000000);
+ status |= test__fixunssfdi(0xbf800000, 0x0000000000000000);
+ status |= test__fixunssfdi(0xc0000000, 0x0000000000000000);
+ status |= test__fixunssfdi(0xff800000, 0x0000000000000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
diff --git a/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c b/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
new file mode 100644
index 0000000000000..0f2774c71686e
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
@@ -0,0 +1,85 @@
+// 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
+
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_fixunssfsi
+
+#include "int_lib.h"
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// By default this test does not specify the expected results for overflowing
+// and NaN inputs, because they can vary between platforms. For the Arm
+// optimized FP implementation, which commits to more detail, we include some
+// extra test cases specific to that NaN policy.
+#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#define ARM_INVALID_HANDLING
+#endif
+
+// Returns: a converted from float to uint32_t
+COMPILER_RT_ABI uint32_t __fixunssfsi(float a);
+
+int test__fixunssfsi(int line, uint32_t a_rep, uint32_t expected) {
+ float a = fromRep32(a_rep);
+ int32_t x = __fixunssfsi(a);
+ int ret = x != expected;
+
+ if (ret) {
+ printf("error at line %d: __fixunssfsi(%08" PRIx32 ") = %08" PRIx32
+ ", expected %08" PRIx32 "\n",
+ line, a_rep, x, expected);
+ }
+ return ret;
+}
+
+#define test__fixunssfsi(a,x) test__fixunssfsi(__LINE__,a,x)
+
+int main(void) {
+ int status = 0;
+
+ status |= test__fixunssfsi(0x00000000, 0x00000000);
+ status |= test__fixunssfsi(0x00000001, 0x00000000);
+ status |= test__fixunssfsi(0x00000001, 0x00000000);
+ status |= test__fixunssfsi(0x00500000, 0x00000000);
+ status |= test__fixunssfsi(0x00500000, 0x00000000);
+ status |= test__fixunssfsi(0x3e800000, 0x00000000);
+ status |= test__fixunssfsi(0x3f000000, 0x00000000);
+ status |= test__fixunssfsi(0x3f400000, 0x00000000);
+ status |= test__fixunssfsi(0x3f800000, 0x00000001);
+ status |= test__fixunssfsi(0x3fa00000, 0x00000001);
+ status |= test__fixunssfsi(0x3fc00000, 0x00000001);
+ status |= test__fixunssfsi(0x3fe00000, 0x00000001);
+ status |= test__fixunssfsi(0x40000000, 0x00000002);
+ status |= test__fixunssfsi(0x40100000, 0x00000002);
+ status |= test__fixunssfsi(0x40200000, 0x00000002);
+ status |= test__fixunssfsi(0x40300000, 0x00000002);
+ status |= test__fixunssfsi(0x4f7fffff, 0xffffff00);
+ status |= test__fixunssfsi(0x80000000, 0x00000000);
+ status |= test__fixunssfsi(0xbf7fffff, 0x00000000);
+
+#ifdef ARM_INVALID_HANDLING
+ // Tests specific to the handling of float-to-integer conversions in
+ // Arm hardware, mimicked by arm/fixunssfsi.S:
+ //
+ // - too-large positive inputs, including +infinity, return the
+ // maximum possible unsigned integer value
+ //
+ // - negative inputs too small to round up to 0, including
+ // -infinity, return 0
+ //
+ // - NaN inputs return 0
+ status |= test__fixunssfsi(0x4f800000, 0xffffffff);
+ status |= test__fixunssfsi(0x7f800000, 0xffffffff);
+ status |= test__fixunssfsi(0x7fa111d3, 0x00000000);
+ status |= test__fixunssfsi(0x7febfdda, 0x00000000);
+ status |= test__fixunssfsi(0xbf800000, 0x00000000);
+ status |= test__fixunssfsi(0xc0000000, 0x00000000);
+ status |= test__fixunssfsi(0xff800000, 0x00000000);
+
+#endif // ARM_INVALID_HANDLING
+
+ return status;
+}
>From 1221fb6b79ffd828ab55d4a82c7028aeb6c34b5e Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 5 Feb 2026 17:25:44 +0000
Subject: [PATCH 2/3] clang-format
---
compiler-rt/test/builtins/Unit/fixdfdinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixdfsinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixsfdinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixsfsinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixunssfdinew_test.c | 4 ++--
compiler-rt/test/builtins/Unit/fixunssfsinew_test.c | 4 ++--
8 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/compiler-rt/test/builtins/Unit/fixdfdinew_test.c b/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
index a8bcbf72fd349..1f0dbb3411724 100644
--- a/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to int64_t
@@ -35,7 +35,7 @@ int test__fixdfdi(int line, uint64_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixdfdi(a,x) test__fixdfdi(__LINE__,a,x)
+#define test__fixdfdi(a, x) test__fixdfdi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixdfsinew_test.c b/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
index bf3944ea616a0..7ddf04b6e68e1 100644
--- a/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to int32_t
@@ -35,7 +35,7 @@ int test__fixdfsi(int line, uint64_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixdfsi(a,x) test__fixdfsi(__LINE__,a,x)
+#define test__fixdfsi(a, x) test__fixdfsi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixsfdinew_test.c b/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
index 6a719c3140dcc..d624fd1684d6d 100644
--- a/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to int64_t
@@ -35,7 +35,7 @@ int test__fixsfdi(int line, uint32_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixsfdi(a,x) test__fixsfdi(__LINE__,a,x)
+#define test__fixsfdi(a, x) test__fixsfdi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixsfsinew_test.c b/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
index 12475a5e447ee..f1adba5ec118f 100644
--- a/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to int32_t
@@ -35,7 +35,7 @@ int test__fixsfsi(int line, uint32_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixsfsi(a,x) test__fixsfsi(__LINE__,a,x)
+#define test__fixsfsi(a, x) test__fixsfsi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c b/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
index 9d87469443375..7074a727c052d 100644
--- a/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to int64_t
@@ -35,7 +35,7 @@ int test__fixunsdfdi(int line, uint64_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixunsdfdi(a,x) test__fixunsdfdi(__LINE__,a,x)
+#define test__fixunsdfdi(a, x) test__fixunsdfdi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c b/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
index a15bda5cbecfe..056c3241b97a4 100644
--- a/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to uint32_t
@@ -35,7 +35,7 @@ int test__fixunsdfsi(int line, uint64_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixunsdfsi(a,x) test__fixunsdfsi(__LINE__,a,x)
+#define test__fixunsdfsi(a, x) test__fixunsdfsi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c b/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
index 43021f4d9490c..d0f5796e938c1 100644
--- a/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to int64_t
@@ -35,7 +35,7 @@ int test__fixunssfdi(int line, uint32_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixunssfdi(a,x) test__fixunssfdi(__LINE__,a,x)
+#define test__fixunssfdi(a, x) test__fixunssfdi(__LINE__, a, x)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c b/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
index 0f2774c71686e..70d05a2876734 100644
--- a/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
@@ -16,7 +16,7 @@
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
-#define ARM_INVALID_HANDLING
+# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to uint32_t
@@ -35,7 +35,7 @@ int test__fixunssfsi(int line, uint32_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixunssfsi(a,x) test__fixunssfsi(__LINE__,a,x)
+#define test__fixunssfsi(a, x) test__fixunssfsi(__LINE__, a, x)
int main(void) {
int status = 0;
>From 6805026af35144b6e89e6e213d4e212e8dbb2b03 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Tue, 24 Feb 2026 16:46:22 +0000
Subject: [PATCH 3/3] Update tests to match #179918
---
compiler-rt/test/builtins/Unit/fixdfdinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixdfsinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixsfdinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixsfsinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixunssfdinew_test.c | 6 +++---
compiler-rt/test/builtins/Unit/fixunssfsinew_test.c | 6 +++---
8 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/compiler-rt/test/builtins/Unit/fixdfdinew_test.c b/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
index 1f0dbb3411724..9c9f38c0424a5 100644
--- a/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixdfdinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to int64_t
COMPILER_RT_ABI int64_t __fixdfdi(double a);
-int test__fixdfdi(int line, uint64_t a_rep, uint64_t expected) {
+int test__fixdfdi(uint64_t a_rep, uint64_t expected, int line) {
double a = fromRep64(a_rep);
uint64_t x = (uint64_t)__fixdfdi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixdfdi(int line, uint64_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixdfdi(a, x) test__fixdfdi(__LINE__, a, x)
+#define test__fixdfdi(a, x) test__fixdfdi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixdfsinew_test.c b/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
index 7ddf04b6e68e1..807ceffb32913 100644
--- a/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixdfsinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to int32_t
COMPILER_RT_ABI int32_t __fixdfsi(double a);
-int test__fixdfsi(int line, uint64_t a_rep, uint32_t expected) {
+int test__fixdfsi(uint64_t a_rep, uint32_t expected, int line) {
double a = fromRep64(a_rep);
uint32_t x = (uint32_t)__fixdfsi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixdfsi(int line, uint64_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixdfsi(a, x) test__fixdfsi(__LINE__, a, x)
+#define test__fixdfsi(a, x) test__fixdfsi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixsfdinew_test.c b/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
index d624fd1684d6d..4474d17497358 100644
--- a/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixsfdinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to int64_t
COMPILER_RT_ABI int64_t __fixsfdi(float a);
-int test__fixsfdi(int line, uint32_t a_rep, uint64_t expected) {
+int test__fixsfdi(uint32_t a_rep, uint64_t expected, int line) {
float a = fromRep32(a_rep);
uint64_t x = (uint64_t)__fixsfdi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixsfdi(int line, uint32_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixsfdi(a, x) test__fixsfdi(__LINE__, a, x)
+#define test__fixsfdi(a, x) test__fixsfdi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixsfsinew_test.c b/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
index f1adba5ec118f..833aeae79bab3 100644
--- a/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixsfsinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to int32_t
COMPILER_RT_ABI int32_t __fixsfsi(float a);
-int test__fixsfsi(int line, uint32_t a_rep, uint32_t expected) {
+int test__fixsfsi(uint32_t a_rep, uint32_t expected, int line) {
float a = fromRep32(a_rep);
uint32_t x = (uint32_t)__fixsfsi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixsfsi(int line, uint32_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixsfsi(a, x) test__fixsfsi(__LINE__, a, x)
+#define test__fixsfsi(a, x) test__fixsfsi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c b/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
index 7074a727c052d..d3a64e7a3998a 100644
--- a/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunsdfdinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to int64_t
COMPILER_RT_ABI int64_t __fixunsdfdi(double a);
-int test__fixunsdfdi(int line, uint64_t a_rep, uint64_t expected) {
+int test__fixunsdfdi(uint64_t a_rep, uint64_t expected, int line) {
double a = fromRep64(a_rep);
uint64_t x = (uint64_t)__fixunsdfdi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixunsdfdi(int line, uint64_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixunsdfdi(a, x) test__fixunsdfdi(__LINE__, a, x)
+#define test__fixunsdfdi(a, x) test__fixunsdfdi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c b/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
index 056c3241b97a4..53dce09fa4d88 100644
--- a/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunsdfsinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from double to uint32_t
COMPILER_RT_ABI uint32_t __fixunsdfsi(double a);
-int test__fixunsdfsi(int line, uint64_t a_rep, uint32_t expected) {
+int test__fixunsdfsi(uint64_t a_rep, uint32_t expected, int line) {
double a = fromRep64(a_rep);
int32_t x = __fixunsdfsi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixunsdfsi(int line, uint64_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixunsdfsi(a, x) test__fixunsdfsi(__LINE__, a, x)
+#define test__fixunsdfsi(a, x) test__fixunsdfsi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c b/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
index d0f5796e938c1..98c28db04eb80 100644
--- a/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunssfdinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to int64_t
COMPILER_RT_ABI int64_t __fixunssfdi(float a);
-int test__fixunssfdi(int line, uint32_t a_rep, uint64_t expected) {
+int test__fixunssfdi(uint32_t a_rep, uint64_t expected, int line) {
float a = fromRep32(a_rep);
uint64_t x = (uint64_t)__fixunssfdi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixunssfdi(int line, uint32_t a_rep, uint64_t expected) {
return ret;
}
-#define test__fixunssfdi(a, x) test__fixunssfdi(__LINE__, a, x)
+#define test__fixunssfdi(a, x) test__fixunssfdi(a, x, __LINE__)
int main(void) {
int status = 0;
diff --git a/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c b/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
index 70d05a2876734..882ec8b7fd72f 100644
--- a/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
+++ b/compiler-rt/test/builtins/Unit/fixunssfsinew_test.c
@@ -15,14 +15,14 @@
// and NaN inputs, because they can vary between platforms. For the Arm
// optimized FP implementation, which commits to more detail, we include some
// extra test cases specific to that NaN policy.
-#if (__arm__ && !(__thumb__ && !__thumb2__)) && COMPILER_RT_ARM_OPTIMIZED_FP
+#if COMPILER_RT_ARM_OPTIMIZED_FP
# define ARM_INVALID_HANDLING
#endif
// Returns: a converted from float to uint32_t
COMPILER_RT_ABI uint32_t __fixunssfsi(float a);
-int test__fixunssfsi(int line, uint32_t a_rep, uint32_t expected) {
+int test__fixunssfsi(uint32_t a_rep, uint32_t expected, int line) {
float a = fromRep32(a_rep);
int32_t x = __fixunssfsi(a);
int ret = x != expected;
@@ -35,7 +35,7 @@ int test__fixunssfsi(int line, uint32_t a_rep, uint32_t expected) {
return ret;
}
-#define test__fixunssfsi(a, x) test__fixunssfsi(__LINE__, a, x)
+#define test__fixunssfsi(a, x) test__fixunssfsi(a, x, __LINE__)
int main(void) {
int status = 0;
More information about the llvm-branch-commits
mailing list