Start a very simple GVN pass (#79)

* Skeleton simple_gvn pass.
* Basic testing infrastructure for simple-gvn.
* Add can_load and can_store flags to instructions.
* Move the replace_values function into the DataFlowGraph.
* Make InstructionData derive from Hash, PartialEq, and Eq.
* Make EntityList's hash and eq functions panic.
* Change Ieee32 and Ieee64 to store u32 and u64, respectively.
This commit is contained in:
Dan Gohman
2017-05-18 18:18:57 -07:00
committed by Jakob Stoklund Olesen
parent 1d8efaad83
commit c826aefa0a
16 changed files with 256 additions and 57 deletions

View File

@@ -14,7 +14,7 @@ use std::str::FromStr;
///
/// An `Imm64` operand can also be used to represent immediate values of smaller integer types by
/// sign-extending to `i64`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Imm64(i64);
impl Imm64 {
@@ -153,7 +153,7 @@ pub type Uimm8 = u8;
///
/// This is used to encode an immediate offset for load/store instructions. All supported ISAs have
/// a maximum load/store offset that fits in an `i32`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Offset32(i32);
impl Offset32 {
@@ -220,7 +220,7 @@ impl FromStr for Offset32 {
/// 32-bit unsigned immediate offset.
///
/// This is used to encode an immediate offset for WebAssembly heap_load/heap_store instructions.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Uoffset32(u32);
impl Uoffset32 {
@@ -282,17 +282,19 @@ impl FromStr for Uoffset32 {
}
}
/// An IEEE binary32 immediate floating point value.
/// An IEEE binary32 immediate floating point value, represented as a u32
/// containing the bitpattern.
///
/// All bit patterns are allowed.
#[derive(Copy, Clone, Debug)]
pub struct Ieee32(f32);
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Ieee32(u32);
/// An IEEE binary64 immediate floating point value.
/// An IEEE binary64 immediate floating point value, represented as a u64
/// containing the bitpattern.
///
/// All bit patterns are allowed.
#[derive(Copy, Clone, Debug)]
pub struct Ieee64(f64);
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Ieee64(u64);
// Format a floating point number in a way that is reasonably human-readable, and that can be
// converted back to binary without any rounding issues. The hexadecimal formatting of normal and
@@ -531,18 +533,13 @@ fn parse_float(s: &str, w: u8, t: u8) -> Result<u64, &'static str> {
impl Ieee32 {
/// Create a new `Ieee32` representing the number `x`.
pub fn new(x: f32) -> Ieee32 {
Ieee32(x)
}
/// Construct `Ieee32` immediate from raw bits.
pub fn from_bits(x: u32) -> Ieee32 {
Ieee32(unsafe { mem::transmute(x) })
}
}
impl Display for Ieee32 {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let bits: u32 = unsafe { mem::transmute(self.0) };
let bits: u32 = self.0;
format_float(bits as u64, 8, 23, f)
}
}
@@ -552,7 +549,7 @@ impl FromStr for Ieee32 {
fn from_str(s: &str) -> Result<Ieee32, &'static str> {
match parse_float(s, 8, 23) {
Ok(b) => Ok(Ieee32::from_bits(b as u32)),
Ok(b) => Ok(Ieee32(b as u32)),
Err(s) => Err(s),
}
}
@@ -561,18 +558,13 @@ impl FromStr for Ieee32 {
impl Ieee64 {
/// Create a new `Ieee64` representing the number `x`.
pub fn new(x: f64) -> Ieee64 {
Ieee64(x)
}
/// Construct `Ieee64` immediate from raw bits.
pub fn from_bits(x: u64) -> Ieee64 {
Ieee64(unsafe { mem::transmute(x) })
}
}
impl Display for Ieee64 {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let bits: u64 = unsafe { mem::transmute(self.0) };
let bits: u64 = self.0;
format_float(bits, 11, 52, f)
}
}
@@ -582,7 +574,7 @@ impl FromStr for Ieee64 {
fn from_str(s: &str) -> Result<Ieee64, &'static str> {
match parse_float(s, 11, 52) {
Ok(b) => Ok(Ieee64::from_bits(b)),
Ok(b) => Ok(Ieee64(b)),
Err(s) => Err(s),
}
}
@@ -743,11 +735,11 @@ mod tests {
assert_eq!(Ieee32::new(f32::NAN).to_string(), "+NaN");
assert_eq!(Ieee32::new(-f32::NAN).to_string(), "-NaN");
// Construct some qNaNs with payloads.
assert_eq!(Ieee32::from_bits(0x7fc00001).to_string(), "+NaN:0x1");
assert_eq!(Ieee32::from_bits(0x7ff00001).to_string(), "+NaN:0x300001");
assert_eq!(Ieee32(0x7fc00001).to_string(), "+NaN:0x1");
assert_eq!(Ieee32(0x7ff00001).to_string(), "+NaN:0x300001");
// Signaling NaNs.
assert_eq!(Ieee32::from_bits(0x7f800001).to_string(), "+sNaN:0x1");
assert_eq!(Ieee32::from_bits(0x7fa00001).to_string(), "+sNaN:0x200001");
assert_eq!(Ieee32(0x7f800001).to_string(), "+sNaN:0x1");
assert_eq!(Ieee32(0x7fa00001).to_string(), "+sNaN:0x200001");
}
#[test]
@@ -845,14 +837,12 @@ mod tests {
assert_eq!(Ieee64::new(f64::NAN).to_string(), "+NaN");
assert_eq!(Ieee64::new(-f64::NAN).to_string(), "-NaN");
// Construct some qNaNs with payloads.
assert_eq!(Ieee64::from_bits(0x7ff8000000000001).to_string(),
"+NaN:0x1");
assert_eq!(Ieee64::from_bits(0x7ffc000000000001).to_string(),
assert_eq!(Ieee64(0x7ff8000000000001).to_string(), "+NaN:0x1");
assert_eq!(Ieee64(0x7ffc000000000001).to_string(),
"+NaN:0x4000000000001");
// Signaling NaNs.
assert_eq!(Ieee64::from_bits(0x7ff0000000000001).to_string(),
"+sNaN:0x1");
assert_eq!(Ieee64::from_bits(0x7ff4000000000001).to_string(),
assert_eq!(Ieee64(0x7ff0000000000001).to_string(), "+sNaN:0x1");
assert_eq!(Ieee64(0x7ff4000000000001).to_string(),
"+sNaN:0x4000000000001");
}