Skip to content

Commit bf912e6

Browse files
authored
Merge pull request #222 from whitequark/master
Implement comparesf2/comparedf2 intrinsics
2 parents 0ba07e4 + 205322b commit bf912e6

File tree

8 files changed

+544
-14
lines changed

8 files changed

+544
-14
lines changed

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,20 @@ features = ["c"]
5252
## Contributing
5353

5454
1. Pick one or more intrinsics from the [pending list](#progress).
55-
2. Fork this repository
56-
3. Port the intrinsic(s) and their corresponding [unit tests][1] from their [C implementation][2] to
57-
Rust.
58-
4. Send a Pull Request (PR)
59-
5. Once the PR passes our extensive [testing infrastructure][3], we'll merge it!
55+
2. Fork this repository.
56+
3. Port the intrinsic(s) and their corresponding [unit tests][1] from their
57+
[C implementation][2] to Rust.
58+
4. Implement a [test generator][3] to compare the behavior of the ported intrinsic(s)
59+
with their implementation on the testing host. Note that randomized compiler-builtin tests
60+
should be run using `cargo test --features gen-tests`.
61+
4. Send a Pull Request (PR).
62+
5. Once the PR passes our extensive [testing infrastructure][4], we'll merge it!
6063
6. Celebrate :tada:
6164

6265
[1]: https://github.com/rust-lang/compiler-rt/tree/8598065bd965d9713bfafb6c1e766d63a7b17b89/test/builtins/Unit
6366
[2]: https://github.com/rust-lang/compiler-rt/tree/8598065bd965d9713bfafb6c1e766d63a7b17b89/lib/builtins
64-
[3]: https://travis-ci.org/rust-lang-nursery/compiler-builtins
67+
[3]: https://github.com/rust-lang-nursery/compiler-builtins/blob/0ba07e49264a54cb5bbd4856fcea083bb3fbec15/build.rs#L180-L265
68+
[4]: https://travis-ci.org/rust-lang-nursery/compiler-builtins
6569

6670
### Porting Reminders
6771

@@ -133,6 +137,8 @@ features = ["c"]
133137
- [ ] arm/unordsf2vfp.S
134138
- [x] ashldi3.c
135139
- [x] ashrdi3.c
140+
- [x] comparedf2.c
141+
- [x] comparesf2.c
136142
- [x] divdf3.c
137143
- [x] divdi3.c
138144
- [x] divmoddi4.c
@@ -301,8 +307,6 @@ These builtins are never called by LLVM.
301307
- ~~clzti2.c~~
302308
- ~~cmpdi2.c~~
303309
- ~~cmpti2.c~~
304-
- ~~comparedf2.c~~
305-
- ~~comparesf2.c~~
306310
- ~~ctzdi2.c~~
307311
- ~~ctzsi2.c~~
308312
- ~~ctzti2.c~~

build.rs

Lines changed: 318 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ mod tests {
8989
Adddf3,
9090
Addsf3,
9191

92+
// float/cmp.rs
93+
Gedf2,
94+
Gesf2,
95+
Ledf2,
96+
Lesf2,
97+
9298
// float/conv.rs
9399
Fixdfdi,
94100
Fixdfsi,
@@ -2529,6 +2535,318 @@ fn floatuntidf() {
25292535
}
25302536
}
25312537

2538+
#[derive(Eq, Hash, PartialEq)]
2539+
pub struct Gedf2 {
2540+
a: u64,
2541+
b: u64,
2542+
c: i32,
2543+
}
2544+
2545+
impl TestCase for Gedf2 {
2546+
fn name() -> &'static str {
2547+
"gedf2"
2548+
}
2549+
2550+
fn generate<R>(rng: &mut R) -> Option<Self>
2551+
where
2552+
R: Rng,
2553+
Self: Sized,
2554+
{
2555+
let a = gen_f64(rng);
2556+
let b = gen_f64(rng);
2557+
// TODO accept NaNs. We don't do that right now because we can't check
2558+
// for NaN-ness on the thumb targets (due to missing intrinsics)
2559+
if a.is_nan() || b.is_nan() {
2560+
return None;
2561+
}
2562+
2563+
let c;
2564+
if a.is_nan() || b.is_nan() {
2565+
c = -1;
2566+
} else if a < b {
2567+
c = -1;
2568+
} else if a > b {
2569+
c = 1;
2570+
} else {
2571+
c = 0;
2572+
}
2573+
2574+
Some(Gedf2 { a: to_u64(a), b: to_u64(b), c })
2575+
}
2576+
2577+
fn to_string(&self, buffer: &mut String) {
2578+
writeln!(
2579+
buffer,
2580+
"(({a}, {b}), {c}),",
2581+
a = self.a,
2582+
b = self.b,
2583+
c = self.c
2584+
)
2585+
.unwrap();
2586+
}
2587+
2588+
fn prologue() -> &'static str {
2589+
"
2590+
use std::mem;
2591+
use compiler_builtins::float::cmp::__gedf2;
2592+
2593+
fn to_f64(x: u64) -> f64 {
2594+
unsafe { mem::transmute(x) }
2595+
}
2596+
2597+
static TEST_CASES: &[((u64, u64), i32)] = &[
2598+
"
2599+
}
2600+
2601+
fn epilogue() -> &'static str {
2602+
"
2603+
];
2604+
2605+
#[test]
2606+
fn gedf2() {
2607+
for &((a, b), c) in TEST_CASES {
2608+
let c_ = __gedf2(to_f64(a), to_f64(b));
2609+
assert_eq!(((a, b), c), ((a, b), c_));
2610+
}
2611+
}
2612+
"
2613+
}
2614+
}
2615+
2616+
#[derive(Eq, Hash, PartialEq)]
2617+
pub struct Gesf2 {
2618+
a: u32,
2619+
b: u32,
2620+
c: i32,
2621+
}
2622+
2623+
impl TestCase for Gesf2 {
2624+
fn name() -> &'static str {
2625+
"gesf2"
2626+
}
2627+
2628+
fn generate<R>(rng: &mut R) -> Option<Self>
2629+
where
2630+
R: Rng,
2631+
Self: Sized,
2632+
{
2633+
let a = gen_f32(rng);
2634+
let b = gen_f32(rng);
2635+
// TODO accept NaNs. We don't do that right now because we can't check
2636+
// for NaN-ness on the thumb targets (due to missing intrinsics)
2637+
if a.is_nan() || b.is_nan() {
2638+
return None;
2639+
}
2640+
2641+
let c;
2642+
if a.is_nan() || b.is_nan() {
2643+
c = -1;
2644+
} else if a < b {
2645+
c = -1;
2646+
} else if a > b {
2647+
c = 1;
2648+
} else {
2649+
c = 0;
2650+
}
2651+
2652+
Some(Gesf2 { a: to_u32(a), b: to_u32(b), c })
2653+
}
2654+
2655+
fn to_string(&self, buffer: &mut String) {
2656+
writeln!(
2657+
buffer,
2658+
"(({a}, {b}), {c}),",
2659+
a = self.a,
2660+
b = self.b,
2661+
c = self.c
2662+
)
2663+
.unwrap();
2664+
}
2665+
2666+
fn prologue() -> &'static str {
2667+
"
2668+
use std::mem;
2669+
use compiler_builtins::float::cmp::__gesf2;
2670+
2671+
fn to_f32(x: u32) -> f32 {
2672+
unsafe { mem::transmute(x) }
2673+
}
2674+
2675+
static TEST_CASES: &[((u32, u32), i32)] = &[
2676+
"
2677+
}
2678+
2679+
fn epilogue() -> &'static str {
2680+
"
2681+
];
2682+
2683+
#[test]
2684+
fn gesf2() {
2685+
for &((a, b), c) in TEST_CASES {
2686+
let c_ = __gesf2(to_f32(a), to_f32(b));
2687+
assert_eq!(((a, b), c), ((a, b), c_));
2688+
}
2689+
}
2690+
"
2691+
}
2692+
}
2693+
2694+
#[derive(Eq, Hash, PartialEq)]
2695+
pub struct Ledf2 {
2696+
a: u64,
2697+
b: u64,
2698+
c: i32,
2699+
}
2700+
2701+
impl TestCase for Ledf2 {
2702+
fn name() -> &'static str {
2703+
"ledf2"
2704+
}
2705+
2706+
fn generate<R>(rng: &mut R) -> Option<Self>
2707+
where
2708+
R: Rng,
2709+
Self: Sized,
2710+
{
2711+
let a = gen_f64(rng);
2712+
let b = gen_f64(rng);
2713+
// TODO accept NaNs. We don't do that right now because we can't check
2714+
// for NaN-ness on the thumb targets (due to missing intrinsics)
2715+
if a.is_nan() || b.is_nan() {
2716+
return None;
2717+
}
2718+
2719+
let c;
2720+
if a.is_nan() || b.is_nan() {
2721+
c = 1;
2722+
} else if a < b {
2723+
c = -1;
2724+
} else if a > b {
2725+
c = 1;
2726+
} else {
2727+
c = 0;
2728+
}
2729+
2730+
Some(Ledf2 { a: to_u64(a), b: to_u64(b), c })
2731+
}
2732+
2733+
fn to_string(&self, buffer: &mut String) {
2734+
writeln!(
2735+
buffer,
2736+
"(({a}, {b}), {c}),",
2737+
a = self.a,
2738+
b = self.b,
2739+
c = self.c
2740+
)
2741+
.unwrap();
2742+
}
2743+
2744+
fn prologue() -> &'static str {
2745+
"
2746+
use std::mem;
2747+
use compiler_builtins::float::cmp::__ledf2;
2748+
2749+
fn to_f64(x: u64) -> f64 {
2750+
unsafe { mem::transmute(x) }
2751+
}
2752+
2753+
static TEST_CASES: &[((u64, u64), i32)] = &[
2754+
"
2755+
}
2756+
2757+
fn epilogue() -> &'static str {
2758+
"
2759+
];
2760+
2761+
#[test]
2762+
fn ledf2() {
2763+
for &((a, b), c) in TEST_CASES {
2764+
let c_ = __ledf2(to_f64(a), to_f64(b));
2765+
assert_eq!(((a, b), c), ((a, b), c_));
2766+
}
2767+
}
2768+
"
2769+
}
2770+
}
2771+
2772+
#[derive(Eq, Hash, PartialEq)]
2773+
pub struct Lesf2 {
2774+
a: u32,
2775+
b: u32,
2776+
c: i32,
2777+
}
2778+
2779+
impl TestCase for Lesf2 {
2780+
fn name() -> &'static str {
2781+
"lesf2"
2782+
}
2783+
2784+
fn generate<R>(rng: &mut R) -> Option<Self>
2785+
where
2786+
R: Rng,
2787+
Self: Sized,
2788+
{
2789+
let a = gen_f32(rng);
2790+
let b = gen_f32(rng);
2791+
// TODO accept NaNs. We don't do that right now because we can't check
2792+
// for NaN-ness on the thumb targets (due to missing intrinsics)
2793+
if a.is_nan() || b.is_nan() {
2794+
return None;
2795+
}
2796+
2797+
let c;
2798+
if a.is_nan() || b.is_nan() {
2799+
c = 1;
2800+
} else if a < b {
2801+
c = -1;
2802+
} else if a > b {
2803+
c = 1;
2804+
} else {
2805+
c = 0;
2806+
}
2807+
2808+
Some(Lesf2 { a: to_u32(a), b: to_u32(b), c })
2809+
}
2810+
2811+
fn to_string(&self, buffer: &mut String) {
2812+
writeln!(
2813+
buffer,
2814+
"(({a}, {b}), {c}),",
2815+
a = self.a,
2816+
b = self.b,
2817+
c = self.c
2818+
)
2819+
.unwrap();
2820+
}
2821+
2822+
fn prologue() -> &'static str {
2823+
"
2824+
use std::mem;
2825+
use compiler_builtins::float::cmp::__lesf2;
2826+
2827+
fn to_f32(x: u32) -> f32 {
2828+
unsafe { mem::transmute(x) }
2829+
}
2830+
2831+
static TEST_CASES: &[((u32, u32), i32)] = &[
2832+
"
2833+
}
2834+
2835+
fn epilogue() -> &'static str {
2836+
"
2837+
];
2838+
2839+
#[test]
2840+
fn lesf2() {
2841+
for &((a, b), c) in TEST_CASES {
2842+
let c_ = __lesf2(to_f32(a), to_f32(b));
2843+
assert_eq!(((a, b), c), ((a, b), c_));
2844+
}
2845+
}
2846+
"
2847+
}
2848+
}
2849+
25322850
#[derive(Eq, Hash, PartialEq)]
25332851
pub struct Moddi3 {
25342852
a: i64,
@@ -4982,8 +5300,6 @@ mod c {
49825300
"clzdi2.c",
49835301
"clzsi2.c",
49845302
"cmpdi2.c",
4985-
"comparedf2.c",
4986-
"comparesf2.c",
49875303
"ctzdi2.c",
49885304
"ctzsi2.c",
49895305
"divdc3.c",
@@ -5127,7 +5443,6 @@ mod c {
51275443
"arm/bswapsi2.S",
51285444
"arm/clzdi2.S",
51295445
"arm/clzsi2.S",
5130-
"arm/comparesf2.S",
51315446
"arm/divmodsi4.S",
51325447
"arm/modsi3.S",
51335448
"arm/switch16.S",

0 commit comments

Comments
 (0)