Refactor so as to convert ExtraInfo when potentially canonicalizing.

It seemed like a good idea at the time, but in practice we discard the extra info all or almost all of the time.

This also introduces a new bug. In an operation like multiply, it's valid to multiply two values, one with a pending NaN and one without. As written, in the SIMD case (because of the two kinds of pending in play), we assert.
This commit is contained in:
Nick Lewycky 2019-11-06 20:45:50 -08:00
parent 26c8fd52c8
commit 284948b6d4
2 changed files with 465 additions and 300 deletions

File diff suppressed because it is too large Load Diff

View File

@ -115,7 +115,7 @@ impl ExtraInfo {
pub fn strip_pending(&self) -> ExtraInfo { pub fn strip_pending(&self) -> ExtraInfo {
ExtraInfo { ExtraInfo {
state: self.state state: self.state
& !(ExtraInfo::arithmetic_f32().state | ExtraInfo::arithmetic_f64().state), & !(ExtraInfo::pending_f32_nan().state | ExtraInfo::pending_f64_nan().state),
} }
} }
} }
@ -154,13 +154,14 @@ impl BitOrAssign for ExtraInfo {
} }
} }
// Intersection for ExtraInfo. Does not check the "pending" bits, since those // Intersection for ExtraInfo.
// aren't safe to discard (or even to reorder). Callers are assumed to be in a
// situation where the result will have a pending bit set unconditionally.
impl BitAnd for ExtraInfo { impl BitAnd for ExtraInfo {
type Output = Self; type Output = Self;
fn bitand(self, other: Self) -> Self { fn bitand(self, other: Self) -> Self {
match ( // Pending canonicalizations are not safe to discard, or even reorder.
assert!(self.has_pending_f32_nan() == other.has_pending_f32_nan());
assert!(self.has_pending_f64_nan() == other.has_pending_f64_nan());
let info = match (
self.is_arithmetic_f32() && other.is_arithmetic_f32(), self.is_arithmetic_f32() && other.is_arithmetic_f32(),
self.is_arithmetic_f64() && other.is_arithmetic_f64(), self.is_arithmetic_f64() && other.is_arithmetic_f64(),
) { ) {
@ -168,7 +169,14 @@ impl BitAnd for ExtraInfo {
(true, false) => ExtraInfo::arithmetic_f32(), (true, false) => ExtraInfo::arithmetic_f32(),
(false, true) => ExtraInfo::arithmetic_f64(), (false, true) => ExtraInfo::arithmetic_f64(),
(true, true) => ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64(), (true, true) => ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64(),
} };
let info = match (self.has_pending_f32_nan(), self.has_pending_f64_nan()) {
(false, false) => info,
(true, false) => info | ExtraInfo::pending_f32_nan(),
(false, true) => info | ExtraInfo::pending_f64_nan(),
(true, true) => panic!(""),
};
info
} }
} }