Skip to content

Commit

Permalink
Merge pull request #222 from whitequark/master
Browse files Browse the repository at this point in the history
Implement comparesf2/comparedf2 intrinsics
  • Loading branch information
alexcrichton authored Jan 13, 2018
2 parents 0ba07e4 + 205322b commit bf912e6
Show file tree
Hide file tree
Showing 8 changed files with 544 additions and 14 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,20 @@ features = ["c"]
## Contributing

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

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

### Porting Reminders

Expand Down Expand Up @@ -133,6 +137,8 @@ features = ["c"]
- [ ] arm/unordsf2vfp.S
- [x] ashldi3.c
- [x] ashrdi3.c
- [x] comparedf2.c
- [x] comparesf2.c
- [x] divdf3.c
- [x] divdi3.c
- [x] divmoddi4.c
Expand Down Expand Up @@ -301,8 +307,6 @@ These builtins are never called by LLVM.
- ~~clzti2.c~~
- ~~cmpdi2.c~~
- ~~cmpti2.c~~
- ~~comparedf2.c~~
- ~~comparesf2.c~~
- ~~ctzdi2.c~~
- ~~ctzsi2.c~~
- ~~ctzti2.c~~
Expand Down
321 changes: 318 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ mod tests {
Adddf3,
Addsf3,

// float/cmp.rs
Gedf2,
Gesf2,
Ledf2,
Lesf2,

// float/conv.rs
Fixdfdi,
Fixdfsi,
Expand Down Expand Up @@ -2529,6 +2535,318 @@ fn floatuntidf() {
}
}

#[derive(Eq, Hash, PartialEq)]
pub struct Gedf2 {
a: u64,
b: u64,
c: i32,
}

impl TestCase for Gedf2 {
fn name() -> &'static str {
"gedf2"
}

fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
let b = gen_f64(rng);
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() {
return None;
}

let c;
if a.is_nan() || b.is_nan() {
c = -1;
} else if a < b {
c = -1;
} else if a > b {
c = 1;
} else {
c = 0;
}

Some(Gedf2 { a: to_u64(a), b: to_u64(b), c })
}

fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}

fn prologue() -> &'static str {
"
use std::mem;
use compiler_builtins::float::cmp::__gedf2;
fn to_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, u64), i32)] = &[
"
}

fn epilogue() -> &'static str {
"
];
#[test]
fn gedf2() {
for &((a, b), c) in TEST_CASES {
let c_ = __gedf2(to_f64(a), to_f64(b));
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}

#[derive(Eq, Hash, PartialEq)]
pub struct Gesf2 {
a: u32,
b: u32,
c: i32,
}

impl TestCase for Gesf2 {
fn name() -> &'static str {
"gesf2"
}

fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
let b = gen_f32(rng);
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() {
return None;
}

let c;
if a.is_nan() || b.is_nan() {
c = -1;
} else if a < b {
c = -1;
} else if a > b {
c = 1;
} else {
c = 0;
}

Some(Gesf2 { a: to_u32(a), b: to_u32(b), c })
}

fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}

fn prologue() -> &'static str {
"
use std::mem;
use compiler_builtins::float::cmp::__gesf2;
fn to_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, u32), i32)] = &[
"
}

fn epilogue() -> &'static str {
"
];
#[test]
fn gesf2() {
for &((a, b), c) in TEST_CASES {
let c_ = __gesf2(to_f32(a), to_f32(b));
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}

#[derive(Eq, Hash, PartialEq)]
pub struct Ledf2 {
a: u64,
b: u64,
c: i32,
}

impl TestCase for Ledf2 {
fn name() -> &'static str {
"ledf2"
}

fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f64(rng);
let b = gen_f64(rng);
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() {
return None;
}

let c;
if a.is_nan() || b.is_nan() {
c = 1;
} else if a < b {
c = -1;
} else if a > b {
c = 1;
} else {
c = 0;
}

Some(Ledf2 { a: to_u64(a), b: to_u64(b), c })
}

fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}

fn prologue() -> &'static str {
"
use std::mem;
use compiler_builtins::float::cmp::__ledf2;
fn to_f64(x: u64) -> f64 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u64, u64), i32)] = &[
"
}

fn epilogue() -> &'static str {
"
];
#[test]
fn ledf2() {
for &((a, b), c) in TEST_CASES {
let c_ = __ledf2(to_f64(a), to_f64(b));
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}

#[derive(Eq, Hash, PartialEq)]
pub struct Lesf2 {
a: u32,
b: u32,
c: i32,
}

impl TestCase for Lesf2 {
fn name() -> &'static str {
"lesf2"
}

fn generate<R>(rng: &mut R) -> Option<Self>
where
R: Rng,
Self: Sized,
{
let a = gen_f32(rng);
let b = gen_f32(rng);
// TODO accept NaNs. We don't do that right now because we can't check
// for NaN-ness on the thumb targets (due to missing intrinsics)
if a.is_nan() || b.is_nan() {
return None;
}

let c;
if a.is_nan() || b.is_nan() {
c = 1;
} else if a < b {
c = -1;
} else if a > b {
c = 1;
} else {
c = 0;
}

Some(Lesf2 { a: to_u32(a), b: to_u32(b), c })
}

fn to_string(&self, buffer: &mut String) {
writeln!(
buffer,
"(({a}, {b}), {c}),",
a = self.a,
b = self.b,
c = self.c
)
.unwrap();
}

fn prologue() -> &'static str {
"
use std::mem;
use compiler_builtins::float::cmp::__lesf2;
fn to_f32(x: u32) -> f32 {
unsafe { mem::transmute(x) }
}
static TEST_CASES: &[((u32, u32), i32)] = &[
"
}

fn epilogue() -> &'static str {
"
];
#[test]
fn lesf2() {
for &((a, b), c) in TEST_CASES {
let c_ = __lesf2(to_f32(a), to_f32(b));
assert_eq!(((a, b), c), ((a, b), c_));
}
}
"
}
}

#[derive(Eq, Hash, PartialEq)]
pub struct Moddi3 {
a: i64,
Expand Down Expand Up @@ -4982,8 +5300,6 @@ mod c {
"clzdi2.c",
"clzsi2.c",
"cmpdi2.c",
"comparedf2.c",
"comparesf2.c",
"ctzdi2.c",
"ctzsi2.c",
"divdc3.c",
Expand Down Expand Up @@ -5127,7 +5443,6 @@ mod c {
"arm/bswapsi2.S",
"arm/clzdi2.S",
"arm/clzsi2.S",
"arm/comparesf2.S",
"arm/divmodsi4.S",
"arm/modsi3.S",
"arm/switch16.S",
Expand Down
Loading

0 comments on commit bf912e6

Please sign in to comment.