https://github.com/statham-arm created https://github.com/llvm/llvm-project/pull/179924
The structure of these comparison functions consists of a header file containing the main code, and several `.S` files that include that header with different macro definitions, so that they can use the same procedure to determine the logical comparison result and then just translate it into a return value in different ways. >From c334fe75b5bc92469650b792a713341cb6be81a4 Mon Sep 17 00:00:00 2001 From: Simon Tatham <[email protected]> Date: Thu, 29 Jan 2026 16:09:19 +0000 Subject: [PATCH] [compiler-rt][ARM] Optimized double-precision FP comparisons The structure of these comparison functions consists of a header file containing the main code, and several `.S` files that include that header with different macro definitions, so that they can use the same procedure to determine the logical comparison result and then just translate it into a return value in different ways. --- compiler-rt/lib/builtins/CMakeLists.txt | 8 + compiler-rt/lib/builtins/arm/cmpdf2.S | 64 ++ compiler-rt/lib/builtins/arm/dcmp.h | 210 ++++++ compiler-rt/lib/builtins/arm/gedf2.S | 61 ++ compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S | 61 ++ compiler-rt/lib/builtins/arm/thumb1/dcmp.h | 236 +++++++ compiler-rt/lib/builtins/arm/thumb1/gedf2.S | 60 ++ .../lib/builtins/arm/thumb1/unorddf2.S | 60 ++ compiler-rt/lib/builtins/arm/unorddf2.S | 71 ++ .../test/builtins/Unit/comparedf2new_test.c | 609 ++++++++++++++++++ 10 files changed, 1440 insertions(+) create mode 100644 compiler-rt/lib/builtins/arm/cmpdf2.S create mode 100644 compiler-rt/lib/builtins/arm/dcmp.h create mode 100644 compiler-rt/lib/builtins/arm/gedf2.S create mode 100644 compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S create mode 100644 compiler-rt/lib/builtins/arm/thumb1/dcmp.h create mode 100644 compiler-rt/lib/builtins/arm/thumb1/gedf2.S create mode 100644 compiler-rt/lib/builtins/arm/thumb1/unorddf2.S create mode 100644 compiler-rt/lib/builtins/arm/unorddf2.S create mode 100644 compiler-rt/test/builtins/Unit/comparedf2new_test.c diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index b8e328f657eea..0e8b0fa553442 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -450,6 +450,9 @@ if(COMPILER_RT_ARM_OPTIMIZED_FP AND BUILTIN_SUPPORTED_ARCH MATCHES "arm") arm/adddf3.S arm/muldf3.S arm/divdf3.S + arm/cmpdf2.S + arm/gedf2.S + arm/unorddf2.S ) set_source_files_properties(${assembly_files} PROPERTIES COMPILE_OPTIONS ${implicit_it_flag}) @@ -503,11 +506,16 @@ set_property(SOURCE arm/adddf3.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY cr if(COMPILER_RT_ARM_OPTIMIZED_FP) set(thumb1_base_SOURCES arm/thumb1/mulsf3.S + arm/thumb1/cmpdf2.S + arm/thumb1/gedf2.S + arm/thumb1/unorddf2.S arm/fnan2.c arm/fnorm2.c arm/funder.c ${thumb1_base_SOURCES} ) + set_property(SOURCE arm/thumb1/cmpdf2.S PROPERTY crt_supersedes comparedf2.c) + set_property(SOURCE arm/thumb1/cmpdf2.S DIRECTORY ${COMPILER_RT_SOURCE_DIR} PROPERTY crt_provides comparedf2) endif() set(arm_EABI_RT_SOURCES diff --git a/compiler-rt/lib/builtins/arm/cmpdf2.S b/compiler-rt/lib/builtins/arm/cmpdf2.S new file mode 100644 index 0000000000000..587c3f619f8ae --- /dev/null +++ b/compiler-rt/lib/builtins/arm/cmpdf2.S @@ -0,0 +1,64 @@ +//===-- cmpdf2.S - double-precision floating point comparison -------------===// +// +// 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 function has the semantics of GNU __cmpdf2: it's a three-way compare +// which returns <0 if x<y, 0 if x==y, and >0 if x>y. If the result is +// unordered (i.e. x or y or both is NaN) then it returns >0. +// +// This also makes it suitable for use as all of __eqdf2, __nedf2, __ltdf2 or +// __ledf2. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" +#include "endian.h" + + .syntax unified + .text + .p2align 2 + + +op0h .req xh +op0l .req xl +op1h .req yh +op1l .req yl +.macro SetReturnRegister + mov r0, #0 + movhi r0, #1 + movlo r0, #-1 +.endm +.macro SetReturnRegisterNE + movne r0, #-1 + movhi r0, #1 +.endm + +#if __ARM_PCS_VFP +DEFINE_COMPILERRT_FUNCTION(__cmpdf2) + push {r4, lr} + VMOV_FROM_DOUBLE(r0, r1, d0) + VMOV_FROM_DOUBLE(r2, r3, d1) + bl __compiler_rt_softfp_cmpdf2 + pop {r4, pc} +#else +DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpdf2, __compiler_rt_softfp_cmpdf2) +#endif +DEFINE_COMPILERRT_FUNCTION_ALIAS(__ledf2, __cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltdf2, __cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__eqdf2, __cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__nedf2, __cmpdf2) + +DEFINE_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpdf2) + #include "dcmp.h" + +LOCAL_LABEL(NaN): + mov r0, #+1 + bx lr + +END_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpdf2) + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/builtins/arm/dcmp.h b/compiler-rt/lib/builtins/arm/dcmp.h new file mode 100644 index 0000000000000..c9fd0ef324365 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/dcmp.h @@ -0,0 +1,210 @@ +//===-- dcmp.h - shared code for double-precision FP comparison functions -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This code is the skeleton of a double-precision FP compare, with two details +// left out: which input value is in which register, and how to make the return +// value. It allows the main comparison logic to be shared between (for +// example) __ledf2 and __gedf2, varying only those details. +// +//===----------------------------------------------------------------------===// + +// How to use this header file: +// +// This header file is expected to be #included from inside a function +// definition in a .S file. The source file including this header should +// provide the following: +// +// op0h, op0l, op1h, op1l: register aliases (via .req) for the registers +// containing the input operands. +// - For most comparisons, op0h,op0l will correspond to ah,al, and op1h,op1l +// to bh,bl (as defined in turn in endian.h). +// - But a function with the reversed semantics of __aeabi_cdrcmple wil define +// them the other way round. +// +// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up +// an appropriate return value in r0, for the cases that do *not* involve NaN. +// - On entry to this macro, the condition codes LO, EQ and HI indicate that +// op0 < op1, op0 == op1 or op0 > op1 respectively. +// - For functions that return a result in the flags, this macro can be empty, +// because those are the correct flags to return anyway. +// - Functions that return a boolean in r0 should set it up by checking the +// flags. +// +// SetReturnRegisterNE: a macro that does the same thing as SetReturnRegister, +// except that if the Z flag is set, it instead does nothing at all. (This +// macro must not assume that the flags were set by a single CMP: in +// particular, C=0 but Z=1 is possible on entry to this macro, so you must not +// use the LO condition code and assume it is mutually exclusive with EQ.) +// +// LOCAL_LABEL(NaN): a label defined within the compare function, after the +// #include of this header. Called when at least one input is a NaN, and sets +// up the appropriate return value for that case. + +// -------------------------------------------------- +// The actual entry point of the compare function. +// +// The basic plan is to start by ORing together the two inputs. This tells us +// two things: +// - the top bit of the output tells us whether both inputs are positive, or +// whether at least one is negative +// - if the 11 exponent bits of the output are not all 1, then there are +// definitely no NaNs, so a fast path can handle most non-NaN cases. + + // First diverge control for the negative-numbers case. + orrs r12, op0h, op1h + bmi LOCAL_LABEL(negative) // high bit set => at least one negative input + + // Here, both inputs are positive. Try adding 1<<20 to their bitwise OR in + // r12. This will carry all the way into the top bit, setting the N flag, if + // all 11 exponent bits were set. + cmn r12, #1 << 20 + bmi LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs + + // The fastest fast path: both inputs positive and we could easily tell there + // were no NaNs. So we just compare op0 and op1 as unsigned integers. + cmp op0h, op1h + SetReturnRegisterNE + bxne lr + cmp op0l, op1l + SetReturnRegister + bx lr + +LOCAL_LABEL(NaNInf_check_positive): + // Second tier for positive numbers. We come here if both inputs are + // positive, but our fast initial check didn't manage to rule out a NaN. But + // it's not guaranteed that there _is_ a NaN, for two reasons: + // + // 1. An input with exponent 0x7FF might be an infinity instead. Those + // behave normally under comparison. + // + // 2. There might not even _be_ an input with exponent 0x7FF. All we know so + // far is that the two inputs ORed together had all the exponent bits + // set. So each of those bits is set in _at least one_ of the inputs, but + // not necessarily all in the _same_ input. + // + // Test each exponent individually for 0x7FF, using the same CMN idiom as + // above. If neither one carries into the sign bit then we have no NaNs _or_ + // infinities and can compare the registers and return again. + cmn op0h, #1 << 20 + cmnpl op1h, #1 << 20 + bmi LOCAL_LABEL(NaN_check_positive) + + // Second-tier return path, now we've ruled out anything difficult. By this + // time we know that the two operands have different exponents (because the + // exponents' bitwise OR is 0x7FF but neither one is 0x7FF by itself, so each + // must have a set bit not present in the other). So we only need to compare + // the high words. + cmp op0h, op1h + SetReturnRegister + bx lr + +LOCAL_LABEL(NaN_check_positive): + // Third tier for positive numbers. Here we know that at least one of the + // inputs has exponent 0x7FF. But they might still be infinities rather than + // NaNs. So now we must check whether there's an actual NaN. + // + // We do this by shifting the high word of each input left to get rid of the + // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in + // the low word. Then we check if the result is _greater_ than 0xFFE00000 + // (but not equal), via adding 0x00200000 to it and testing for the HI + // condition (carry flag set, but Z clear). + // + // We could have skipped the second-tier check and done this more rigorous + // test immediately. But that would cost an extra instruction in the case + // where there are no infinities or NaNs, and we assume that that is so much + // more common that it's worth optimizing for. + cmp op0l, #1 // set C if op0l is nonzero + adc op0h, op0h, op0h // shift op0h left, bringing in the C bit + cmp op1l, #1 // set C if op1l is nonzero + adc op1h, op1h, op1h // shift op1h left, bringing in the C bit + cmn op0h, #1 << 21 // if HI, then op0 is a NaN + cmnls op1h, #1 << 21 // if not HI, then do the same check for op1 + bhi LOCAL_LABEL(NaN) // now, if HI, there's definitely a NaN + + // Now we've finally ruled out NaNs! And we still know both inputs are + // positive. So the third-tier return path can just compare the top words + // again. (The fact that we've just shifted them left doesn't make a + // difference.) + cmp op0h, op1h + SetReturnRegister + bx lr + +LOCAL_LABEL(negative): + // We come here if at least one operand is negative. We haven't checked for + // NaNs at all yet (the sign check came first), so repeat the first-tier + // check strategy of seeing if all exponent bits are set in r12. + // + // On this path, the sign bit in r12 is set, so if adding 1 to the low + // exponent bit carries all the way through into the sign bit, it will + // _clear_ the sign bit rather than setting it. So we expect MI to be the + // "definitely no NaNs" result, where it was PL on the positive branch. + cmn r12, #1 << 20 + bpl LOCAL_LABEL(NaNInf_check_negative) + + // Now we have no NaNs, but at least one negative number. This gives us two + // complications: + // + // 1. Floating-point numbers are sign/magnitude, not two's complement, so we + // have to consider separately the cases of "both negative" and "one of + // each sign". + // + // 2. -0 and +0 are required to compare equal. + // + // But problem #1 is not as hard as it sounds! If both operands are negative, + // then we can get the result we want by comparing them as unsigned integers + // the opposite way round, because the input with the smaller value (as an + // integer) is the larger number in an FP ordering sense. And if one operand + // is negative and the other is positive, the _same_ reversed comparison + // works, because the positive number (with zero sign bit) will always + // compare less than the negative one in an unsigned-integers sense. + // + // So we only have to worry about problem #2, signed zeroes. This only + // affects the answer if _both_ operands are zero. So we check that by + // testing all bits of both operands apart from the sign bit. + orrs r12, op0l, op0h, LSL #1 // EQ if op0 is zero + orrseq r12, op1l, op1h, LSL #1 // now only EQ if both are zero + cmpne op1h, op0h // otherwise, compare them backwards + SetReturnRegisterNE + bxne lr + cmp op1l, op0l + SetReturnRegister + bx lr + +LOCAL_LABEL(NaNInf_check_negative): + // Second tier for negative numbers: we know the OR of the exponents is 0xFF, + // but again, we might not have either _actual_ exponent 0xFF, and also, an + // exponent 0xFF might be an infinity instead of a NaN. + // + // On this path we've already branched twice (once for negative numbers and + // once for the first-tier NaN check), so we'll just go straight to the + // precise check for NaNs. + // + // Like the NaNInf_check_positive case, we do each NaN check by making a + // word consisting of (high word << 1) OR (1 if low word is nonzero). But + // unlike the positive case, we can't make those words _in place_, + // overwriting op0h and op1h themselves, because that would shift the sign + // bits off the top, and we still need the sign bits to get the comparison + // right. (In the positive case, we knew both sign bits were 0, enabling a + // shortcut.) + cmp op0l, #1 // set C if op0l is nonzero + adc r12, op0h, op0h // shift op0h left, bringing in the C bit + cmn r12, #1 << 21 // if HI, then op0 is a NaN + bhi LOCAL_LABEL(NaN) + cmp op1l, #1 // set C if op1l is nonzero + adc r12, op1h, op1h // shift op1h left, bringing in the C bit + cmn r12, #1 << 21 // if HI, then op1 is a NaN + bhi LOCAL_LABEL(NaN) + + // Now we've ruled out NaNs, so we can just compare the two input registers + // and return. On this path we _don't_ need to check for the special case of + // comparing two zeroes, because we only came here if the bitwise OR of the + // exponent fields was 0x7FF, which means the exponents can't both have been + // zero! So we can _just_ do the reversed CMP and finish. + cmp op1h, op0h + SetReturnRegister + bx lr diff --git a/compiler-rt/lib/builtins/arm/gedf2.S b/compiler-rt/lib/builtins/arm/gedf2.S new file mode 100644 index 0000000000000..531827559b236 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/gedf2.S @@ -0,0 +1,61 @@ +//===-- gedf2.S - double-precision floating point comparison --------------===// +// +// 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 function has the semantics of GNU __cmpdf2, except for its NaN +// handling. It's a three-way compare which returns <0 if x<y, 0 if x==y, and +// >0 if x>y. If the result is unordered (i.e. x or y or both is NaN) then it +// returns <0, where __cmpdf2 would return >0. +// +// This also makes it suitable for use as __gtdf2 or __gedf2 (or __eqdf2 or +// __nedf2). +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" +#include "endian.h" + + .syntax unified + .text + .p2align 2 + +op0h .req xh +op0l .req xl +op1h .req yh +op1l .req yl +.macro SetReturnRegister + mov r0, #0 + movhi r0, #1 + movlo r0, #-1 +.endm +.macro SetReturnRegisterNE + movne r0, #-1 + movhi r0, #1 +.endm + +#if __ARM_PCS_VFP +DEFINE_COMPILERRT_FUNCTION(__gedf2) + push {r4, lr} + VMOV_FROM_DOUBLE(r0, r1, d0) + VMOV_FROM_DOUBLE(r2, r3, d1) + bl __compiler_rt_softfp_gedf2 + pop {r4, pc} +#else +DEFINE_COMPILERRT_FUNCTION_ALIAS(__gedf2, __compiler_rt_softfp_gedf2) +#endif +DEFINE_COMPILERRT_FUNCTION_ALIAS(__gtdf2, __gedf2) + +DEFINE_COMPILERRT_FUNCTION(__compiler_rt_softfp_gedf2) + #include "dcmp.h" + +LOCAL_LABEL(NaN): + mov r0, #-1 + bx lr + +END_COMPILERRT_FUNCTION(__compiler_rt_softfp_gedf2) + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S b/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S new file mode 100644 index 0000000000000..d6d37198b5145 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/thumb1/cmpdf2.S @@ -0,0 +1,61 @@ +//===-- cmpdf2.S - double-precision floating point comparison -------------===// +// +// 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 function has the semantics of GNU __cmpdf2: it's a three-way compare +// which returns <0 if x<y, 0 if x==y, and >0 if x>y. If the result is +// unordered (i.e. x or y or both is NaN) then it returns >0. +// +// This also makes it suitable for use as all of __eqdf2, __nedf2, __ltdf2 or +// __ledf2. +// +//===----------------------------------------------------------------------===// + +#include "../../assembly.h" +#include "../endian.h" + + .syntax unified + .text + .p2align 2 + +op0h .req xh +op0l .req xl +op1h .req yh +op1l .req yl +.macro SetReturnRegister + bhi 0f + blo 1f + movs r0, #0 + // This macro is always called immediately before returning from the + // function, so it's safe to use the same return instruction here, instead of + // wasting time branching forward to the end of the macro. + pop {r4,r5,r6,pc} +0: + movs r0, #1 + pop {r4,r5,r6,pc} +1: + movs r0, #1 + rsbs r0, r0, #0 + pop {r4,r5,r6,pc} +.endm + +DEFINE_COMPILERRT_FUNCTION_ALIAS(__cmpdf2, __compiler_rt_softfp_cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__ledf2, __cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__ltdf2, __cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__eqdf2, __cmpdf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__nedf2, __cmpdf2) + +DEFINE_COMPILERRT_THUMB_FUNCTION(__compiler_rt_softfp_cmpdf2) + #include "dcmp.h" + +LOCAL_LABEL(NaN): + movs r0, #1 + pop {r4,r5,r6,pc} + +END_COMPILERRT_FUNCTION(__compiler_rt_softfp_cmpdf2) + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/builtins/arm/thumb1/dcmp.h b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h new file mode 100644 index 0000000000000..fc45b5d469120 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/thumb1/dcmp.h @@ -0,0 +1,236 @@ +//===-- dcmp.h - shared code for double-precision FP comparison functions -===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This code is the skeleton of a double-precision FP compare, with two details +// left out: which input value is in which register, and how to make the return +// value. It allows the main comparison logic to be shared between (for +// example) __ledf2 and __gedf2, varying only those details. +// +//===----------------------------------------------------------------------===// + +// How to use this header file: +// +// This header file is expected to be #included from inside a function +// definition in a .S file. The source file including this header should +// provide the following: +// +// op0h, op0l, op1h, op1l: register aliases (via .req) for the registers +// containing the input operands. +// - For most comparisons, op0h,op0l will correspond to ah,al, and op1h,op1l +// to bh,bl (as defined in turn in endian.h). +// - But a function with the reversed semantics of __aeabi_cdrcmple wil define +// them the other way round. +// +// SetReturnRegister: an assembly macro that looks at the PSR flags and sets up +// an appropriate return value in r0, for the cases that do *not* involve NaN. +// - On entry to this macro, the condition codes LO, EQ and HI indicate that +// op0 < op1, op0 == op1 or op0 > op1 respectively. +// - For functions that return a result in the flags, this macro can be empty, +// because those are the correct flags to return anyway. +// - Functions that return a boolean in r0 should set it up by checking the +// flags. +// +// LOCAL_LABEL(NaN): a label defined within the compare function, after the +// #include of this header. Called when at least one input is a NaN, and sets +// up the appropriate return value for that case. + +// -------------------------------------------------- +// The actual entry point of the compare function. +// +// The basic plan is to start by ORing together the two inputs. This tells us +// two things: +// - the top bit of the output tells us whether both inputs are positive, or +// whether at least one is negative +// - if the 11 exponent bits of the output are not all 1, then there are +// definitely no NaNs, so a fast path can handle most non-NaN cases. + + push {r4,r5,r6,lr} + + // Set up the constant 1 << 20 in a register, which we'll need on all + // branches. + movs r5, #1 + lsls r5, r5, #20 + + // First diverge control for the negative-numbers case. + movs r4, op0h + orrs r4, r4, op1h + bmi LOCAL_LABEL(negative) // high bit set => at least one negative input + + // Here, both inputs are positive. Try adding 1<<20 to their bitwise OR in + // r4. This will carry all the way into the top bit, setting the N flag, if + // all 11 exponent bits were set. + cmn r4, r5 + bmi LOCAL_LABEL(NaNInf_check_positive) // need to look harder for NaNs + + // The fastest fast path: both inputs positive and we could easily tell there + // were no NaNs. So we just compare op0 and op1 as unsigned integers. + cmp op0h, op1h + beq LOCAL_LABEL(low_word_positive) + SetReturnRegister + pop {r4,r5,r6,pc} +LOCAL_LABEL(low_word_positive): + cmp op0l, op1l + SetReturnRegister + pop {r4,r5,r6,pc} + +LOCAL_LABEL(NaNInf_check_positive): + // Second tier for positive numbers. We come here if both inputs are + // positive, but our fast initial check didn't manage to rule out a NaN. But + // it's not guaranteed that there _is_ a NaN, for two reasons: + // + // 1. An input with exponent 0x7FF might be an infinity instead. Those + // behave normally under comparison. + // + // 2. There might not even _be_ an input with exponent 0x7FF. All we know so + // far is that the two inputs ORed together had all the exponent bits + // set. So each of those bits is set in _at least one_ of the inputs, but + // not necessarily all in the _same_ input. + // + // Test each exponent individually for 0x7FF, using the same CMN idiom as + // above. If neither one carries into the sign bit then we have no NaNs _or_ + // infinities and can compare the registers and return again. + cmn op0h, r5 + bmi LOCAL_LABEL(NaN_check_positive) + cmn op1h, r5 + bmi LOCAL_LABEL(NaN_check_positive) + + // Second-tier return path, now we've ruled out anything difficult. By this + // time we know that the two operands have different exponents (because the + // exponents' bitwise OR is 0x7FF but neither one is 0x7FF by itself, so each + // must have a set bit not present in the other). So we only need to compare + // the high words. + cmp op0h, op1h + SetReturnRegister + pop {r4,r5,r6,pc} + +LOCAL_LABEL(NaN_check_positive): + // Third tier for positive numbers. Here we know that at least one of the + // inputs has exponent 0x7FF. But they might still be infinities rather than + // NaNs. So now we must check whether there's an actual NaN. + // + // We do this by shifting the high word of each input left to get rid of the + // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in + // the low word. Then we check if the result is _greater_ than 0xFFE00000 + // (but not equal), via adding 0x00200000 to it and testing for the HI + // condition (carry flag set, but Z clear). + // + // We could have skipped the second-tier check and done this more rigorous + // test immediately. But that would cost an extra instruction in the case + // where there are no infinities or NaNs, and we assume that that is so much + // more common that it's worth optimizing for. + lsls r6, r5, #1 // set r6 = 1<<21 + cmp op0l, #1 // set C if op0l is nonzero + adcs op0h, op0h, op0h // shift op0h left, bringing in the C bit + cmn op0h, r6 // if HI, then op0 is a NaN + bhi LOCAL_LABEL(NaN) + cmp op1l, #1 // set C if op1l is nonzero + adcs op1h, op1h, op1h // shift op1h left, bringing in the C bit + cmn op1h, r6 // if HI, then op1 is a NaN + bhi LOCAL_LABEL(NaN) + + // Now we've finally ruled out NaNs! And we still know both inputs are + // positive. So the third-tier return path can just compare the top words + // again. (The fact that we've just shifted them left doesn't make a + // difference.) + cmp op0h, op1h + SetReturnRegister + pop {r4,r5,r6,pc} + +LOCAL_LABEL(negative): + // We come here if at least one operand is negative. We haven't checked for + // NaNs at all yet (the sign check came first), so repeat the first-tier + // check strategy of seeing if all exponent bits are set in r12. + // + // On this path, the sign bit in r12 is set, so if adding 1 to the low + // exponent bit carries all the way through into the sign bit, it will + // _clear_ the sign bit rather than setting it. So we expect MI to be the + // "definitely no NaNs" result, where it was PL on the positive branch. + cmn r4, r5 + bpl LOCAL_LABEL(NaNInf_check_negative) + + // Now we have no NaNs, but at least one negative number. This gives us two + // complications: + // + // 1. Floating-point numbers are sign/magnitude, not two's complement, so we + // have to consider separately the cases of "both negative" and "one of + // each sign". + // + // 2. -0 and +0 are required to compare equal. + // + // But problem #1 is not as hard as it sounds! If both operands are negative, + // then we can get the result we want by comparing them as unsigned integers + // the opposite way round, because the input with the smaller value (as an + // integer) is the larger number in an FP ordering sense. And if one operand + // is negative and the other is positive, the _same_ reversed comparison + // works, because the positive number (with zero sign bit) will always + // compare less than the negative one in an unsigned-integers sense. + // + // So we only have to worry about problem #2, signed zeroes. This only + // affects the answer if _both_ operands are zero. So we check that by + // testing all bits of both operands apart from the sign bit. + lsls r6, r4, #1 // logical OR of both high words except the signs + orrs r6, r6, op0l // combine that with the low word of op0 + orrs r6, r6, op1l // and op1, so now only EQ if both are zero + beq LOCAL_LABEL(equal) + // Now we've ruled out confusing zero cases, just compare the operands in + // reverse sense. + cmp op1h, op0h + beq LOCAL_LABEL(low_word_negative) + SetReturnRegister + pop {r4,r5,r6,pc} +LOCAL_LABEL(low_word_negative): + cmp op1l, op0l + SetReturnRegister + pop {r4,r5,r6,pc} + +LOCAL_LABEL(equal): + // We come here if we know the inputs are supposed to compare equal. Set up + // the flags by comparing a register with itself. + // + // (We might have come here via a BEQ, in which case we know Z=1, but we also + // need C=1 for our caller to get _all_ the right flags.) + cmp r0, r0 // compare a register with itself + SetReturnRegister + pop {r4,r5,r6,pc} + +LOCAL_LABEL(NaNInf_check_negative): + // Second tier for negative numbers: we know the OR of the exponents is 0xFF, + // but again, we might not have either _actual_ exponent 0xFF, and also, an + // exponent 0xFF might be an infinity instead of a NaN. + // + // On this path we've already branched twice (once for negative numbers and + // once for the first-tier NaN check), so we'll just go straight to the + // precise check for NaNs. + // + // Like the NaNInf_check_positive case, we do each NaN check by making a + // word consisting of (high word << 1) OR (1 if low word is nonzero). But + // unlike the positive case, we can't make those words _in place_, + // overwriting op0h and op1h themselves, because that would shift the sign + // bits off the top, and we still need the sign bits to get the comparison + // right. (In the positive case, we knew both sign bits were 0, enabling a + // shortcut.) + lsls r6, r5, #1 // set r6 = 1<<21 + movs r4, op0h // copy op0h into a scratch register to modify + cmp op0l, #1 // set C if op0l is nonzero + adcs r4, r4, r4 // shift left, bringing in the C bit + cmn r4, r6 // if HI, then op0 is a NaN + bhi LOCAL_LABEL(NaN) + movs r4, op1h // copy op1h into a scratch register to modify + cmp op1l, #1 // set C if op1l is nonzero + adcs r4, r4, r4 // shift left, bringing in the C bit + cmn r4, r6 // if HI, then op1 is a NaN + bhi LOCAL_LABEL(NaN) + + // Now we've ruled out NaNs, so we can just compare the two input registers + // and return. On this path we _don't_ need to check for the special case of + // comparing two zeroes, because we only came here if the bitwise OR of the + // exponent fields was 0x7FF, which means the exponents can't both have been + // zero! So we can _just_ do the reversed CMP and finish. + cmp op1h, op0h + SetReturnRegister + pop {r4,r5,r6,pc} diff --git a/compiler-rt/lib/builtins/arm/thumb1/gedf2.S b/compiler-rt/lib/builtins/arm/thumb1/gedf2.S new file mode 100644 index 0000000000000..3486403761bd5 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/thumb1/gedf2.S @@ -0,0 +1,60 @@ +//===-- gedf2.S - double-precision floating point comparison --------------===// +// +// 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 function has the semantics of GNU __cmpdf2, except for its NaN +// handling. It's a three-way compare which returns <0 if x<y, 0 if x==y, and +// >0 if x>y. If the result is unordered (i.e. x or y or both is NaN) then it +// returns <0, where __cmpdf2 would return >0. +// +// This also makes it suitable for use as __gtdf2 or __gedf2 (or __eqdf2 or +// __nedf2). +// +//===----------------------------------------------------------------------===// + +#include "../../assembly.h" +#include "../endian.h" + + .syntax unified + .text + .p2align 2 + +op0h .req xh +op0l .req xl +op1h .req yh +op1l .req yl +.macro SetReturnRegister + bhi 0f + blo 1f + movs r0, #0 + // This macro is always called immediately before returning from the + // function, so it's safe to use the same return instruction here, instead of + // wasting time branching forward to the end of the macro. + pop {r4,r5,r6,pc} +0: + movs r0, #1 + pop {r4,r5,r6,pc} +1: + movs r0, #1 + rsbs r0, r0, #0 + pop {r4,r5,r6,pc} +.endm + +DEFINE_COMPILERRT_FUNCTION_ALIAS(__gedf2, __compiler_rt_softfp_gedf2) +DEFINE_COMPILERRT_FUNCTION_ALIAS(__gtdf2, __gedf2) + +DEFINE_COMPILERRT_THUMB_FUNCTION(__compiler_rt_softfp_gedf2) + #include "dcmp.h" + +LOCAL_LABEL(NaN): + movs r0, #1 + rsbs r0, r0, #0 + pop {r4,r5,r6,pc} + +END_COMPILERRT_FUNCTION(__compiler_rt_softfp_gedf2) + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/builtins/arm/thumb1/unorddf2.S b/compiler-rt/lib/builtins/arm/thumb1/unorddf2.S new file mode 100644 index 0000000000000..a489e8a54fca4 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/thumb1/unorddf2.S @@ -0,0 +1,60 @@ +//===-- unorddf2.S - double-precision floating point comparison -----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Return 1 if the result of comparing x with y is 'unordered', i.e. +// one of x and y is NaN. +// +//===----------------------------------------------------------------------===// + +#include "../../assembly.h" +#include "../endian.h" + + .syntax unified + .text + .p2align 2 + +DEFINE_COMPILERRT_FUNCTION_ALIAS(__unorddf2, __aeabi_dcmpun) + +DEFINE_COMPILERRT_THUMB_FUNCTION(__aeabi_dcmpun) + + // This function isn't based on the general-purpose code in dcmp.h, because + // it's more effort than needed. Here we just need to identify whether or not + // there's at least one NaN in the inputs. There's no need to vary that check + // based on the sign bit, so we might as well just do the NaN test as quickly + // as possible. + // + // We do this by shifting the high word of each input left to get rid of the + // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in + // the low word. Then we check if the result is _greater_ than 0xFFE00000 + // (but not equal), via adding 0x00200000 to it and testing for the HI + // condition (carry flag set, but Z clear). + // + // Once we've done that transformation to the first input xh:xl, we + // free up xl to contain our constant 0x00200000, so there's no need + // to push any registers. + cmp xl, #1 // set C if xl is nonzero + adcs xh, xh, xh // shift xh left, bringing in the C bit + movs xl, #1 // now xl is free, make the test constant + lsls xl, xl, #21 // by shifting 1 left to make 0x00200000 + cmn xh, xl // HI if x is a NaN + bhi LOCAL_LABEL(NaN) + cmp yl, #1 // set C if yl is nonzero + adcs yh, yh, yh // shift yh left, bringing in the C bit + cmn yh, xl // HI if y is a NaN + bhi LOCAL_LABEL(NaN) + + movs r0, #0 + bx lr + +LOCAL_LABEL(NaN): + movs r0, #1 + bx lr + +END_COMPILERRT_FUNCTION(__aeabi_dcmpun) + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/lib/builtins/arm/unorddf2.S b/compiler-rt/lib/builtins/arm/unorddf2.S new file mode 100644 index 0000000000000..961b64bf21f44 --- /dev/null +++ b/compiler-rt/lib/builtins/arm/unorddf2.S @@ -0,0 +1,71 @@ +//===-- unorddf2.S - double-precision floating point comparison -----------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Return 1 if the result of comparing x with y is 'unordered', i.e. +// one of x and y is NaN. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" +#include "endian.h" + + + .syntax unified + .text + .p2align 2 + + +#if __ARM_PCS_VFP +DEFINE_COMPILERRT_FUNCTION(__unorddf2) + push {r4, lr} + VMOV_FROM_DOUBLE(r0, r1, d0) + VMOV_FROM_DOUBLE(r2, r3, d1) + bl __aeabi_dcmpun + pop {r4, pc} +#else +DEFINE_COMPILERRT_FUNCTION_ALIAS(__unorddf2, __aeabi_dcmpun) +#endif + +DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmpun) + + // This function isn't based on the general-purpose code in dcmp.h, because + // it's more effort than needed. Here we just need to identify whether or not + // there's at least one NaN in the inputs. There's no need to vary that check + // based on the sign bit, so we might as well just do the NaN test as quickly + // as possible. + // + // We do this by shifting the high word of each input left to get rid of the + // sign bit, shifting a bit in at the bottom which is 1 if any bit is set in + // the low word. Then we check if the result is _greater_ than 0xFFE00000 + // (but not equal), via adding 0x00200000 to it and testing for the HI + // condition (carry flag set, but Z clear). + // + // Once we've done that transformation to the first input xh:xl, we + // free up xl to contain our constant 0x00200000, so there's no need + // to push any registers. + cmp xl, #1 // set C if xl is nonzero + adc xh, xh, xh // shift xh left, bringing in the C bit + cmp yl, #1 // set C if yl is nonzero + adc yh, yh, yh // shift yh left, bringing in the C bit + cmn xh, #1 << 21 // if HI, then x is a NaN + cmnls yh, #1 << 21 // if not HI, then do the same check for y + + // If LS, then we have no NaNs and return false. We do this as quickly as we + // can (not stopping to take two instructions setting up r0 for both + // possibilities), on the assumption that NaNs are rare and we want to + // optimize for the non-NaN path. + movls r0, #0 + bxls lr + + // Otherwise, we have at least one NaN, and return true. + mov r0, #1 + bx lr + +END_COMPILERRT_FUNCTION(__aeabi_dcmpun) + +NO_EXEC_STACK_DIRECTIVE diff --git a/compiler-rt/test/builtins/Unit/comparedf2new_test.c b/compiler-rt/test/builtins/Unit/comparedf2new_test.c new file mode 100644 index 0000000000000..f78a1a6aaa02d --- /dev/null +++ b/compiler-rt/test/builtins/Unit/comparedf2new_test.c @@ -0,0 +1,609 @@ +// 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_comparedf2 + +#include "int_lib.h" +#include <inttypes.h> +#include <stdio.h> + +#include "fp_test.h" + +COMPILER_RT_ABI int __eqdf2(double, double); +COMPILER_RT_ABI int __nedf2(double, double); +COMPILER_RT_ABI int __gedf2(double, double); +COMPILER_RT_ABI int __gtdf2(double, double); +COMPILER_RT_ABI int __ledf2(double, double); +COMPILER_RT_ABI int __ltdf2(double, double); +COMPILER_RT_ABI int __cmpdf2(double, double); +COMPILER_RT_ABI int __unorddf2(double, double); + +enum Result { + RESULT_LT, + RESULT_GT, + RESULT_EQ, + RESULT_UN +}; + +int expect(int line, uint64_t a_rep, uint64_t b_rep, const char *name, int result, int ok, const char *expected) { + if (!ok) + printf("error at line %d: %s(%016" PRIx64 ", %016" PRIx64 ") = %d, expected %s\n", + line, name, a_rep, b_rep, result, expected); + return !ok; +} + +int test__comparedf2(int line, uint64_t a_rep, uint64_t b_rep, enum Result result) { + double a = fromRep64(a_rep), b = fromRep64(b_rep); + + int eq = __eqdf2(a, b); + int ne = __nedf2(a, b); + int ge = __gedf2(a, b); + int gt = __gtdf2(a, b); + int le = __ledf2(a, b); + int lt = __ltdf2(a, b); + int cmp = __cmpdf2(a, b); + int unord = __unorddf2(a, b); + + int ret = 0; + + switch (result) { + case RESULT_LT: + ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0"); + ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0"); + ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0"); + ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0"); + ret |= expect(line, a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0"); + ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt < 0, "< 0"); + ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == -1, "== -1"); + ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0"); + break; + case RESULT_GT: + ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0"); + ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0"); + ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0"); + ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt > 0, "> 0"); + ret |= expect(line, a_rep, b_rep, "__ledf2", le, le > 0, "> 0"); + ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0"); + ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1"); + ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0"); + break; + case RESULT_EQ: + ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq == 0, "== 0"); + ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne == 0, "== 0"); + ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge >= 0, ">= 0"); + ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0"); + ret |= expect(line, a_rep, b_rep, "__ledf2", le, le <= 0, "<= 0"); + ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0"); + ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 0, "== 0"); + ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 0, "== 0"); + break; + case RESULT_UN: + ret |= expect(line, a_rep, b_rep, "__eqdf2", eq, eq != 0, "!= 0"); + ret |= expect(line, a_rep, b_rep, "__nedf2", ne, ne != 0, "!= 0"); + ret |= expect(line, a_rep, b_rep, "__gedf2", ge, ge < 0, "< 0"); + ret |= expect(line, a_rep, b_rep, "__gtdf2", gt, gt <= 0, "<= 0"); + ret |= expect(line, a_rep, b_rep, "__ledf2", le, le > 0, "> 0"); + ret |= expect(line, a_rep, b_rep, "__ltdf2", lt, lt >= 0, ">= 0"); + ret |= expect(line, a_rep, b_rep, "__cmpdf2", cmp, cmp == 1, "== 1"); + ret |= expect(line, a_rep, b_rep, "__unorddf2", unord, unord == 1, "== 1"); + break; + } + + return ret; +} + +#define test__comparedf2(a,b,x) test__comparedf2(__LINE__,a,b,x) + +int main(void) { + int status = 0; + + status |= test__comparedf2(0x0000000000000000, 0x0000000000000001, RESULT_LT); + status |= test__comparedf2(0x0000000000000000, 0x000fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x0000000000000000, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000000, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000000, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000000, 0x7ff00000a5a42e09, RESULT_UN); + status |= test__comparedf2(0x0000000000000000, 0x7ffcd5b95f9b89ae, RESULT_UN); + status |= test__comparedf2(0x0000000000000000, 0x7ffcd5b95f9b89ae, RESULT_UN); + status |= test__comparedf2(0x0000000000000000, 0x8000000000000000, RESULT_EQ); + status |= test__comparedf2(0x0000000000000000, 0x8000000000000001, RESULT_GT); + status |= test__comparedf2(0x0000000000000000, 0x800fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0000000000000000, 0x8010000000000000, RESULT_GT); + status |= test__comparedf2(0x0000000000000000, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0x0000000000000000, 0xfff00000a5a42e09, RESULT_UN); + status |= test__comparedf2(0x0000000000000000, 0xfffcd5b95f9b89ae, RESULT_UN); + status |= test__comparedf2(0x0000000000000000, 0xfffcd5b95f9b89ae, RESULT_UN); + status |= test__comparedf2(0x0000000000000001, 0x0000000000000001, RESULT_EQ); + status |= test__comparedf2(0x0000000000000001, 0x3fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x3ffffffffffffffe, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x3fffffffffffffff, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x7fdfffffffffffff, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x7feffffffffffffe, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x7fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0x0000000000000001, 0x7ff00000887bcf03, RESULT_UN); + status |= test__comparedf2(0x0000000000000001, 0x7ff753b1887bcf03, RESULT_UN); + status |= test__comparedf2(0x0000000000000001, 0x7ffc3134b058fe20, RESULT_UN); + status |= test__comparedf2(0x0000000000000001, 0x8000000000000001, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xbfefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xbffffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xbfffffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xffdfffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xffeffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xffefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0000000000000001, 0xfff00000887bcf03, RESULT_UN); + status |= test__comparedf2(0x0000000000000001, 0xfff753b1887bcf03, RESULT_UN); + status |= test__comparedf2(0x0000000000000001, 0xfffc3134b058fe20, RESULT_UN); + status |= test__comparedf2(0x0000000000000002, 0x0000000000000001, RESULT_GT); + status |= test__comparedf2(0x0000000000000003, 0x0000000000000002, RESULT_GT); + status |= test__comparedf2(0x0000000000000003, 0x4008000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000003, 0x4014000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000003, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x0000000000000003, 0xc014000000000000, RESULT_GT); + status |= test__comparedf2(0x0000000000000003, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x0000000000000004, 0x0000000000000004, RESULT_EQ); + status |= test__comparedf2(0x000ffffffffffffc, 0x800ffffffffffffc, RESULT_GT); + status |= test__comparedf2(0x000ffffffffffffd, 0x000ffffffffffffe, RESULT_LT); + status |= test__comparedf2(0x000fffffffffffff, 0x0000000000000000, RESULT_GT); + status |= test__comparedf2(0x000fffffffffffff, 0x000ffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x000fffffffffffff, 0x000fffffffffffff, RESULT_EQ); + status |= test__comparedf2(0x000fffffffffffff, 0x0010000000000000, RESULT_LT); + status |= test__comparedf2(0x000fffffffffffff, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x000fffffffffffff, 0x7ff00000dfe15ee3, RESULT_UN); + status |= test__comparedf2(0x000fffffffffffff, 0x7ff6d1ebdfe15ee3, RESULT_UN); + status |= test__comparedf2(0x000fffffffffffff, 0x7ffed0664505a878, RESULT_UN); + status |= test__comparedf2(0x000fffffffffffff, 0x8000000000000000, RESULT_GT); + status |= test__comparedf2(0x000fffffffffffff, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0x000fffffffffffff, 0xfff00000dfe15ee3, RESULT_UN); + status |= test__comparedf2(0x000fffffffffffff, 0xfff6d1ebdfe15ee3, RESULT_UN); + status |= test__comparedf2(0x000fffffffffffff, 0xfffed0664505a878, RESULT_UN); + status |= test__comparedf2(0x0010000000000000, 0x0000000000000000, RESULT_GT); + status |= test__comparedf2(0x0010000000000000, 0x0010000000000000, RESULT_EQ); + status |= test__comparedf2(0x0010000000000000, 0x8010000000000000, RESULT_GT); + status |= test__comparedf2(0x0010000000000001, 0x0010000000000000, RESULT_GT); + status |= test__comparedf2(0x0010000000000001, 0x0010000000000002, RESULT_LT); + status |= test__comparedf2(0x001fffffffffffff, 0x0020000000000000, RESULT_LT); + status |= test__comparedf2(0x001fffffffffffff, 0x0020000000000002, RESULT_LT); + status |= test__comparedf2(0x001fffffffffffff, 0x0020000000000004, RESULT_LT); + status |= test__comparedf2(0x0020000000000000, 0x001fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0020000000000001, 0x0010000000000001, RESULT_GT); + status |= test__comparedf2(0x0020000000000001, 0x001fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0020000000000002, 0x0010000000000001, RESULT_GT); + status |= test__comparedf2(0x002fffffffffffff, 0x0030000000000000, RESULT_LT); + status |= test__comparedf2(0x0030000000000000, 0x002fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0030000000000001, 0x002fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x0030000000000002, 0x0020000000000003, RESULT_GT); + status |= test__comparedf2(0x3fe0000000000000, 0x3fe0000000000000, RESULT_EQ); + status |= test__comparedf2(0x3fefffffffffffff, 0x0000000000000001, RESULT_GT); + status |= test__comparedf2(0x3fefffffffffffff, 0x8000000000000001, RESULT_GT); + status |= test__comparedf2(0x3ff0000000000000, 0x3ff0000000000000, RESULT_EQ); + status |= test__comparedf2(0x3ff0000000000000, 0x3ff0000000000003, RESULT_LT); + status |= test__comparedf2(0x3ff0000000000000, 0x4000000000000000, RESULT_LT); + status |= test__comparedf2(0x3ff0000000000000, 0x401c000000000000, RESULT_LT); + status |= test__comparedf2(0x3ff0000000000000, 0x7ff0000033022725, RESULT_UN); + status |= test__comparedf2(0x3ff0000000000000, 0x7ff4f5ad33022725, RESULT_UN); + status |= test__comparedf2(0x3ff0000000000000, 0x7ffd3870667efc9d, RESULT_UN); + status |= test__comparedf2(0x3ff0000000000000, 0x8000000000000000, RESULT_GT); + status |= test__comparedf2(0x3ff0000000000000, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x3ff0000000000000, 0xbff0000000000003, RESULT_GT); + status |= test__comparedf2(0x3ff0000000000000, 0xfff0000033022725, RESULT_UN); + status |= test__comparedf2(0x3ff0000000000000, 0xfff4f5ad33022725, RESULT_UN); + status |= test__comparedf2(0x3ff0000000000000, 0xfffd3870667efc9d, RESULT_UN); + status |= test__comparedf2(0x3ff0000000000001, 0x3ff0000000000000, RESULT_GT); + status |= test__comparedf2(0x3ff0000000000001, 0x3ff0000000000002, RESULT_LT); + status |= test__comparedf2(0x3ff0000000000001, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x3ffffffffffffffc, 0x3ffffffffffffffd, RESULT_LT); + status |= test__comparedf2(0x3fffffffffffffff, 0x0000000000000001, RESULT_GT); + status |= test__comparedf2(0x3fffffffffffffff, 0x4000000000000000, RESULT_LT); + status |= test__comparedf2(0x4000000000000000, 0x3ff0000000000000, RESULT_GT); + status |= test__comparedf2(0x4000000000000000, 0x3fffffffffffffff, RESULT_GT); + status |= test__comparedf2(0x4000000000000000, 0x4000000000000000, RESULT_EQ); + status |= test__comparedf2(0x4000000000000000, 0x4000000000000001, RESULT_LT); + status |= test__comparedf2(0x4000000000000000, 0xc000000000000000, RESULT_GT); + status |= test__comparedf2(0x4000000000000000, 0xc000000000000001, RESULT_GT); + status |= test__comparedf2(0x4000000000000000, 0xc014000000000000, RESULT_GT); + status |= test__comparedf2(0x4000000000000001, 0x3ff0000000000001, RESULT_GT); + status |= test__comparedf2(0x4000000000000001, 0x4000000000000002, RESULT_LT); + status |= test__comparedf2(0x4000000000000001, 0xc000000000000002, RESULT_GT); + status |= test__comparedf2(0x4000000000000002, 0x3ff0000000000001, RESULT_GT); + status |= test__comparedf2(0x4000000000000002, 0x3ff0000000000003, RESULT_GT); + status |= test__comparedf2(0x4000000000000004, 0x4000000000000003, RESULT_GT); + status |= test__comparedf2(0x4008000000000000, 0x4008000000000000, RESULT_EQ); + status |= test__comparedf2(0x400fffffffffffff, 0x400ffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x400fffffffffffff, 0x4010000000000002, RESULT_LT); + status |= test__comparedf2(0x4010000000000001, 0x400fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x4014000000000000, 0x0000000000000000, RESULT_GT); + status |= test__comparedf2(0x4014000000000000, 0x8000000000000000, RESULT_GT); + status |= test__comparedf2(0x4014000000000000, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x4014000000000000, 0xc014000000000000, RESULT_GT); + status |= test__comparedf2(0x7fb0000000000001, 0x7fafffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7fcfffffffffffff, 0x7fcffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x7fcfffffffffffff, 0x7fd0000000000002, RESULT_LT); + status |= test__comparedf2(0x7fd0000000000000, 0x7fcfffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7fd0000000000000, 0x7fd0000000000000, RESULT_EQ); + status |= test__comparedf2(0x7fd0000000000000, 0x7fd0000000000001, RESULT_LT); + status |= test__comparedf2(0x7fd0000000000001, 0x7fd0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fd0000000000001, 0x7fe0000000000001, RESULT_LT); + status |= test__comparedf2(0x7fd0000000000001, 0xffd0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fd0000000000002, 0x7fc0000000000003, RESULT_GT); + status |= test__comparedf2(0x7fd0000000000004, 0x7fd0000000000003, RESULT_GT); + status |= test__comparedf2(0x7fdffffffffffffe, 0x7fdffffffffffffe, RESULT_EQ); + status |= test__comparedf2(0x7fdffffffffffffe, 0x7fdfffffffffffff, RESULT_LT); + status |= test__comparedf2(0x7fdffffffffffffe, 0xffdfffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7fdfffffffffffff, 0x3ff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fdfffffffffffff, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x7fdfffffffffffff, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fdfffffffffffff, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000000, 0x3ff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000000, 0x7fe0000000000000, RESULT_EQ); + status |= test__comparedf2(0x7fe0000000000000, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x7fe0000000000000, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000000, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000000, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000001, 0x7fe0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000001, 0x7fe0000000000002, RESULT_LT); + status |= test__comparedf2(0x7fe0000000000001, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fe0000000000002, 0x7fd0000000000001, RESULT_GT); + status |= test__comparedf2(0x7feffffffffffffe, 0x3ff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7feffffffffffffe, 0x7fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0x7feffffffffffffe, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7feffffffffffffe, 0xffefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7fefffffffffffff, 0x0000000000000001, RESULT_GT); + status |= test__comparedf2(0x7fefffffffffffff, 0x3ff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fefffffffffffff, 0x7fefffffffffffff, RESULT_EQ); + status |= test__comparedf2(0x7fefffffffffffff, 0x7ff00000c901461b, RESULT_UN); + status |= test__comparedf2(0x7fefffffffffffff, 0x7ff784a9c901461b, RESULT_UN); + status |= test__comparedf2(0x7fefffffffffffff, 0x7ffe2c1db2e4a313, RESULT_UN); + status |= test__comparedf2(0x7fefffffffffffff, 0x8000000000000001, RESULT_GT); + status |= test__comparedf2(0x7fefffffffffffff, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7fefffffffffffff, 0xfff00000c901461b, RESULT_UN); + status |= test__comparedf2(0x7fefffffffffffff, 0xfff784a9c901461b, RESULT_UN); + status |= test__comparedf2(0x7fefffffffffffff, 0xfffe2c1db2e4a313, RESULT_UN); + status |= test__comparedf2(0x7ff0000000000000, 0x0000000000000000, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x0000000000000001, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x000fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x7fe0000000000000, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x7fefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x7ff0000000000000, RESULT_EQ); + status |= test__comparedf2(0x7ff0000000000000, 0x7ff0e6d059ac9171, RESULT_UN); + status |= test__comparedf2(0x7ff0000000000000, 0x7ffbda2fc9024ae6, RESULT_UN); + status |= test__comparedf2(0x7ff0000000000000, 0x8000000000000000, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x8000000000000001, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0x800fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0xffefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x7ff0000000000000, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0x7ff0000047e8b9a0, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff4017647e8b9a0, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff00000abfe5d29, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff2a1cdabfe5d29, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff000005155db76, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff645cb5155db76, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff0000070c46aa0, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff2068470c46aa0, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff00000b5aee637, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff72b19b5aee637, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff00000c08c2788, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff1e0c1c08c2788, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff00000ec581a54, 0x7ff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff00000ec581a54, 0x7ff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff571eaec581a54, 0x7ff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff571eaec581a54, 0x7ff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff000003a3a1f94, 0x7ff00000229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff000003a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff6439e3a3a1f94, 0x7ff00000229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff6439e3a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff00000ec581a54, 0xfff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff00000ec581a54, 0xfff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff571eaec581a54, 0xfff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff571eaec581a54, 0xfff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0x7ff000003a3a1f94, 0xfff00000229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff000003a3a1f94, 0xfffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff6439e3a3a1f94, 0xfff00000229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff6439e3a3a1f94, 0xfffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0x7ff00000c31d528e, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff5fb72c31d528e, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff00000ac81d215, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff4481aac81d215, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff00000d12062fd, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff707f6d12062fd, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff000001c6481ef, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff66ee91c6481ef, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff00000985729a7, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff19cff985729a7, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff0000053ec80fe, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff7dbc153ec80fe, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff00000816fb493, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff87f75816fb493, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff000000c2d7c33, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff91ecb0c2d7c33, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff00000a68bae40, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ffc0acda68bae40, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff000002fe14961, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ffcfa4e2fe14961, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff000005c206da1, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff800bb5c206da1, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff0000051887a34, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ffce11951887a34, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff000002b4c32a8, 0x7ff000001edb8786, RESULT_UN); + status |= test__comparedf2(0x7ff000002b4c32a8, 0x7ff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0x7ff000001edb8786, RESULT_UN); + status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0x7ff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0x7ff00000bc88c2a9, 0x7ff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff00000bc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0x7ff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff000002b4c32a8, 0xfff000001edb8786, RESULT_UN); + status |= test__comparedf2(0x7ff000002b4c32a8, 0xfff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0xfff000001edb8786, RESULT_UN); + status |= test__comparedf2(0x7ffbd6b52b4c32a8, 0xfff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0x7ff00000bc88c2a9, 0xfff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff00000bc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0xfff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff8eaadbc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0x7ff00000a47525ca, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ffcb028a47525ca, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff0000097c1af12, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ffc541e97c1af12, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0x7ff00000bb1c07a4, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff966b7bb1c07a4, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff000001d98f07c, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff9dbf61d98f07c, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff0000040e65504, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ffb2a7440e65504, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0x7ff00000d9dc7412, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0x7ff8af62d9dc7412, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0x8000000000000000, 0x0000000000000000, RESULT_EQ); + status |= test__comparedf2(0x8000000000000000, 0x0000000000000001, RESULT_LT); + status |= test__comparedf2(0x8000000000000000, 0x000fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8000000000000000, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x8000000000000000, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x8000000000000000, 0x7ff000005a0faea3, RESULT_UN); + status |= test__comparedf2(0x8000000000000000, 0x7ff225cc5a0faea3, RESULT_UN); + status |= test__comparedf2(0x8000000000000000, 0x7ffa0cc436ad9daa, RESULT_UN); + status |= test__comparedf2(0x8000000000000000, 0x8000000000000001, RESULT_GT); + status |= test__comparedf2(0x8000000000000000, 0x800fffffffffffff, RESULT_GT); + status |= test__comparedf2(0x8000000000000000, 0x8010000000000000, RESULT_GT); + status |= test__comparedf2(0x8000000000000000, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x8000000000000000, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0x8000000000000000, 0xfff000005a0faea3, RESULT_UN); + status |= test__comparedf2(0x8000000000000000, 0xfff225cc5a0faea3, RESULT_UN); + status |= test__comparedf2(0x8000000000000000, 0xfffa0cc436ad9daa, RESULT_UN); + status |= test__comparedf2(0x8000000000000001, 0x0000000000000001, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x3fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x3ffffffffffffffe, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x3fffffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x7fdfffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x7feffffffffffffe, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x7fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8000000000000001, 0x7ff0000013fd5944, RESULT_UN); + status |= test__comparedf2(0x8000000000000001, 0x7ff4154313fd5944, RESULT_UN); + status |= test__comparedf2(0x8000000000000001, 0x7ffd397ba0f9b5e1, RESULT_UN); + status |= test__comparedf2(0x8000000000000001, 0x8000000000000001, RESULT_EQ); + status |= test__comparedf2(0x8000000000000001, 0xbfefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xbff0000000000000, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xbffffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xbfffffffffffffff, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xffdfffffffffffff, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xffeffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xffefffffffffffff, RESULT_GT); + status |= test__comparedf2(0x8000000000000001, 0xfff0000013fd5944, RESULT_UN); + status |= test__comparedf2(0x8000000000000001, 0xfff4154313fd5944, RESULT_UN); + status |= test__comparedf2(0x8000000000000001, 0xfffd397ba0f9b5e1, RESULT_UN); + status |= test__comparedf2(0x8000000000000002, 0x8000000000000001, RESULT_LT); + status |= test__comparedf2(0x8000000000000003, 0x4008000000000000, RESULT_LT); + status |= test__comparedf2(0x8000000000000003, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0x8000000000000003, 0x8000000000000002, RESULT_LT); + status |= test__comparedf2(0x8000000000000003, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0x8000000000000004, 0x8000000000000004, RESULT_EQ); + status |= test__comparedf2(0x800ffffffffffffd, 0x800ffffffffffffe, RESULT_GT); + status |= test__comparedf2(0x800fffffffffffff, 0x0000000000000000, RESULT_LT); + status |= test__comparedf2(0x800fffffffffffff, 0x000fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x800fffffffffffff, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0x800fffffffffffff, 0x7ff00000a2b85efa, RESULT_UN); + status |= test__comparedf2(0x800fffffffffffff, 0x7ff1d4fba2b85efa, RESULT_UN); + status |= test__comparedf2(0x800fffffffffffff, 0x7ffd08c114a37fe6, RESULT_UN); + status |= test__comparedf2(0x800fffffffffffff, 0x8000000000000000, RESULT_LT); + status |= test__comparedf2(0x800fffffffffffff, 0x800ffffffffffffe, RESULT_LT); + status |= test__comparedf2(0x800fffffffffffff, 0x800fffffffffffff, RESULT_EQ); + status |= test__comparedf2(0x800fffffffffffff, 0x8010000000000000, RESULT_GT); + status |= test__comparedf2(0x800fffffffffffff, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0x800fffffffffffff, 0xfff00000a2b85efa, RESULT_UN); + status |= test__comparedf2(0x800fffffffffffff, 0xfff1d4fba2b85efa, RESULT_UN); + status |= test__comparedf2(0x800fffffffffffff, 0xfffd08c114a37fe6, RESULT_UN); + status |= test__comparedf2(0x8010000000000000, 0x0000000000000000, RESULT_LT); + status |= test__comparedf2(0x8010000000000000, 0x0010000000000000, RESULT_LT); + status |= test__comparedf2(0x8010000000000001, 0x8010000000000000, RESULT_LT); + status |= test__comparedf2(0x8010000000000001, 0x8010000000000002, RESULT_GT); + status |= test__comparedf2(0x801fffffffffffff, 0x8020000000000000, RESULT_GT); + status |= test__comparedf2(0x801fffffffffffff, 0x8020000000000002, RESULT_GT); + status |= test__comparedf2(0x801fffffffffffff, 0x8020000000000004, RESULT_GT); + status |= test__comparedf2(0x8020000000000000, 0x801fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8020000000000001, 0x8010000000000001, RESULT_LT); + status |= test__comparedf2(0x8020000000000001, 0x801fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8020000000000002, 0x8010000000000001, RESULT_LT); + status |= test__comparedf2(0x802fffffffffffff, 0x8030000000000000, RESULT_GT); + status |= test__comparedf2(0x8030000000000000, 0x802fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8030000000000001, 0x802fffffffffffff, RESULT_LT); + status |= test__comparedf2(0x8030000000000002, 0x8020000000000003, RESULT_LT); + status |= test__comparedf2(0xbff0000000000000, 0x3ff0000000000003, RESULT_LT); + status |= test__comparedf2(0xbff0000000000000, 0x7ff000000d32ab76, RESULT_UN); + status |= test__comparedf2(0xbff0000000000000, 0x7ff3d46c0d32ab76, RESULT_UN); + status |= test__comparedf2(0xbff0000000000000, 0x7ffb51e7ffa1e86b, RESULT_UN); + status |= test__comparedf2(0xbff0000000000000, 0x8000000000000000, RESULT_LT); + status |= test__comparedf2(0xbff0000000000000, 0xbff0000000000003, RESULT_GT); + status |= test__comparedf2(0xbff0000000000000, 0xfff000000d32ab76, RESULT_UN); + status |= test__comparedf2(0xbff0000000000000, 0xfff3d46c0d32ab76, RESULT_UN); + status |= test__comparedf2(0xbff0000000000000, 0xfffb51e7ffa1e86b, RESULT_UN); + status |= test__comparedf2(0xbff0000000000001, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xbff0000000000001, 0xbff0000000000000, RESULT_LT); + status |= test__comparedf2(0xbff0000000000001, 0xbff0000000000002, RESULT_GT); + status |= test__comparedf2(0xbffffffffffffffc, 0xbffffffffffffffd, RESULT_GT); + status |= test__comparedf2(0xbfffffffffffffff, 0x0000000000000001, RESULT_LT); + status |= test__comparedf2(0xbfffffffffffffff, 0xc000000000000000, RESULT_GT); + status |= test__comparedf2(0xc000000000000000, 0x4000000000000001, RESULT_LT); + status |= test__comparedf2(0xc000000000000000, 0xbfffffffffffffff, RESULT_LT); + status |= test__comparedf2(0xc000000000000000, 0xc000000000000001, RESULT_GT); + status |= test__comparedf2(0xc000000000000001, 0x4000000000000002, RESULT_LT); + status |= test__comparedf2(0xc000000000000001, 0xbff0000000000001, RESULT_LT); + status |= test__comparedf2(0xc000000000000001, 0xc000000000000002, RESULT_GT); + status |= test__comparedf2(0xc000000000000002, 0xbff0000000000001, RESULT_LT); + status |= test__comparedf2(0xc000000000000002, 0xbff0000000000003, RESULT_LT); + status |= test__comparedf2(0xc000000000000004, 0xc000000000000003, RESULT_LT); + status |= test__comparedf2(0xc008000000000000, 0x4008000000000000, RESULT_LT); + status |= test__comparedf2(0xc00fffffffffffff, 0xc00ffffffffffffe, RESULT_LT); + status |= test__comparedf2(0xc00fffffffffffff, 0xc010000000000002, RESULT_GT); + status |= test__comparedf2(0xc010000000000001, 0xc00fffffffffffff, RESULT_LT); + status |= test__comparedf2(0xffb0000000000001, 0xffafffffffffffff, RESULT_LT); + status |= test__comparedf2(0xffcfffffffffffff, 0xffcffffffffffffe, RESULT_LT); + status |= test__comparedf2(0xffcfffffffffffff, 0xffd0000000000002, RESULT_GT); + status |= test__comparedf2(0xffd0000000000000, 0xffcfffffffffffff, RESULT_LT); + status |= test__comparedf2(0xffd0000000000000, 0xffd0000000000001, RESULT_GT); + status |= test__comparedf2(0xffd0000000000001, 0x7fd0000000000000, RESULT_LT); + status |= test__comparedf2(0xffd0000000000001, 0xffd0000000000000, RESULT_LT); + status |= test__comparedf2(0xffd0000000000001, 0xffe0000000000001, RESULT_GT); + status |= test__comparedf2(0xffd0000000000002, 0xffc0000000000003, RESULT_LT); + status |= test__comparedf2(0xffd0000000000004, 0xffd0000000000003, RESULT_LT); + status |= test__comparedf2(0xffdffffffffffffe, 0x7fdffffffffffffe, RESULT_LT); + status |= test__comparedf2(0xffdffffffffffffe, 0x7fdfffffffffffff, RESULT_LT); + status |= test__comparedf2(0xffdffffffffffffe, 0xffdffffffffffffe, RESULT_EQ); + status |= test__comparedf2(0xffdffffffffffffe, 0xffdfffffffffffff, RESULT_GT); + status |= test__comparedf2(0xffdfffffffffffff, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffdfffffffffffff, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0xffdfffffffffffff, 0xbff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffdfffffffffffff, 0xffe0000000000000, RESULT_GT); + status |= test__comparedf2(0xffe0000000000000, 0x0000000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000000, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000000, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000000, 0x8000000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000000, 0xbff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000000, 0xffe0000000000000, RESULT_EQ); + status |= test__comparedf2(0xffe0000000000000, 0xfff0000000000000, RESULT_GT); + status |= test__comparedf2(0xffe0000000000001, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000001, 0xffe0000000000000, RESULT_LT); + status |= test__comparedf2(0xffe0000000000001, 0xffe0000000000002, RESULT_GT); + status |= test__comparedf2(0xffe0000000000002, 0xffd0000000000001, RESULT_LT); + status |= test__comparedf2(0xffeffffffffffffe, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffeffffffffffffe, 0x7fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0xffeffffffffffffe, 0xbff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffeffffffffffffe, 0xffefffffffffffff, RESULT_GT); + status |= test__comparedf2(0xffefffffffffffff, 0x0000000000000001, RESULT_LT); + status |= test__comparedf2(0xffefffffffffffff, 0x3ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffefffffffffffff, 0x7ff000007d4a42a6, RESULT_UN); + status |= test__comparedf2(0xffefffffffffffff, 0x7ff7252c7d4a42a6, RESULT_UN); + status |= test__comparedf2(0xffefffffffffffff, 0x7ff980ec6115c6fb, RESULT_UN); + status |= test__comparedf2(0xffefffffffffffff, 0x8000000000000001, RESULT_LT); + status |= test__comparedf2(0xffefffffffffffff, 0xbff0000000000000, RESULT_LT); + status |= test__comparedf2(0xffefffffffffffff, 0xffefffffffffffff, RESULT_EQ); + status |= test__comparedf2(0xffefffffffffffff, 0xfff000007d4a42a6, RESULT_UN); + status |= test__comparedf2(0xffefffffffffffff, 0xfff7252c7d4a42a6, RESULT_UN); + status |= test__comparedf2(0xffefffffffffffff, 0xfff980ec6115c6fb, RESULT_UN); + status |= test__comparedf2(0xfff0000000000000, 0x0000000000000000, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x0000000000000001, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x000fffffffffffff, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x7fe0000000000000, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x7fefffffffffffff, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x7ff0000000000000, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x7ff00000578bbe24, RESULT_UN); + status |= test__comparedf2(0xfff0000000000000, 0x7ff63d54578bbe24, RESULT_UN); + status |= test__comparedf2(0xfff0000000000000, 0x7ffbc66614390083, RESULT_UN); + status |= test__comparedf2(0xfff0000000000000, 0x8000000000000000, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x8000000000000001, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0x800fffffffffffff, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0xffe0000000000000, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0xffefffffffffffff, RESULT_LT); + status |= test__comparedf2(0xfff0000000000000, 0xfff0000000000000, RESULT_EQ); + status |= test__comparedf2(0xfff0000000000000, 0xfff00000578bbe24, RESULT_UN); + status |= test__comparedf2(0xfff0000000000000, 0xfff63d54578bbe24, RESULT_UN); + status |= test__comparedf2(0xfff0000000000000, 0xfffbc66614390083, RESULT_UN); + status |= test__comparedf2(0xfff0000047e8b9a0, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff4017647e8b9a0, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff00000abfe5d29, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff2a1cdabfe5d29, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff000005155db76, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff645cb5155db76, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff0000070c46aa0, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff2068470c46aa0, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff00000b5aee637, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff72b19b5aee637, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff00000c08c2788, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff1e0c1c08c2788, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff00000ec581a54, 0x7ff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff00000ec581a54, 0x7ff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff571eaec581a54, 0x7ff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff571eaec581a54, 0x7ff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff000003a3a1f94, 0x7ff00000229f3502, RESULT_UN); + status |= test__comparedf2(0xfff000003a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0xfff6439e3a3a1f94, 0x7ff00000229f3502, RESULT_UN); + status |= test__comparedf2(0xfff6439e3a3a1f94, 0x7ffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0xfff00000ec581a54, 0xfff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff00000ec581a54, 0xfff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff571eaec581a54, 0xfff0000021ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff571eaec581a54, 0xfff45d2221ebdfaf, RESULT_UN); + status |= test__comparedf2(0xfff000003a3a1f94, 0xfff00000229f3502, RESULT_UN); + status |= test__comparedf2(0xfff000003a3a1f94, 0xfffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0xfff6439e3a3a1f94, 0xfff00000229f3502, RESULT_UN); + status |= test__comparedf2(0xfff6439e3a3a1f94, 0xfffb8fa0229f3502, RESULT_UN); + status |= test__comparedf2(0xfff00000c31d528e, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff5fb72c31d528e, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff00000ac81d215, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff4481aac81d215, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff00000d12062fd, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff707f6d12062fd, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff000001c6481ef, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff66ee91c6481ef, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff00000985729a7, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff19cff985729a7, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff0000053ec80fe, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff7dbc153ec80fe, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff00000816fb493, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff87f75816fb493, 0x0000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff000000c2d7c33, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff91ecb0c2d7c33, 0x0000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff00000a68bae40, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfffc0acda68bae40, 0x000fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff000002fe14961, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfffcfa4e2fe14961, 0x3ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff000005c206da1, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff800bb5c206da1, 0x7fefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff0000051887a34, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfffce11951887a34, 0x7ff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff000002b4c32a8, 0x7ff000001edb8786, RESULT_UN); + status |= test__comparedf2(0xfff000002b4c32a8, 0x7ff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0xfffbd6b52b4c32a8, 0x7ff000001edb8786, RESULT_UN); + status |= test__comparedf2(0xfffbd6b52b4c32a8, 0x7ff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0xfff00000bc88c2a9, 0x7ff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff00000bc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff8eaadbc88c2a9, 0x7ff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff8eaadbc88c2a9, 0x7ffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff000002b4c32a8, 0xfff000001edb8786, RESULT_UN); + status |= test__comparedf2(0xfff000002b4c32a8, 0xfff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0xfffbd6b52b4c32a8, 0xfff000001edb8786, RESULT_UN); + status |= test__comparedf2(0xfffbd6b52b4c32a8, 0xfff342ea1edb8786, RESULT_UN); + status |= test__comparedf2(0xfff00000bc88c2a9, 0xfff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff00000bc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff8eaadbc88c2a9, 0xfff000002fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff8eaadbc88c2a9, 0xfffdc9ee2fa062f4, RESULT_UN); + status |= test__comparedf2(0xfff00000a47525ca, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0xfffcb028a47525ca, 0x8000000000000000, RESULT_UN); + status |= test__comparedf2(0xfff0000097c1af12, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0xfffc541e97c1af12, 0x8000000000000001, RESULT_UN); + status |= test__comparedf2(0xfff00000bb1c07a4, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff966b7bb1c07a4, 0x800fffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff000001d98f07c, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff9dbf61d98f07c, 0xbff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff0000040e65504, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfffb2a7440e65504, 0xffefffffffffffff, RESULT_UN); + status |= test__comparedf2(0xfff00000d9dc7412, 0xfff0000000000000, RESULT_UN); + status |= test__comparedf2(0xfff8af62d9dc7412, 0xfff0000000000000, RESULT_UN); + + return status; +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
