peepmatic: Do not use paths in linear IR

Rather than using paths from the root instruction to the instruction we are
matching against or checking if it is constant or whatever, use temporary
variables. When we successfully match an instruction's opcode, we simultaneously
define these temporaries for the instruction's operands. This is similar to how
open-coding these matches in Rust would use `match` expressions with pattern
matching to bind the operands to variables at the same time.

This saves about 1.8% of instructions retired when Peepmatic is enabled.
This commit is contained in:
Nick Fitzgerald
2020-09-23 15:53:30 -07:00
parent 447c3e71a6
commit c015d69eb8
14 changed files with 633 additions and 844 deletions

View File

@@ -7,7 +7,6 @@ use peepmatic_runtime::{
cc::ConditionCode,
integer_interner::{IntegerId, IntegerInterner},
linear,
paths::{PathId, PathInterner},
};
use std::convert::{TryFrom, TryInto};
use std::fmt::Debug;
@@ -15,7 +14,7 @@ use std::io::{self, Write};
use std::num::{NonZeroU16, NonZeroU32};
#[derive(Debug)]
pub(crate) struct PeepholeDotFmt<'a>(pub(crate) &'a PathInterner, pub(crate) &'a IntegerInterner);
pub(crate) struct PeepholeDotFmt<'a>(pub(crate) &'a IntegerInterner);
impl<TOperator> DotFmt<linear::MatchResult, linear::MatchOp, Box<[linear::Action<TOperator>]>>
for PeepholeDotFmt<'_>
@@ -44,7 +43,7 @@ where
write!(w, "{}", cc)
}
linear::MatchOp::IntegerValue { .. } => {
let x = self.1.lookup(IntegerId(
let x = self.0.lookup(IntegerId(
NonZeroU16::new(x.get().try_into().unwrap()).unwrap(),
));
write!(w, "{}", x)
@@ -61,17 +60,16 @@ where
write!(w, r#"<font face="monospace">"#)?;
let p = p(self.0);
match op {
Opcode { path } => write!(w, "opcode @ {}", p(path))?,
IsConst { path } => write!(w, "is-const? @ {}", p(path))?,
IsPowerOfTwo { path } => write!(w, "is-power-of-two? @ {}", p(path))?,
BitWidth { path } => write!(w, "bit-width @ {}", p(path))?,
FitsInNativeWord { path } => write!(w, "fits-in-native-word @ {}", p(path))?,
Eq { path_a, path_b } => write!(w, "{} == {}", p(path_a), p(path_b))?,
IntegerValue { path } => write!(w, "integer-value @ {}", p(path))?,
BooleanValue { path } => write!(w, "boolean-value @ {}", p(path))?,
ConditionCode { path } => write!(w, "condition-code @ {}", p(path))?,
Opcode(id) => write!(w, "opcode $lhs{}", id.0)?,
IsConst(id) => write!(w, "is-const? $lhs{}", id.0)?,
IsPowerOfTwo(id) => write!(w, "is-power-of-two? $lhs{}", id.0)?,
BitWidth(id) => write!(w, "bit-width $lhs{}", id.0)?,
FitsInNativeWord(id) => write!(w, "fits-in-native-word $lhs{}", id.0)?,
Eq(a, b) => write!(w, "$lhs{} == $lhs{}", a.0, b.0)?,
IntegerValue(id) => write!(w, "integer-value $lhs{}", id.0)?,
BooleanValue(id) => write!(w, "boolean-value $lhs{}", id.0)?,
ConditionCode(id) => write!(w, "condition-code $lhs{}", id.0)?,
Nop => write!(w, "nop")?,
}
@@ -91,11 +89,9 @@ where
write!(w, r#"<font face="monospace">"#)?;
let p = p(self.0);
for a in actions.iter() {
match a {
GetLhs { path } => write!(w, "get-lhs @ {}<br/>", p(path))?,
GetLhs { lhs } => write!(w, "get-lhs $lhs{}<br/>", lhs.0)?,
UnaryUnquote { operator, operand } => {
write!(w, "eval {:?} $rhs{}<br/>", operator, operand.0)?
}
@@ -107,7 +103,7 @@ where
MakeIntegerConst {
value,
bit_width: _,
} => write!(w, "make {}<br/>", self.1.lookup(*value))?,
} => write!(w, "make {}<br/>", self.0.lookup(*value))?,
MakeBooleanConst {
value,
bit_width: _,
@@ -142,13 +138,3 @@ where
writeln!(w, "</font>")
}
}
fn p<'a>(paths: &'a PathInterner) -> impl Fn(&PathId) -> String + 'a {
move |path: &PathId| {
let mut s = vec![];
for b in paths.lookup(*path).0 {
s.push(b.to_string());
}
s.join(".")
}
}