adding a simple peephole for phis
This commit is contained in:
parent
bb625a9e19
commit
83146cfd61
|
@ -307,20 +307,20 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_down(&mut self, node: Nid, visited: &mut BitSet) {
|
fn push_down(&mut self, node: Nid, visited: &mut BitSet, antideps: &mut [Nid]) {
|
||||||
if !visited.set(node) {
|
if !visited.set(node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for usage in self[node].outputs.clone() {
|
for usage in self[node].outputs.clone() {
|
||||||
if self.is_forward_edge(usage, node) && self[node].kind == Kind::Stre {
|
if self.is_forward_edge(usage, node) && self[node].kind == Kind::Stre {
|
||||||
self.push_down(usage, visited);
|
self.push_down(usage, visited, antideps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for usage in self[node].outputs.clone() {
|
for usage in self[node].outputs.clone() {
|
||||||
if self.is_forward_edge(usage, node) {
|
if self.is_forward_edge(usage, node) {
|
||||||
self.push_down(usage, visited);
|
self.push_down(usage, visited, antideps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,18 +347,18 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self[node].kind == Kind::Load {
|
if self[node].kind == Kind::Load {
|
||||||
min = self.find_antideps(node, min);
|
min = self.find_antideps(node, min, antideps);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self[node].kind == Kind::Stre {
|
if self[node].kind == Kind::Stre {
|
||||||
self[node].antidep = self[node].inputs[0];
|
antideps[node as usize] = self[node].inputs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if self[min].kind.ends_basic_block() {
|
if self[min].kind.ends_basic_block() {
|
||||||
min = self.idom(min);
|
min = self.idom(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.check_dominance(node, min, true);
|
self.assert_dominance(node, min, true);
|
||||||
|
|
||||||
let prev = self[node].inputs[0];
|
let prev = self[node].inputs[0];
|
||||||
debug_assert!(self.idepth(min) >= self.idepth(prev));
|
debug_assert!(self.idepth(min) >= self.idepth(prev));
|
||||||
|
@ -368,14 +368,14 @@ impl Nodes {
|
||||||
self[min].outputs.push(node);
|
self[min].outputs.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_antideps(&mut self, load: Nid, mut min: Nid) -> Nid {
|
fn find_antideps(&mut self, load: Nid, mut min: Nid, antideps: &mut [Nid]) -> Nid {
|
||||||
debug_assert!(self[load].kind == Kind::Load);
|
debug_assert!(self[load].kind == Kind::Load);
|
||||||
|
|
||||||
let (aclass, _) = self.aclass_index(self[load].inputs[1]);
|
let (aclass, _) = self.aclass_index(self[load].inputs[1]);
|
||||||
|
|
||||||
let mut cursor = min;
|
let mut cursor = min;
|
||||||
while cursor != self[load].inputs[0] {
|
while cursor != self[load].inputs[0] {
|
||||||
self[cursor].antidep = load;
|
antideps[cursor as usize] = load;
|
||||||
if self[cursor].clobbers.get(aclass as _) {
|
if self[cursor].clobbers.get(aclass as _) {
|
||||||
min = self[cursor].inputs[0];
|
min = self[cursor].inputs[0];
|
||||||
break;
|
break;
|
||||||
|
@ -391,8 +391,8 @@ impl Nodes {
|
||||||
match self[out].kind {
|
match self[out].kind {
|
||||||
Kind::Stre => {
|
Kind::Stre => {
|
||||||
let mut cursor = self[out].inputs[0];
|
let mut cursor = self[out].inputs[0];
|
||||||
while cursor != self[out].antidep {
|
while cursor != antideps[out as usize] {
|
||||||
if self[cursor].antidep == load {
|
if antideps[cursor as usize] == load {
|
||||||
min = self.common_dom(min, cursor);
|
min = self.common_dom(min, cursor);
|
||||||
if min == cursor {
|
if min == cursor {
|
||||||
self.bind(load, out);
|
self.bind(load, out);
|
||||||
|
@ -409,8 +409,8 @@ impl Nodes {
|
||||||
.position(|&n| n == self[load].inputs[2])
|
.position(|&n| n == self[load].inputs[2])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut cursor = self[self[out].inputs[0]].inputs[n];
|
let mut cursor = self[self[out].inputs[0]].inputs[n];
|
||||||
while cursor != self[out].antidep {
|
while cursor != antideps[out as usize] {
|
||||||
if self[cursor].antidep == load {
|
if antideps[cursor as usize] == load {
|
||||||
min = self.common_dom(min, cursor);
|
min = self.common_dom(min, cursor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -587,7 +587,10 @@ impl Nodes {
|
||||||
visited.clear(self.values.len());
|
visited.clear(self.values.len());
|
||||||
self.push_up(rpo, visited);
|
self.push_up(rpo, visited);
|
||||||
visited.clear(self.values.len());
|
visited.clear(self.values.len());
|
||||||
self.push_down(VOID, visited);
|
debug_assert!(rpo.is_empty());
|
||||||
|
rpo.resize(self.values.len(), VOID);
|
||||||
|
self.push_down(VOID, visited, rpo);
|
||||||
|
rpo.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
|
@ -874,6 +877,8 @@ impl Nodes {
|
||||||
let new_lhs = self.new_node(ty, K::BinOp { op }, [ctrl, a, rhs], tys);
|
let new_lhs = self.new_node(ty, K::BinOp { op }, [ctrl, a, rhs], tys);
|
||||||
return Some(self.new_node(ty, K::BinOp { op }, [ctrl, new_lhs, b], tys));
|
return Some(self.new_node(ty, K::BinOp { op }, [ctrl, new_lhs, b], tys));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.add_trigger(b, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if op == T::Add
|
if op == T::Add
|
||||||
|
@ -936,7 +941,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self[target].ty == ty::Id::VOID {
|
if self[target].ty == ty::Id::VOID {
|
||||||
match self.try_opt_cond(target) {
|
match self.try_match_cond(target) {
|
||||||
CondOptRes::Unknown => {}
|
CondOptRes::Unknown => {}
|
||||||
CondOptRes::Known { value, .. } => {
|
CondOptRes::Known { value, .. } => {
|
||||||
let ty = if value {
|
let ty = if value {
|
||||||
|
@ -1009,7 +1014,7 @@ impl Nodes {
|
||||||
if let Some(&load) =
|
if let Some(&load) =
|
||||||
self[n].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
self[n].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
||||||
{
|
{
|
||||||
self[load].peep_triggers.push(target);
|
self.add_trigger(load, target);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1040,7 +1045,7 @@ impl Nodes {
|
||||||
if let Some(&load) =
|
if let Some(&load) =
|
||||||
self[cursor].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
self[cursor].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
||||||
{
|
{
|
||||||
self[load].peep_triggers.push(target);
|
self.add_trigger(load, target);
|
||||||
continue 'a;
|
continue 'a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,6 +1059,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
K::Phi => {
|
K::Phi => {
|
||||||
let &[ctrl, lhs, rhs] = self[target].inputs.as_slice() else { unreachable!() };
|
let &[ctrl, lhs, rhs] = self[target].inputs.as_slice() else { unreachable!() };
|
||||||
|
let ty = self[target].ty;
|
||||||
|
|
||||||
if rhs == target || lhs == rhs {
|
if rhs == target || lhs == rhs {
|
||||||
return Some(lhs);
|
return Some(lhs);
|
||||||
|
@ -1072,15 +1078,21 @@ impl Nodes {
|
||||||
[ctrl, self[lhs].inputs[1], self[rhs].inputs[1]],
|
[ctrl, self[lhs].inputs[1], self[rhs].inputs[1]],
|
||||||
tys,
|
tys,
|
||||||
);
|
);
|
||||||
let mut vc = Vc::from([VOID, pick_value, self[lhs].inputs[2]]);
|
let mut vc = self[lhs].inputs.clone();
|
||||||
for &rest in &self[lhs].inputs[3..] {
|
vc[1] = pick_value;
|
||||||
vc.push(rest);
|
|
||||||
}
|
|
||||||
for &rest in &self[rhs].inputs[4..] {
|
|
||||||
vc.push(rest);
|
|
||||||
}
|
|
||||||
return Some(self.new_node(self[lhs].ty, Kind::Stre, vc, tys));
|
return Some(self.new_node(self[lhs].ty, Kind::Stre, vc, tys));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Kind::BinOp { op } = self[lhs].kind
|
||||||
|
&& self[rhs].kind == (Kind::BinOp { op })
|
||||||
|
{
|
||||||
|
debug_assert!(ty != ty::Id::VOID);
|
||||||
|
let inps = [ctrl, self[lhs].inputs[1], self[rhs].inputs[1]];
|
||||||
|
let nlhs = self.new_node(ty, Kind::Phi, inps, tys);
|
||||||
|
let inps = [ctrl, self[lhs].inputs[2], self[rhs].inputs[2]];
|
||||||
|
let nrhs = self.new_node(ty, Kind::Phi, inps, tys);
|
||||||
|
return Some(self.new_node(ty, Kind::BinOp { op }, [VOID, nlhs, nrhs], tys));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
K::Stck => {
|
K::Stck => {
|
||||||
if let &[mut a, mut b] = self[target].outputs.as_slice() {
|
if let &[mut a, mut b] = self[target].outputs.as_slice() {
|
||||||
|
@ -1136,7 +1148,7 @@ impl Nodes {
|
||||||
|| self[value].outputs.iter().any(|&n| self[n].kind != Kind::Stre)
|
|| self[value].outputs.iter().any(|&n| self[n].kind != Kind::Stre)
|
||||||
{
|
{
|
||||||
for &ele in self[value].outputs.clone().iter().filter(|&&n| n != target) {
|
for &ele in self[value].outputs.clone().iter().filter(|&&n| n != target) {
|
||||||
self[ele].peep_triggers.push(target);
|
self.add_trigger(ele, target);
|
||||||
}
|
}
|
||||||
break 'eliminate;
|
break 'eliminate;
|
||||||
}
|
}
|
||||||
|
@ -1240,7 +1252,7 @@ impl Nodes {
|
||||||
if let Some(&load) =
|
if let Some(&load) =
|
||||||
self[target].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
self[target].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
||||||
{
|
{
|
||||||
self[load].peep_triggers.push(target);
|
self.add_trigger(load, target);
|
||||||
} else if value != VOID
|
} else if value != VOID
|
||||||
&& self[value].kind != Kind::Load
|
&& self[value].kind != Kind::Load
|
||||||
&& self[store].kind == Kind::Stre
|
&& self[store].kind == Kind::Stre
|
||||||
|
@ -1313,7 +1325,7 @@ impl Nodes {
|
||||||
cursor = self[cursor].inputs[3];
|
cursor = self[cursor].inputs[3];
|
||||||
} else {
|
} else {
|
||||||
let reg = self.aclass_index(self[cursor].inputs[2]).1;
|
let reg = self.aclass_index(self[cursor].inputs[2]).1;
|
||||||
self[reg].peep_triggers.push(target);
|
self.add_trigger(reg, target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1357,7 +1369,7 @@ impl Nodes {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_opt_cond(&self, target: Nid) -> CondOptRes {
|
fn try_match_cond(&self, target: Nid) -> CondOptRes {
|
||||||
let &[ctrl, cond, ..] = self[target].inputs.as_slice() else { unreachable!() };
|
let &[ctrl, cond, ..] = self[target].inputs.as_slice() else { unreachable!() };
|
||||||
if let Kind::CInt { value } = self[cond].kind {
|
if let Kind::CInt { value } = self[cond].kind {
|
||||||
return CondOptRes::Known { value: value != 0, pin: None };
|
return CondOptRes::Known { value: value != 0, pin: None };
|
||||||
|
@ -1739,7 +1751,7 @@ impl Nodes {
|
||||||
aclass.last_store.set(lvar.last_store.get(), self);
|
aclass.last_store.set(lvar.last_store.get(), self);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) {
|
fn assert_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) {
|
||||||
if !cfg!(debug_assertions) {
|
if !cfg!(debug_assertions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1804,6 +1816,12 @@ impl Nodes {
|
||||||
self[nid].kind == Kind::CInt { value: 0 }
|
self[nid].kind == Kind::CInt { value: 0 }
|
||||||
&& self[nid].outputs.iter().all(|&n| self[n].kind != Kind::Phi)
|
&& self[nid].outputs.iter().all(|&n| self[n].kind != Kind::Phi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_trigger(&mut self, blocker: Nid, target: Nid) {
|
||||||
|
if !self[blocker].peep_triggers.contains(&target) {
|
||||||
|
self[blocker].peep_triggers.push(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CondOptRes {
|
enum CondOptRes {
|
||||||
|
@ -1961,12 +1979,11 @@ pub struct Node {
|
||||||
peep_triggers: Vc,
|
peep_triggers: Vc,
|
||||||
clobbers: BitSet,
|
clobbers: BitSet,
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
|
pos: Pos,
|
||||||
depth: Cell<IDomDepth>,
|
depth: Cell<IDomDepth>,
|
||||||
lock_rc: LockRc,
|
lock_rc: LockRc,
|
||||||
loop_depth: Cell<LoopDepth>,
|
loop_depth: Cell<LoopDepth>,
|
||||||
aclass: AClassId,
|
aclass: AClassId,
|
||||||
antidep: Nid,
|
|
||||||
pos: Pos,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
@ -4370,7 +4387,7 @@ impl<'a> Codegen<'a> {
|
||||||
for (id, node) in self.ci.nodes.iter() {
|
for (id, node) in self.ci.nodes.iter() {
|
||||||
let Kind::Assert { kind, pos } = node.kind else { continue };
|
let Kind::Assert { kind, pos } = node.kind else { continue };
|
||||||
|
|
||||||
let res = self.ci.nodes.try_opt_cond(id);
|
let res = self.ci.nodes.try_match_cond(id);
|
||||||
|
|
||||||
// TODO: highlight the pin position
|
// TODO: highlight the pin position
|
||||||
let msg = match (kind, res) {
|
let msg = match (kind, res) {
|
||||||
|
|
|
@ -361,7 +361,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) {
|
fn reschedule_block(&self, from: Nid, outputs: &mut Vc) {
|
||||||
// NOTE: this code is horible
|
// NOTE: this code is horible
|
||||||
let fromc = Some(&from);
|
let fromc = Some(&from);
|
||||||
let mut buf = Vec::with_capacity(outputs.len());
|
let mut buf = Vec::with_capacity(outputs.len());
|
||||||
|
|
|
@ -15,7 +15,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
impl HbvmBackend {
|
impl HbvmBackend {
|
||||||
pub fn emit_body_code_my(
|
pub(super) fn emit_body_code_my(
|
||||||
&mut self,
|
&mut self,
|
||||||
nodes: &mut Nodes,
|
nodes: &mut Nodes,
|
||||||
sig: Sig,
|
sig: Sig,
|
||||||
|
@ -317,7 +317,7 @@ impl HbvmBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Function<'a> {
|
struct Function<'a> {
|
||||||
sig: Sig,
|
sig: Sig,
|
||||||
tail: bool,
|
tail: bool,
|
||||||
backrefs: Vec<u16>,
|
backrefs: Vec<u16>,
|
||||||
|
@ -560,18 +560,18 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Env<'a> {
|
struct Env<'a> {
|
||||||
ctx: &'a Function<'a>,
|
ctx: &'a Function<'a>,
|
||||||
func: &'a Func,
|
func: &'a Func,
|
||||||
res: &'a mut Res,
|
res: &'a mut Res,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Env<'a> {
|
impl<'a> Env<'a> {
|
||||||
pub fn new(ctx: &'a Function<'a>, func: &'a Func, res: &'a mut Res) -> Self {
|
fn new(ctx: &'a Function<'a>, func: &'a Func, res: &'a mut Res) -> Self {
|
||||||
Self { ctx, func, res }
|
Self { ctx, func, res }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
self.res.bundles.clear();
|
self.res.bundles.clear();
|
||||||
self.res.node_to_reg.clear();
|
self.res.node_to_reg.clear();
|
||||||
self.res.node_to_reg.resize(self.ctx.vreg_count(), 0);
|
self.res.node_to_reg.resize(self.ctx.vreg_count(), 0);
|
||||||
|
@ -722,16 +722,16 @@ impl<'a> Env<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Res {
|
pub(super) struct Res {
|
||||||
pub bundles: Vec<Bundle>,
|
bundles: Vec<Bundle>,
|
||||||
pub node_to_reg: Vec<Reg>,
|
node_to_reg: Vec<Reg>,
|
||||||
use_buf: Vec<(Nid, Nid)>,
|
use_buf: Vec<(Nid, Nid)>,
|
||||||
phi_input_buf: Vec<Nid>,
|
phi_input_buf: Vec<Nid>,
|
||||||
dfs_buf: Vec<Nid>,
|
dfs_buf: Vec<Nid>,
|
||||||
dfs_seem: BitSet,
|
dfs_seem: BitSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bundle {
|
struct Bundle {
|
||||||
taken: Vec<bool>,
|
taken: Vec<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -759,12 +759,12 @@ impl Bundle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Func {
|
struct Func {
|
||||||
pub blocks: Vec<Block>,
|
blocks: Vec<Block>,
|
||||||
pub instrs: Vec<Nid>,
|
instrs: Vec<Nid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Block {
|
struct Block {
|
||||||
pub range: Range<usize>,
|
range: Range<usize>,
|
||||||
pub entry: Nid,
|
entry: Nid,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue