peepmatic: Apply some review suggestions from @bjorn3

This commit is contained in:
Nick Fitzgerald
2020-05-08 13:47:14 -07:00
parent a9b280ca3a
commit 22a070ed4f
4 changed files with 181 additions and 219 deletions

View File

@@ -196,7 +196,7 @@ fn const_to_value<'a>(builder: impl InstBuilder<'a>, c: Constant, root: Inst) ->
Constant::Int(x, width) => { Constant::Int(x, width) => {
let width = bit_width(builder.data_flow_graph(), width, root); let width = bit_width(builder.data_flow_graph(), width, root);
let ty = match width { let ty = match width {
1 | 8 => types::I8, 8 => types::I8,
16 => types::I16, 16 => types::I16,
32 => types::I32, 32 => types::I32,
64 => types::I64, 64 => types::I64,
@@ -407,7 +407,7 @@ fn get_argument(dfg: &DataFlowGraph, inst: Inst, i: usize) -> Option<Value> {
fn peepmatic_ty_to_ir_ty(ty: Type, dfg: &DataFlowGraph, root: Inst) -> types::Type { fn peepmatic_ty_to_ir_ty(ty: Type, dfg: &DataFlowGraph, root: Inst) -> types::Type {
match (ty.kind, bit_width(dfg, ty.bit_width, root)) { match (ty.kind, bit_width(dfg, ty.bit_width, root)) {
(Kind::Int, 1) | (Kind::Int, 8) => types::I8, (Kind::Int, 8) => types::I8,
(Kind::Int, 16) => types::I16, (Kind::Int, 16) => types::I16,
(Kind::Int, 32) => types::I32, (Kind::Int, 32) => types::I32,
(Kind::Int, 64) => types::I64, (Kind::Int, 64) => types::I64,

View File

@@ -53,6 +53,9 @@ pub fn bool_to_match_result(b: bool) -> MatchResult {
unsafe { Ok(NonZeroU32::new_unchecked(b + 1)) } unsafe { Ok(NonZeroU32::new_unchecked(b + 1)) }
} }
/// A partial match of an optimization's LHS and partial construction of its
/// RHS.
///
/// An increment is a matching operation, the expected result from that /// An increment is a matching operation, the expected result from that
/// operation to continue to the next increment, and the actions to take to /// operation to continue to the next increment, and the actions to take to
/// build up the LHS scope and RHS instructions given that we got the expected /// build up the LHS scope and RHS instructions given that we got the expected
@@ -156,17 +159,18 @@ pub struct LhsId(pub u16);
pub struct RhsId(pub u16); pub struct RhsId(pub u16);
/// An action to perform when transitioning between states in the automata. /// An action to perform when transitioning between states in the automata.
///
/// When evaluating actions, the `i^th` action implicitly defines the
/// `RhsId(i)`.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Action { pub enum Action {
/// Implicitly define the n^th built up RHS instruction as something from /// Reuse something from the left-hand side.
/// the left-hand side.
GetLhs { GetLhs {
/// The path to the instruction or value. /// The path to the instruction or value.
path: PathId, path: PathId,
}, },
/// Implicitly define the n^th RHS instruction as the result of the /// Perform compile-time evaluation.
/// compile-time evaluation off this unquote operation.
UnaryUnquote { UnaryUnquote {
/// The unquote operator. /// The unquote operator.
operator: UnquoteOperator, operator: UnquoteOperator,
@@ -174,8 +178,7 @@ pub enum Action {
operand: RhsId, operand: RhsId,
}, },
/// Implicitly define the n^th RHS instruction as the result of the /// Perform compile-time evaluation.
/// compile-time evaluation off this unquote operation.
BinaryUnquote { BinaryUnquote {
/// The unquote operator. /// The unquote operator.
operator: UnquoteOperator, operator: UnquoteOperator,
@@ -183,7 +186,7 @@ pub enum Action {
operands: [RhsId; 2], operands: [RhsId; 2],
}, },
/// Implicitly define the n^th RHS as an integer constant. /// Create an integer constant.
MakeIntegerConst { MakeIntegerConst {
/// The constant integer value. /// The constant integer value.
value: IntegerId, value: IntegerId,
@@ -191,7 +194,7 @@ pub enum Action {
bit_width: BitWidth, bit_width: BitWidth,
}, },
/// Implicitly define the n^th RHS as a boolean constant. /// Create a boolean constant.
MakeBooleanConst { MakeBooleanConst {
/// The constant boolean value. /// The constant boolean value.
value: bool, value: bool,
@@ -199,14 +202,13 @@ pub enum Action {
bit_width: BitWidth, bit_width: BitWidth,
}, },
/// Implicitly defint the n^th RHS as a condition code. /// Create a condition code.
MakeConditionCode { MakeConditionCode {
/// The condition code. /// The condition code.
cc: ConditionCode, cc: ConditionCode,
}, },
/// Implicitly define the n^th RHS instruction by making a unary /// Make a unary instruction.
/// instruction.
MakeUnaryInst { MakeUnaryInst {
/// The operand for this instruction. /// The operand for this instruction.
operand: RhsId, operand: RhsId,
@@ -216,8 +218,7 @@ pub enum Action {
operator: Operator, operator: Operator,
}, },
/// Implicitly define the n^th RHS instruction by making a binary /// Make a binary instruction.
/// instruction.
MakeBinaryInst { MakeBinaryInst {
/// The opcode for this instruction. /// The opcode for this instruction.
operator: Operator, operator: Operator,
@@ -227,8 +228,7 @@ pub enum Action {
operands: [RhsId; 2], operands: [RhsId; 2],
}, },
/// Implicitly define the n^th RHS instruction by making a ternary /// Make a ternary instruction.
/// instruction.
MakeTernaryInst { MakeTernaryInst {
/// The opcode for this instruction. /// The opcode for this instruction.
operator: Operator, operator: Operator,

View File

@@ -54,17 +54,17 @@ pub struct PathId(u16);
/// path mapping. /// path mapping.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct PathInterner { pub struct PathInterner {
// A map from a path (whose owned data is inside `arena`) to the canonical /// A map from a path (whose owned data is inside `arena`) to the canonical
// `PathId` we assigned it when interning it. /// `PathId` we assigned it when interning it.
map: HashMap<UnsafePath, PathId>, map: HashMap<UnsafePath, PathId>,
// A map from a `PathId` index to an unsafe, self-borrowed path pointing /// A map from a `PathId` index to an unsafe, self-borrowed path pointing
// into `arena`. It is safe to given these out as safe `Path`s, as long as /// into `arena`. It is safe to given these out as safe `Path`s, as long as
// the lifetime is not longer than this `PathInterner`'s lifetime. /// the lifetime is not longer than this `PathInterner`'s lifetime.
paths: Vec<UnsafePath>, paths: Vec<UnsafePath>,
// Bump allocation arena for path data. The bump arena ensures that these /// Bump allocation arena for path data. The bump arena ensures that these
// allocations never move, and are therefore safe for self-references. /// allocations never move, and are therefore safe for self-references.
arena: bumpalo::Bump, arena: bumpalo::Bump,
} }

View File

@@ -599,13 +599,17 @@ mod tests {
let mut i = |i: u64| integers.intern(i); let mut i = |i: u64| integers.intern(i);
#[allow(unused_variables)] #[allow(unused_variables)]
let expected = $make_expected(&mut p, &mut i); let make_expected: fn(
&mut dyn FnMut(&[u8]) -> PathId,
&mut dyn FnMut(u64) -> IntegerId,
) -> Vec<linear::Increment> = $make_expected;
let expected = make_expected(&mut p, &mut i);
dbg!(&expected); dbg!(&expected);
let actual = linearize_optimization(&mut paths, &mut integers, &opts.optimizations[0]); let actual = linearize_optimization(&mut paths, &mut integers, &opts.optimizations[0]);
dbg!(&actual); dbg!(&actual.increments);
assert_eq!(expected, actual); assert_eq!(expected, actual.increments);
} }
}; };
} }
@@ -617,234 +621,192 @@ mod tests {
(is-power-of-two $C)) (is-power-of-two $C))
(ishl $x $C)) (ishl $x $C))
", ",
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { |p, i| vec![
linear::Optimization { linear::Increment {
increments: vec![ operation: Opcode { path: p(&[0]) },
linear::Increment { expected: Ok(NonZeroU32::new(Operator::Imul as _).unwrap()),
operation: Opcode { path: p(&[0]) }, actions: vec![
expected: Ok(NonZeroU32::new(Operator::Imul as _).unwrap()), GetLhs { path: p(&[0, 0]) },
actions: vec![ GetLhs { path: p(&[0, 1]) },
GetLhs { path: p(&[0, 0]) }, MakeBinaryInst {
GetLhs { path: p(&[0, 1]) }, operator: Operator::Ishl,
MakeBinaryInst { r#type: Type {
operator: Operator::Ishl, kind: Kind::Int,
r#type: Type { bit_width: BitWidth::Polymorphic,
kind: Kind::Int, },
bit_width: BitWidth::Polymorphic, operands: [linear::RhsId(0), linear::RhsId(1)],
},
operands: [linear::RhsId(0), linear::RhsId(1)],
},
],
},
linear::Increment {
operation: Nop,
expected: Err(Else),
actions: vec![],
},
linear::Increment {
operation: IsConst { path: p(&[0, 1]) },
expected: bool_to_match_result(true),
actions: vec![],
},
linear::Increment {
operation: IsPowerOfTwo { path: p(&[0, 1]) },
expected: bool_to_match_result(true),
actions: vec![],
}, },
], ],
} },
}, linear::Increment {
operation: Nop,
expected: Err(Else),
actions: vec![],
},
linear::Increment {
operation: IsConst { path: p(&[0, 1]) },
expected: bool_to_match_result(true),
actions: vec![],
},
linear::Increment {
operation: IsPowerOfTwo { path: p(&[0, 1]) },
expected: bool_to_match_result(true),
actions: vec![],
},
],
); );
linearizes_to!( linearizes_to!(variable_pattern_id_optimization, "(=> $x $x)", |p, i| vec![
variable_pattern_id_optimization, linear::Increment {
"(=> $x $x)", operation: Nop,
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { expected: Err(Else),
linear::Optimization { actions: vec![GetLhs { path: p(&[0]) }],
increments: vec![linear::Increment { }
operation: Nop, ]);
expected: Err(Else),
actions: vec![GetLhs { path: p(&[0]) }],
}],
}
},
);
linearizes_to!( linearizes_to!(constant_pattern_id_optimization, "(=> $C $C)", |p, i| vec![
constant_pattern_id_optimization, linear::Increment {
"(=> $C $C)", operation: IsConst { path: p(&[0]) },
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { expected: bool_to_match_result(true),
linear::Optimization { actions: vec![GetLhs { path: p(&[0]) }],
increments: vec![linear::Increment { }
operation: IsConst { path: p(&[0]) }, ]);
expected: bool_to_match_result(true),
actions: vec![GetLhs { path: p(&[0]) }],
}],
}
},
);
linearizes_to!( linearizes_to!(
boolean_literal_id_optimization, boolean_literal_id_optimization,
"(=> true true)", "(=> true true)",
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { |p, i| vec![linear::Increment {
linear::Optimization { operation: BooleanValue { path: p(&[0]) },
increments: vec![linear::Increment { expected: bool_to_match_result(true),
operation: BooleanValue { path: p(&[0]) }, actions: vec![MakeBooleanConst {
expected: bool_to_match_result(true), value: true,
actions: vec![MakeBooleanConst { bit_width: BitWidth::Polymorphic,
value: true, }],
bit_width: BitWidth::Polymorphic, }]
}],
}],
}
},
); );
linearizes_to!( linearizes_to!(number_literal_id_optimization, "(=> 5 5)", |p, i| vec![
number_literal_id_optimization, linear::Increment {
"(=> 5 5)", operation: IntegerValue { path: p(&[0]) },
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { expected: Ok(i(5).into()),
linear::Optimization { actions: vec![MakeIntegerConst {
increments: vec![linear::Increment { value: i(5),
operation: IntegerValue { path: p(&[0]) }, bit_width: BitWidth::Polymorphic,
expected: Ok(i(5).into()), }],
actions: vec![MakeIntegerConst { }
value: i(5), ]);
bit_width: BitWidth::Polymorphic,
}],
}],
}
},
);
linearizes_to!( linearizes_to!(
operation_id_optimization, operation_id_optimization,
"(=> (iconst $C) (iconst $C))", "(=> (iconst $C) (iconst $C))",
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { |p, i| vec![
linear::Optimization { linear::Increment {
increments: vec![ operation: Opcode { path: p(&[0]) },
linear::Increment { expected: Ok(NonZeroU32::new(Operator::Iconst as _).unwrap()),
operation: Opcode { path: p(&[0]) }, actions: vec![
expected: Ok(NonZeroU32::new(Operator::Iconst as _).unwrap()), GetLhs { path: p(&[0, 0]) },
actions: vec![ MakeUnaryInst {
GetLhs { path: p(&[0, 0]) }, operator: Operator::Iconst,
MakeUnaryInst { r#type: Type {
operator: Operator::Iconst, kind: Kind::Int,
r#type: Type { bit_width: BitWidth::Polymorphic,
kind: Kind::Int, },
bit_width: BitWidth::Polymorphic, operand: linear::RhsId(0),
},
operand: linear::RhsId(0),
},
],
},
linear::Increment {
operation: IsConst { path: p(&[0, 0]) },
expected: bool_to_match_result(true),
actions: vec![],
}, },
], ],
} },
}, linear::Increment {
operation: IsConst { path: p(&[0, 0]) },
expected: bool_to_match_result(true),
actions: vec![],
},
]
); );
linearizes_to!( linearizes_to!(
redundant_bor, redundant_bor,
"(=> (bor $x (bor $x $y)) (bor $x $y))", "(=> (bor $x (bor $x $y)) (bor $x $y))",
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { |p, i| vec![
linear::Optimization { linear::Increment {
increments: vec![ operation: Opcode { path: p(&[0]) },
linear::Increment { expected: Ok(NonZeroU32::new(Operator::Bor as _).unwrap()),
operation: Opcode { path: p(&[0]) }, actions: vec![
expected: Ok(NonZeroU32::new(Operator::Bor as _).unwrap()), GetLhs { path: p(&[0, 0]) },
actions: vec![ GetLhs {
GetLhs { path: p(&[0, 0]) }, path: p(&[0, 1, 1]),
GetLhs {
path: p(&[0, 1, 1]),
},
MakeBinaryInst {
operator: Operator::Bor,
r#type: Type {
kind: Kind::Int,
bit_width: BitWidth::Polymorphic,
},
operands: [linear::RhsId(0), linear::RhsId(1)],
},
],
}, },
linear::Increment { MakeBinaryInst {
operation: Nop, operator: Operator::Bor,
expected: Err(Else), r#type: Type {
actions: vec![], kind: Kind::Int,
}, bit_width: BitWidth::Polymorphic,
linear::Increment {
operation: Opcode { path: p(&[0, 1]) },
expected: Ok(NonZeroU32::new(Operator::Bor as _).unwrap()),
actions: vec![],
},
linear::Increment {
operation: Eq {
path_a: p(&[0, 1, 0]),
path_b: p(&[0, 0]),
}, },
expected: bool_to_match_result(true), operands: [linear::RhsId(0), linear::RhsId(1)],
actions: vec![],
},
linear::Increment {
operation: Nop,
expected: Err(Else),
actions: vec![],
}, },
], ],
} },
}, linear::Increment {
operation: Nop,
expected: Err(Else),
actions: vec![],
},
linear::Increment {
operation: Opcode { path: p(&[0, 1]) },
expected: Ok(NonZeroU32::new(Operator::Bor as _).unwrap()),
actions: vec![],
},
linear::Increment {
operation: Eq {
path_a: p(&[0, 1, 0]),
path_b: p(&[0, 0]),
},
expected: bool_to_match_result(true),
actions: vec![],
},
linear::Increment {
operation: Nop,
expected: Err(Else),
actions: vec![],
},
]
); );
linearizes_to!( linearizes_to!(
large_integers, large_integers,
// u64::MAX // u64::MAX
"(=> 18446744073709551615 0)", "(=> 18446744073709551615 0)",
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { |p, i| vec![linear::Increment {
linear::Optimization { operation: IntegerValue { path: p(&[0]) },
increments: vec![linear::Increment { expected: Ok(i(std::u64::MAX).into()),
operation: IntegerValue { path: p(&[0]) }, actions: vec![MakeIntegerConst {
expected: Ok(i(std::u64::MAX).into()), value: i(0),
actions: vec![MakeIntegerConst { bit_width: BitWidth::Polymorphic,
value: i(0), }],
bit_width: BitWidth::Polymorphic, }]
}],
}],
}
}
); );
linearizes_to!( linearizes_to!(
ireduce_with_type_ascription, ireduce_with_type_ascription,
"(=> (ireduce{i32} $x) 0)", "(=> (ireduce{i32} $x) 0)",
|p: &mut dyn FnMut(&[u8]) -> PathId, i: &mut dyn FnMut(u64) -> IntegerId| { |p, i| vec![
linear::Optimization { linear::Increment {
increments: vec![ operation: Opcode { path: p(&[0]) },
linear::Increment { expected: Ok(NonZeroU32::new(Operator::Ireduce as _).unwrap()),
operation: Opcode { path: p(&[0]) }, actions: vec![MakeIntegerConst {
expected: Ok(NonZeroU32::new(Operator::Ireduce as _).unwrap()), value: i(0),
actions: vec![MakeIntegerConst { bit_width: BitWidth::ThirtyTwo,
value: i(0), }],
bit_width: BitWidth::ThirtyTwo, },
}], linear::Increment {
}, operation: linear::MatchOp::BitWidth { path: p(&[0]) },
linear::Increment { expected: Ok(NonZeroU32::new(32).unwrap()),
operation: linear::MatchOp::BitWidth { path: p(&[0]) }, actions: vec![],
expected: Ok(NonZeroU32::new(32).unwrap()), },
actions: vec![], linear::Increment {
}, operation: Nop,
linear::Increment { expected: Err(Else),
operation: Nop, actions: vec![],
expected: Err(Else), },
actions: vec![], ]
},
],
}
}
); );
} }