[Clang][SME2] Enable multi-vector loads & stores for SME2 (#75821)
[llvm-project.git] / compiler-rt / lib / builtins / fp_compare_impl.inc
bloba9a4f6fbf5dfe45f00c795ff3ef3a00f0e8e1d7b
1 //===-- lib/fp_compare_impl.inc - Floating-point comparison -------*- C -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "fp_lib.h"
11 // GCC uses long (at least for x86_64) as the return type of the comparison
12 // functions. We need to ensure that the return value is sign-extended in the
13 // same way as GCC expects (since otherwise GCC-generated __builtin_isinf
14 // returns true for finite 128-bit floating-point numbers).
15 #ifdef __aarch64__
16 // AArch64 GCC overrides libgcc_cmp_return to use int instead of long.
17 typedef int CMP_RESULT;
18 #elif __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 4
19 // LLP64 ABIs use long long instead of long.
20 typedef long long CMP_RESULT;
21 #elif __AVR__
22 // AVR uses a single byte for the return value.
23 typedef char CMP_RESULT;
24 #else
25 // Otherwise the comparison functions return long.
26 typedef long CMP_RESULT;
27 #endif
29 #if !defined(__clang__) && defined(__GNUC__)
30 // GCC uses a special __libgcc_cmp_return__ mode to define the return type, so
31 // check that we are ABI-compatible when compiling the builtins with GCC.
32 typedef int GCC_CMP_RESULT __attribute__((__mode__(__libgcc_cmp_return__)));
33 _Static_assert(sizeof(GCC_CMP_RESULT) == sizeof(CMP_RESULT),
34                "SOFTFP ABI not compatible with GCC");
35 #endif
37 enum {
38   LE_LESS = -1,
39   LE_EQUAL = 0,
40   LE_GREATER = 1,
41   LE_UNORDERED = 1,
44 static inline CMP_RESULT __leXf2__(fp_t a, fp_t b) {
45   const srep_t aInt = toRep(a);
46   const srep_t bInt = toRep(b);
47   const rep_t aAbs = aInt & absMask;
48   const rep_t bAbs = bInt & absMask;
50   // If either a or b is NaN, they are unordered.
51   if (aAbs > infRep || bAbs > infRep)
52     return LE_UNORDERED;
54   // If a and b are both zeros, they are equal.
55   if ((aAbs | bAbs) == 0)
56     return LE_EQUAL;
58   // If at least one of a and b is positive, we get the same result comparing
59   // a and b as signed integers as we would with a floating-point compare.
60   if ((aInt & bInt) >= 0) {
61     if (aInt < bInt)
62       return LE_LESS;
63     else if (aInt == bInt)
64       return LE_EQUAL;
65     else
66       return LE_GREATER;
67   } else {
68     // Otherwise, both are negative, so we need to flip the sense of the
69     // comparison to get the correct result.  (This assumes a twos- or ones-
70     // complement integer representation; if integers are represented in a
71     // sign-magnitude representation, then this flip is incorrect).
72     if (aInt > bInt)
73       return LE_LESS;
74     else if (aInt == bInt)
75       return LE_EQUAL;
76     else
77       return LE_GREATER;
78   }
81 enum {
82   GE_LESS = -1,
83   GE_EQUAL = 0,
84   GE_GREATER = 1,
85   GE_UNORDERED = -1 // Note: different from LE_UNORDERED
88 static inline CMP_RESULT __geXf2__(fp_t a, fp_t b) {
89   const srep_t aInt = toRep(a);
90   const srep_t bInt = toRep(b);
91   const rep_t aAbs = aInt & absMask;
92   const rep_t bAbs = bInt & absMask;
94   if (aAbs > infRep || bAbs > infRep)
95     return GE_UNORDERED;
96   if ((aAbs | bAbs) == 0)
97     return GE_EQUAL;
98   if ((aInt & bInt) >= 0) {
99     if (aInt < bInt)
100       return GE_LESS;
101     else if (aInt == bInt)
102       return GE_EQUAL;
103     else
104       return GE_GREATER;
105   } else {
106     if (aInt > bInt)
107       return GE_LESS;
108     else if (aInt == bInt)
109       return GE_EQUAL;
110     else
111       return GE_GREATER;
112   }
115 static inline CMP_RESULT __unordXf2__(fp_t a, fp_t b) {
116   const rep_t aAbs = toRep(a) & absMask;
117   const rep_t bAbs = toRep(b) & absMask;
118   return aAbs > infRep || bAbs > infRep;