Skip to content

Commit

Permalink
chapter17: idealize phi and cproj
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertObkircher committed Feb 7, 2025
1 parent a1cc403 commit 887b308
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/sea_of_nodes/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ impl Phi {
for i in 1..self.inputs(sea).len() {
// If the region's control input is live, add this as a dependency
// to the control because we can be peeped should it become dead.
let region_in_i = region.inputs(sea)[i].unwrap().add_dep(*self, sea);
let region_in_i = region.inputs(sea)[i].unwrap().add_dep(self, sea);
if region_in_i.ty(sea) != Some(sea.types.xctrl) && self.inputs(sea)[i] != Some(*self) {
if live.is_none() || live == self.inputs(sea)[i] {
live = self.inputs(sea)[i];
Expand Down
68 changes: 32 additions & 36 deletions src/sea_of_nodes/nodes/idealize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::sea_of_nodes::nodes::node::{
Sub, TypedNode,
};
use crate::sea_of_nodes::nodes::{BoolOp, Node, Nodes, Op};
use crate::sea_of_nodes::types::Type;
use crate::sea_of_nodes::types::Ty;

impl Node {
/// do not peephole directly returned values!
Expand Down Expand Up @@ -107,7 +107,7 @@ impl Add {
// transformation.
if lhs.inputs(sea)[2]
.unwrap()
.add_dep(*self, sea)
.add_dep(self, sea)
.ty(sea)
.unwrap()
.is_constant(sea.tys)
Expand Down Expand Up @@ -228,13 +228,10 @@ impl Bool {

impl Phi {
fn idealize_phi(self, sea: &mut Nodes) -> Option<Node> {
let region = self.inputs(sea)[0];
if !sea.instanceof_region(region) {
let Some(r) = self.region(sea).to_region(sea) else {
return self.inputs(sea)[1]; // Input has collapse to e.g. starting control.
}
if Nodes::in_progress(&sea.ops, &sea.inputs, *self)
|| region.unwrap().inputs(sea).is_empty()
{
};
if Nodes::in_progress(&sea.ops, &sea.inputs, **r) || r.inputs(sea).len() <= 1 {
return None; // Input is in-progress
}

Expand All @@ -248,11 +245,8 @@ impl Phi {
// Phi(op(A,B),op(Q,R),op(X,Y)) becomes
// op(Phi(A,Q,X), Phi(B,R,Y)).
let op = self.inputs(sea)[1].expect("not same_inputs");
if op.inputs(sea).len() == 3
&& op.inputs(sea)[0].is_none()
&& !op.is_cfg(sea)
&& self.same_op(sea)
{
if op.inputs(sea).len() == 3 && op.inputs(sea)[0].is_none() && self.same_op(sea) {
debug_assert!(!op.is_cfg(sea));
let n_in = &self.inputs(sea);

let mut lhss = vec![None; n_in.len()];
Expand All @@ -277,13 +271,13 @@ impl Phi {
// If merging Phi(N, cast(N)) - we are losing the cast JOIN effects, so just remove.
if self.inputs(sea).len() == 3 {
if let Some(cast) = self.inputs(sea)[1].unwrap().to_cast(sea) {
let in_1 = cast.inputs(sea)[1].unwrap().add_dep(*self, sea);
let in_1 = cast.inputs(sea)[1].unwrap().add_dep(self, sea);
if Some(in_1) == self.inputs(sea)[2] {
return self.inputs(sea)[2];
}
}
if let Some(cast) = self.inputs(sea)[2].unwrap().to_cast(sea) {
let in_1 = cast.inputs(sea)[1].unwrap().add_dep(*self, sea);
let in_1 = cast.inputs(sea)[1].unwrap().add_dep(self, sea);
if Some(in_1) == self.inputs(sea)[1] {
return self.inputs(sea)[1];
}
Expand All @@ -307,13 +301,11 @@ impl Phi {

if nullx != 0 {
let val = self.inputs(sea)[3 - nullx].unwrap();
let region = self.region(sea);
let idom = region.idom(sea).unwrap();
if let Some(iff) = idom.to_if(sea) {
if iff.pred(sea).unwrap().add_dep(*self, sea) == val {
if let Some(iff) = r.idom(sea).unwrap().add_dep(self, sea).to_if(sea) {
if iff.pred(sea).unwrap().add_dep(self, sea) == val {
// Must walk the idom on the null side to make sure we hit False.
let mut idom = region.cfg(nullx, sea).unwrap();
while idom.inputs(sea)[0] != Some(**iff) {
let mut idom = r.cfg(nullx, sea).unwrap();
while !idom.inputs(sea).is_empty() && idom.inputs(sea)[0] != Some(**iff) {
idom = idom.idom(sea).unwrap();
}
if idom.to_cproj(sea).is_some_and(|p| sea[p].index == 1) {
Expand Down Expand Up @@ -352,30 +344,34 @@ impl Return {

impl CProj {
fn idealize_cproj(self, sea: &mut Nodes) -> Option<Node> {
let index = sea[self].index;
if let Some(iff) = self.inputs(sea)[0]?.to_if(sea) {
if let Some(Type::Tuple(ts)) = iff.ty(sea).as_deref() {
if ts[1 - index] == sea.types.xctrl {
return iff.inputs(sea)[0]; // We become our input control
}
}
let ctrl = self.cfg(0, sea).unwrap();
let idx = sea[self].index;

// Flip a negating if-test, to remove the not
if let Some(not) = iff.inputs(sea)[1]?.add_dep(**self, sea).to_not(sea) {
if let Some(tt) = ctrl.ty(sea).and_then(Ty::to_tuple) {
if tt.data()[idx] == sea.types.xctrl {
return Some(**sea.xctrl); // We are dead
}
// Only true for IfNodes
if ctrl.is_if(sea) && tt.data()[1 - idx] == sea.types.xctrl {
return ctrl.inputs(sea)[0]; // We become our input control
}
}
// Flip a negating if-test, to remove the not
if let Some(iff) = ctrl.to_if(sea) {
if let Some(not) = iff.pred(sea).unwrap().add_dep(self, sea).to_not(sea) {
return Some(**CProj::new(
If::new(
iff.inputs(sea)[0].unwrap(),
Some(not.inputs(sea)[1].unwrap()),
sea,
)
.peephole(sea),
1 - index,
if index == 0 { "False" } else { "True" },
1 - idx,
if idx == 0 { "False" } else { "True" },
sea,
));
}
}

None
}
}
Expand Down Expand Up @@ -464,9 +460,9 @@ impl If {
let mut prior = *self;
let mut dom = self.idom(sea);
while let Some(d) = dom {
d.add_dep(**self, sea);
d.add_dep(self, sea);
if let Some(d) = d.to_if(sea) {
if d.pred(sea).unwrap().add_dep(**self, sea) == pred {
if d.pred(sea).unwrap().add_dep(self, sea) == pred {
if let Op::CProj(p) = &sea[prior] {
let value = if p.index == 0 {
sea.types.int_one
Expand Down Expand Up @@ -557,7 +553,7 @@ impl Load {
/// Profitable if we find a matching Store on this Phi arm.
fn profit(self, phi_node: Phi, idx: usize, sea: &mut Nodes) -> bool {
phi_node.inputs(sea)[idx].is_some_and(|px| {
px.add_dep(*self, sea)
px.add_dep(self, sea)
.to_store(sea)
.is_some_and(|px| self.ptr(sea) == px.ptr(sea))
})
Expand Down
3 changes: 2 additions & 1 deletion src/sea_of_nodes/nodes/iter_peeps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ impl Node {
/// Add a node to the list of dependencies. Only add it if its not an input
/// or output of this node, that is, it is at least one step away. The node
/// being added must benefit from this node being peepholed.
pub fn add_dep(self, dep: Node, sea: &mut Nodes) -> Node {
pub fn add_dep(self, dep: impl Into<Node>, sea: &mut Nodes) -> Node {
let dep = dep.into();
// Running peepholes during the big assert cannot have side effects
// like adding dependencies.
if sea.iter_peeps.mid_assert {
Expand Down

0 comments on commit 887b308

Please sign in to comment.