]> git.proxmox.com Git - rustc.git/blob - vendor/compiler_builtins/src/float/cmp.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / vendor / compiler_builtins / src / float / cmp.rs
1 #![allow(unreachable_code)]
2
3 use float::Float;
4 use int::Int;
5
6 #[derive(Clone, Copy)]
7 enum Result {
8 Less,
9 Equal,
10 Greater,
11 Unordered,
12 }
13
14 impl Result {
15 fn to_le_abi(self) -> i32 {
16 match self {
17 Result::Less => -1,
18 Result::Equal => 0,
19 Result::Greater => 1,
20 Result::Unordered => 1,
21 }
22 }
23
24 fn to_ge_abi(self) -> i32 {
25 match self {
26 Result::Less => -1,
27 Result::Equal => 0,
28 Result::Greater => 1,
29 Result::Unordered => -1,
30 }
31 }
32 }
33
34 fn cmp<F: Float>(a: F, b: F) -> Result {
35 let one = F::Int::ONE;
36 let zero = F::Int::ZERO;
37 let szero = F::SignedInt::ZERO;
38
39 let sign_bit = F::SIGN_MASK as F::Int;
40 let abs_mask = sign_bit - one;
41 let exponent_mask = F::EXPONENT_MASK;
42 let inf_rep = exponent_mask;
43
44 let a_rep = a.repr();
45 let b_rep = b.repr();
46 let a_abs = a_rep & abs_mask;
47 let b_abs = b_rep & abs_mask;
48
49 // If either a or b is NaN, they are unordered.
50 if a_abs > inf_rep || b_abs > inf_rep {
51 return Result::Unordered;
52 }
53
54 // If a and b are both zeros, they are equal.
55 if a_abs | b_abs == zero {
56 return Result::Equal;
57 }
58
59 let a_srep = a.signed_repr();
60 let b_srep = b.signed_repr();
61
62 // If at least one of a and b is positive, we get the same result comparing
63 // a and b as signed integers as we would with a fp_ting-point compare.
64 if a_srep & b_srep >= szero {
65 if a_srep < b_srep {
66 Result::Less
67 } else if a_srep == b_srep {
68 Result::Equal
69 } else {
70 Result::Greater
71 }
72 // Otherwise, both are negative, so we need to flip the sense of the
73 // comparison to get the correct result. (This assumes a twos- or ones-
74 // complement integer representation; if integers are represented in a
75 // sign-magnitude representation, then this flip is incorrect).
76 } else if a_srep > b_srep {
77 Result::Less
78 } else if a_srep == b_srep {
79 Result::Equal
80 } else {
81 Result::Greater
82 }
83 }
84
85 fn unord<F: Float>(a: F, b: F) -> bool {
86 let one = F::Int::ONE;
87
88 let sign_bit = F::SIGN_MASK as F::Int;
89 let abs_mask = sign_bit - one;
90 let exponent_mask = F::EXPONENT_MASK;
91 let inf_rep = exponent_mask;
92
93 let a_rep = a.repr();
94 let b_rep = b.repr();
95 let a_abs = a_rep & abs_mask;
96 let b_abs = b_rep & abs_mask;
97
98 a_abs > inf_rep || b_abs > inf_rep
99 }
100
101 intrinsics! {
102 pub extern "C" fn __lesf2(a: f32, b: f32) -> i32 {
103 cmp(a, b).to_le_abi()
104 }
105
106 pub extern "C" fn __gesf2(a: f32, b: f32) -> i32 {
107 cmp(a, b).to_ge_abi()
108 }
109
110 #[arm_aeabi_alias = __aeabi_fcmpun]
111 pub extern "C" fn __unordsf2(a: f32, b: f32) -> i32 {
112 unord(a, b) as i32
113 }
114
115 pub extern "C" fn __eqsf2(a: f32, b: f32) -> i32 {
116 cmp(a, b).to_le_abi()
117 }
118
119 pub extern "C" fn __ltsf2(a: f32, b: f32) -> i32 {
120 cmp(a, b).to_le_abi()
121 }
122
123 pub extern "C" fn __nesf2(a: f32, b: f32) -> i32 {
124 cmp(a, b).to_le_abi()
125 }
126
127 pub extern "C" fn __gtsf2(a: f32, b: f32) -> i32 {
128 cmp(a, b).to_ge_abi()
129 }
130
131 pub extern "C" fn __ledf2(a: f64, b: f64) -> i32 {
132 cmp(a, b).to_le_abi()
133 }
134
135 pub extern "C" fn __gedf2(a: f64, b: f64) -> i32 {
136 cmp(a, b).to_ge_abi()
137 }
138
139 #[arm_aeabi_alias = __aeabi_dcmpun]
140 pub extern "C" fn __unorddf2(a: f64, b: f64) -> i32 {
141 unord(a, b) as i32
142 }
143
144 pub extern "C" fn __eqdf2(a: f64, b: f64) -> i32 {
145 cmp(a, b).to_le_abi()
146 }
147
148 pub extern "C" fn __ltdf2(a: f64, b: f64) -> i32 {
149 cmp(a, b).to_le_abi()
150 }
151
152 pub extern "C" fn __nedf2(a: f64, b: f64) -> i32 {
153 cmp(a, b).to_le_abi()
154 }
155
156 pub extern "C" fn __gtdf2(a: f64, b: f64) -> i32 {
157 cmp(a, b).to_ge_abi()
158 }
159 }
160
161 #[cfg(target_arch = "arm")]
162 intrinsics! {
163 pub extern "aapcs" fn __aeabi_fcmple(a: f32, b: f32) -> i32 {
164 (__lesf2(a, b) <= 0) as i32
165 }
166
167 pub extern "aapcs" fn __aeabi_fcmpge(a: f32, b: f32) -> i32 {
168 (__gesf2(a, b) >= 0) as i32
169 }
170
171 pub extern "aapcs" fn __aeabi_fcmpeq(a: f32, b: f32) -> i32 {
172 (__eqsf2(a, b) == 0) as i32
173 }
174
175 pub extern "aapcs" fn __aeabi_fcmplt(a: f32, b: f32) -> i32 {
176 (__ltsf2(a, b) < 0) as i32
177 }
178
179 pub extern "aapcs" fn __aeabi_fcmpgt(a: f32, b: f32) -> i32 {
180 (__gtsf2(a, b) > 0) as i32
181 }
182
183 pub extern "aapcs" fn __aeabi_dcmple(a: f64, b: f64) -> i32 {
184 (__ledf2(a, b) <= 0) as i32
185 }
186
187 pub extern "aapcs" fn __aeabi_dcmpge(a: f64, b: f64) -> i32 {
188 (__gedf2(a, b) >= 0) as i32
189 }
190
191 pub extern "aapcs" fn __aeabi_dcmpeq(a: f64, b: f64) -> i32 {
192 (__eqdf2(a, b) == 0) as i32
193 }
194
195 pub extern "aapcs" fn __aeabi_dcmplt(a: f64, b: f64) -> i32 {
196 (__ltdf2(a, b) < 0) as i32
197 }
198
199 pub extern "aapcs" fn __aeabi_dcmpgt(a: f64, b: f64) -> i32 {
200 (__gtdf2(a, b) > 0) as i32
201 }
202
203 // On hard-float targets LLVM will use native instructions
204 // for all VFP intrinsics below
205
206 pub extern "C" fn __gesf2vfp(a: f32, b: f32) -> i32 {
207 (a >= b) as i32
208 }
209
210 pub extern "C" fn __gedf2vfp(a: f64, b: f64) -> i32 {
211 (a >= b) as i32
212 }
213
214 pub extern "C" fn __gtsf2vfp(a: f32, b: f32) -> i32 {
215 (a > b) as i32
216 }
217
218 pub extern "C" fn __gtdf2vfp(a: f64, b: f64) -> i32 {
219 (a > b) as i32
220 }
221
222 pub extern "C" fn __ltsf2vfp(a: f32, b: f32) -> i32 {
223 (a < b) as i32
224 }
225
226 pub extern "C" fn __ltdf2vfp(a: f64, b: f64) -> i32 {
227 (a < b) as i32
228 }
229
230 pub extern "C" fn __lesf2vfp(a: f32, b: f32) -> i32 {
231 (a <= b) as i32
232 }
233
234 pub extern "C" fn __ledf2vfp(a: f64, b: f64) -> i32 {
235 (a <= b) as i32
236 }
237
238 pub extern "C" fn __nesf2vfp(a: f32, b: f32) -> i32 {
239 (a != b) as i32
240 }
241
242 pub extern "C" fn __nedf2vfp(a: f64, b: f64) -> i32 {
243 (a != b) as i32
244 }
245
246 pub extern "C" fn __eqsf2vfp(a: f32, b: f32) -> i32 {
247 (a == b) as i32
248 }
249
250 pub extern "C" fn __eqdf2vfp(a: f64, b: f64) -> i32 {
251 (a == b) as i32
252 }
253 }