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) {
|
||||
return;
|
||||
}
|
||||
|
||||
for usage in self[node].outputs.clone() {
|
||||
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() {
|
||||
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 {
|
||||
min = self.find_antideps(node, min);
|
||||
min = self.find_antideps(node, min, antideps);
|
||||
}
|
||||
|
||||
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() {
|
||||
min = self.idom(min);
|
||||
}
|
||||
|
||||
self.check_dominance(node, min, true);
|
||||
self.assert_dominance(node, min, true);
|
||||
|
||||
let prev = self[node].inputs[0];
|
||||
debug_assert!(self.idepth(min) >= self.idepth(prev));
|
||||
|
@ -368,14 +368,14 @@ impl Nodes {
|
|||
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);
|
||||
|
||||
let (aclass, _) = self.aclass_index(self[load].inputs[1]);
|
||||
|
||||
let mut cursor = min;
|
||||
while cursor != self[load].inputs[0] {
|
||||
self[cursor].antidep = load;
|
||||
antideps[cursor as usize] = load;
|
||||
if self[cursor].clobbers.get(aclass as _) {
|
||||
min = self[cursor].inputs[0];
|
||||
break;
|
||||
|
@ -391,8 +391,8 @@ impl Nodes {
|
|||
match self[out].kind {
|
||||
Kind::Stre => {
|
||||
let mut cursor = self[out].inputs[0];
|
||||
while cursor != self[out].antidep {
|
||||
if self[cursor].antidep == load {
|
||||
while cursor != antideps[out as usize] {
|
||||
if antideps[cursor as usize] == load {
|
||||
min = self.common_dom(min, cursor);
|
||||
if min == cursor {
|
||||
self.bind(load, out);
|
||||
|
@ -409,8 +409,8 @@ impl Nodes {
|
|||
.position(|&n| n == self[load].inputs[2])
|
||||
.unwrap();
|
||||
let mut cursor = self[self[out].inputs[0]].inputs[n];
|
||||
while cursor != self[out].antidep {
|
||||
if self[cursor].antidep == load {
|
||||
while cursor != antideps[out as usize] {
|
||||
if antideps[cursor as usize] == load {
|
||||
min = self.common_dom(min, cursor);
|
||||
break;
|
||||
}
|
||||
|
@ -587,7 +587,10 @@ impl Nodes {
|
|||
visited.clear(self.values.len());
|
||||
self.push_up(rpo, visited);
|
||||
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) {
|
||||
|
@ -874,6 +877,8 @@ impl Nodes {
|
|||
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));
|
||||
}
|
||||
|
||||
self.add_trigger(b, target);
|
||||
}
|
||||
|
||||
if op == T::Add
|
||||
|
@ -936,7 +941,7 @@ impl Nodes {
|
|||
}
|
||||
|
||||
if self[target].ty == ty::Id::VOID {
|
||||
match self.try_opt_cond(target) {
|
||||
match self.try_match_cond(target) {
|
||||
CondOptRes::Unknown => {}
|
||||
CondOptRes::Known { value, .. } => {
|
||||
let ty = if value {
|
||||
|
@ -1009,7 +1014,7 @@ impl Nodes {
|
|||
if let Some(&load) =
|
||||
self[n].outputs.iter().find(|&&n| self[n].kind == Kind::Load)
|
||||
{
|
||||
self[load].peep_triggers.push(target);
|
||||
self.add_trigger(load, target);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1045,7 @@ impl Nodes {
|
|||
if let Some(&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;
|
||||
}
|
||||
|
||||
|
@ -1054,6 +1059,7 @@ impl Nodes {
|
|||
}
|
||||
K::Phi => {
|
||||
let &[ctrl, lhs, rhs] = self[target].inputs.as_slice() else { unreachable!() };
|
||||
let ty = self[target].ty;
|
||||
|
||||
if rhs == target || lhs == rhs {
|
||||
return Some(lhs);
|
||||
|
@ -1072,15 +1078,21 @@ impl Nodes {
|
|||
[ctrl, self[lhs].inputs[1], self[rhs].inputs[1]],
|
||||
tys,
|
||||
);
|
||||
let mut vc = Vc::from([VOID, pick_value, self[lhs].inputs[2]]);
|
||||
for &rest in &self[lhs].inputs[3..] {
|
||||
vc.push(rest);
|
||||
}
|
||||
for &rest in &self[rhs].inputs[4..] {
|
||||
vc.push(rest);
|
||||
}
|
||||
let mut vc = self[lhs].inputs.clone();
|
||||
vc[1] = pick_value;
|
||||
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 => {
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -1240,7 +1252,7 @@ impl Nodes {
|
|||
if let Some(&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
|
||||
&& self[value].kind != Kind::Load
|
||||
&& self[store].kind == Kind::Stre
|
||||
|
@ -1313,7 +1325,7 @@ impl Nodes {
|
|||
cursor = self[cursor].inputs[3];
|
||||
} else {
|
||||
let reg = self.aclass_index(self[cursor].inputs[2]).1;
|
||||
self[reg].peep_triggers.push(target);
|
||||
self.add_trigger(reg, target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1357,7 +1369,7 @@ impl Nodes {
|
|||
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!() };
|
||||
if let Kind::CInt { value } = self[cond].kind {
|
||||
return CondOptRes::Known { value: value != 0, pin: None };
|
||||
|
@ -1739,7 +1751,7 @@ impl Nodes {
|
|||
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) {
|
||||
return;
|
||||
}
|
||||
|
@ -1804,6 +1816,12 @@ impl Nodes {
|
|||
self[nid].kind == Kind::CInt { value: 0 }
|
||||
&& 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 {
|
||||
|
@ -1961,12 +1979,11 @@ pub struct Node {
|
|||
peep_triggers: Vc,
|
||||
clobbers: BitSet,
|
||||
ty: ty::Id,
|
||||
pos: Pos,
|
||||
depth: Cell<IDomDepth>,
|
||||
lock_rc: LockRc,
|
||||
loop_depth: Cell<LoopDepth>,
|
||||
aclass: AClassId,
|
||||
antidep: Nid,
|
||||
pos: Pos,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
|
@ -4370,7 +4387,7 @@ impl<'a> Codegen<'a> {
|
|||
for (id, node) in self.ci.nodes.iter() {
|
||||
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
|
||||
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
|
||||
let fromc = Some(&from);
|
||||
let mut buf = Vec::with_capacity(outputs.len());
|
||||
|
|
|
@ -15,7 +15,7 @@ use {
|
|||
};
|
||||
|
||||
impl HbvmBackend {
|
||||
pub fn emit_body_code_my(
|
||||
pub(super) fn emit_body_code_my(
|
||||
&mut self,
|
||||
nodes: &mut Nodes,
|
||||
sig: Sig,
|
||||
|
@ -317,7 +317,7 @@ impl HbvmBackend {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Function<'a> {
|
||||
struct Function<'a> {
|
||||
sig: Sig,
|
||||
tail: bool,
|
||||
backrefs: Vec<u16>,
|
||||
|
@ -560,18 +560,18 @@ impl<'a> Function<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Env<'a> {
|
||||
struct Env<'a> {
|
||||
ctx: &'a Function<'a>,
|
||||
func: &'a Func,
|
||||
res: &'a mut Res,
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
fn run(&mut self) {
|
||||
self.res.bundles.clear();
|
||||
self.res.node_to_reg.clear();
|
||||
self.res.node_to_reg.resize(self.ctx.vreg_count(), 0);
|
||||
|
@ -722,16 +722,16 @@ impl<'a> Env<'a> {
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Res {
|
||||
pub bundles: Vec<Bundle>,
|
||||
pub node_to_reg: Vec<Reg>,
|
||||
pub(super) struct Res {
|
||||
bundles: Vec<Bundle>,
|
||||
node_to_reg: Vec<Reg>,
|
||||
use_buf: Vec<(Nid, Nid)>,
|
||||
phi_input_buf: Vec<Nid>,
|
||||
dfs_buf: Vec<Nid>,
|
||||
dfs_seem: BitSet,
|
||||
}
|
||||
|
||||
pub struct Bundle {
|
||||
struct Bundle {
|
||||
taken: Vec<bool>,
|
||||
}
|
||||
|
||||
|
@ -759,12 +759,12 @@ impl Bundle {
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Func {
|
||||
pub blocks: Vec<Block>,
|
||||
pub instrs: Vec<Nid>,
|
||||
struct Func {
|
||||
blocks: Vec<Block>,
|
||||
instrs: Vec<Nid>,
|
||||
}
|
||||
|
||||
pub struct Block {
|
||||
pub range: Range<usize>,
|
||||
pub entry: Nid,
|
||||
struct Block {
|
||||
range: Range<usize>,
|
||||
entry: Nid,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue