saving this to make sure
This commit is contained in:
parent
37db783699
commit
bbd7e12af4
290
lang/src/son.rs
290
lang/src/son.rs
|
@ -9,7 +9,7 @@ use {
|
||||||
idfl::{self},
|
idfl::{self},
|
||||||
CtorField, Expr, FileId, Pos,
|
CtorField, Expr, FileId, Pos,
|
||||||
},
|
},
|
||||||
task,
|
reg, task,
|
||||||
ty::{self, Arg, ArrayLen, Loc, Tuple},
|
ty::{self, Arg, ArrayLen, Loc, Tuple},
|
||||||
vc::{BitSet, Vc},
|
vc::{BitSet, Vc},
|
||||||
FTask, Func, Global, Ident, Offset, OffsetIter, Reloc, Sig, StringRef, SymKey, TypeParser,
|
FTask, Func, Global, Ident, Offset, OffsetIter, Reloc, Sig, StringRef, SymKey, TypeParser,
|
||||||
|
@ -375,7 +375,8 @@ impl Nodes {
|
||||||
to: &mut Scope,
|
to: &mut Scope,
|
||||||
from: &mut Scope,
|
from: &mut Scope,
|
||||||
) {
|
) {
|
||||||
for (i, (to_value, from_value)) in to.iter_mut().zip(from.iter_mut()).enumerate() {
|
for (i, (to_value, from_value)) in to.vars.iter_mut().zip(from.vars.iter_mut()).enumerate()
|
||||||
|
{
|
||||||
debug_assert_eq!(to_value.ty, from_value.ty);
|
debug_assert_eq!(to_value.ty, from_value.ty);
|
||||||
if to_value.value() != from_value.value() {
|
if to_value.value() != from_value.value() {
|
||||||
self.load_loop_var(i, from_value, loops);
|
self.load_loop_var(i, from_value, loops);
|
||||||
|
@ -387,8 +388,21 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
to.loads.drain(..).for_each(|l| _ = l.remove(self));
|
for (i, (to_class, from_class)) in
|
||||||
from.loads.drain(..).for_each(|l| _ = l.remove(self));
|
to.aclasses.iter_mut().zip(from.aclasses.iter_mut()).enumerate()
|
||||||
|
{
|
||||||
|
if to_class.last_store.get() != from_class.last_store.get() {
|
||||||
|
self.load_loop_aclass(i, from_class, loops);
|
||||||
|
self.load_loop_aclass(i, to_class, loops);
|
||||||
|
if to_class.last_store.get() != from_class.last_store.get() {
|
||||||
|
let inps = [ctrl.get(), from_class.last_store.get(), to_class.last_store.get()];
|
||||||
|
to_class
|
||||||
|
.last_store
|
||||||
|
.set_remove(self.new_node(ty::Id::VOID, Kind::Phi, inps), self);
|
||||||
|
to_class.loads.drain(..).for_each(|d| _ = d.remove(self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn graphviz_low(
|
fn graphviz_low(
|
||||||
|
@ -1122,29 +1136,16 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_loop_var(&mut self, index: usize, value: &mut Variable, loops: &mut [Loop]) {
|
fn load_loop_var(&mut self, index: usize, var: &mut Variable, loops: &mut [Loop]) {
|
||||||
self.load_loop_value(&mut |l| l.scope.iter_mut().nth(index).unwrap(), value, loops);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_loop_store(&mut self, value: &mut Variable, loops: &mut [Loop]) {
|
|
||||||
self.load_loop_value(&mut |l| &mut l.scope.store, value, loops);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_loop_value(
|
|
||||||
&mut self,
|
|
||||||
get_lvalue: &mut impl FnMut(&mut Loop) -> &mut Variable,
|
|
||||||
var: &mut Variable,
|
|
||||||
loops: &mut [Loop],
|
|
||||||
) {
|
|
||||||
if var.value() != VOID {
|
if var.value() != VOID {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let [loops @ .., loob] = loops else { unreachable!() };
|
let [loops @ .., loob] = loops else { unreachable!() };
|
||||||
let node = loob.node;
|
let node = loob.node;
|
||||||
let lvar = get_lvalue(loob);
|
let lvar = &mut loob.scope.vars[index];
|
||||||
|
|
||||||
self.load_loop_value(get_lvalue, lvar, loops);
|
self.load_loop_var(index, lvar, loops);
|
||||||
|
|
||||||
if !self[lvar.value()].is_lazy_phi(node) {
|
if !self[lvar.value()].is_lazy_phi(node) {
|
||||||
let inps = [node, lvar.value(), VOID];
|
let inps = [node, lvar.value(), VOID];
|
||||||
|
@ -1153,6 +1154,24 @@ impl Nodes {
|
||||||
var.set_value(lvar.value(), self);
|
var.set_value(lvar.value(), self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_loop_aclass(&mut self, index: usize, var: &mut AClass, loops: &mut [Loop]) {
|
||||||
|
if var.last_store.get() != VOID {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let [loops @ .., loob] = loops else { unreachable!() };
|
||||||
|
let node = loob.node;
|
||||||
|
let lvar = &mut loob.scope.aclasses[index];
|
||||||
|
|
||||||
|
self.load_loop_aclass(index, lvar, loops);
|
||||||
|
|
||||||
|
if !self[lvar.last_store.get()].is_lazy_phi(node) {
|
||||||
|
let inps = [node, lvar.last_store.get(), VOID];
|
||||||
|
lvar.last_store.set(self.new_node_nop(ty::Id::VOID, Kind::Phi, inps), self);
|
||||||
|
}
|
||||||
|
var.last_store.set(lvar.last_store.get(), self);
|
||||||
|
}
|
||||||
|
|
||||||
fn check_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) {
|
fn check_dominance(&mut self, nd: Nid, min: Nid, check_outputs: bool) {
|
||||||
if !cfg!(debug_assertions) {
|
if !cfg!(debug_assertions) {
|
||||||
return;
|
return;
|
||||||
|
@ -1223,6 +1242,7 @@ impl Nodes {
|
||||||
|
|
||||||
let mut saved = Vc::default();
|
let mut saved = Vc::default();
|
||||||
let mut cursor = last_store;
|
let mut cursor = last_store;
|
||||||
|
let mut first_store = last_store;
|
||||||
while cursor != MEM && self[cursor].kind == Kind::Stre {
|
while cursor != MEM && self[cursor].kind == Kind::Stre {
|
||||||
let mut contact_point = cursor;
|
let mut contact_point = cursor;
|
||||||
let mut region = self[cursor].inputs[2];
|
let mut region = self[cursor].inputs[2];
|
||||||
|
@ -1240,6 +1260,7 @@ impl Nodes {
|
||||||
};
|
};
|
||||||
unidentifed.remove(index);
|
unidentifed.remove(index);
|
||||||
saved.push(contact_point);
|
saved.push(contact_point);
|
||||||
|
first_store = cursor;
|
||||||
cursor = *self[cursor].inputs.get(3).unwrap_or(&MEM);
|
cursor = *self[cursor].inputs.get(3).unwrap_or(&MEM);
|
||||||
|
|
||||||
if unidentifed.is_empty() {
|
if unidentifed.is_empty() {
|
||||||
|
@ -1255,6 +1276,19 @@ impl Nodes {
|
||||||
{
|
{
|
||||||
self.modify_input(mcall, self[mcall].inputs.len() - 1, region);
|
self.modify_input(mcall, self[mcall].inputs.len() - 1, region);
|
||||||
} else {
|
} else {
|
||||||
|
debug_assert_matches!(
|
||||||
|
self[last_store].kind,
|
||||||
|
Kind::Stre | Kind::Mem,
|
||||||
|
"{:?}",
|
||||||
|
self[last_store]
|
||||||
|
);
|
||||||
|
debug_assert_matches!(
|
||||||
|
self[first_store].kind,
|
||||||
|
Kind::Stre | Kind::Mem,
|
||||||
|
"{:?}",
|
||||||
|
self[first_store]
|
||||||
|
);
|
||||||
|
|
||||||
if !unidentifed.is_empty() {
|
if !unidentifed.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1278,7 +1312,12 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.replace(dst, *self[dst].inputs.get(3).unwrap_or(&MEM));
|
let prev_store = self[dst].inputs[3];
|
||||||
|
if prev_store != MEM && first_store != MEM {
|
||||||
|
self.modify_input(first_store, 3, prev_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.replace(dst, last_store);
|
||||||
if self.values[stack as usize].is_ok() {
|
if self.values[stack as usize].is_ok() {
|
||||||
self.lock(stack);
|
self.lock(stack);
|
||||||
}
|
}
|
||||||
|
@ -1413,6 +1452,7 @@ pub struct Node {
|
||||||
depth: IDomDepth,
|
depth: IDomDepth,
|
||||||
lock_rc: LockRc,
|
lock_rc: LockRc,
|
||||||
loop_depth: LoopDepth,
|
loop_depth: LoopDepth,
|
||||||
|
aclass: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
@ -1583,30 +1623,47 @@ impl Variable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub struct AClass {
|
||||||
|
last_store: StrongRef,
|
||||||
|
loads: Vec<StrongRef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AClass {
|
||||||
|
fn dup(&self, nodes: &mut Nodes) -> Self {
|
||||||
|
Self {
|
||||||
|
last_store: self.last_store.dup(nodes),
|
||||||
|
loads: self.loads.iter().map(|v| v.dup(nodes)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(mut self, nodes: &mut Nodes) {
|
||||||
|
self.last_store.remove(nodes);
|
||||||
|
self.loads.drain(..).for_each(|n| _ = n.remove(nodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(nodes: &mut Nodes) -> Self {
|
||||||
|
Self { last_store: StrongRef::new(MEM, nodes), loads: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
vars: Vec<Variable>,
|
vars: Vec<Variable>,
|
||||||
loads: Vec<StrongRef>,
|
aclasses: Vec<AClass>,
|
||||||
store: Variable,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
fn iter_mut(&mut self) -> impl Iterator<Item = &mut Variable> {
|
|
||||||
core::iter::once(&mut self.store).chain(self.vars.iter_mut())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dup(&self, nodes: &mut Nodes) -> Self {
|
fn dup(&self, nodes: &mut Nodes) -> Self {
|
||||||
Self {
|
Self {
|
||||||
vars: self.vars.iter().map(|v| v.dup(nodes)).collect(),
|
vars: self.vars.iter().map(|v| v.dup(nodes)).collect(),
|
||||||
loads: self.loads.iter().map(|l| l.dup(nodes)).collect(),
|
aclasses: self.aclasses.iter().map(|v| v.dup(nodes)).collect(),
|
||||||
store: self.store.dup(nodes),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&mut self, nodes: &mut Nodes) {
|
fn clear(&mut self, nodes: &mut Nodes) {
|
||||||
self.vars.drain(..).for_each(|n| n.remove(nodes));
|
self.vars.drain(..).for_each(|n| n.remove(nodes));
|
||||||
self.loads.drain(..).for_each(|l| _ = l.remove(nodes));
|
self.aclasses.drain(..).for_each(|l| l.remove(nodes));
|
||||||
mem::take(&mut self.store).remove(nodes);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1661,8 +1718,7 @@ impl ItemCtx {
|
||||||
let loops = self.nodes.new_node(ty::Id::VOID, Kind::Loops, [VOID]);
|
let loops = self.nodes.new_node(ty::Id::VOID, Kind::Loops, [VOID]);
|
||||||
debug_assert_eq!(loops, LOOPS);
|
debug_assert_eq!(loops, LOOPS);
|
||||||
self.nodes.lock(loops);
|
self.nodes.lock(loops);
|
||||||
self.scope.store =
|
self.scope.aclasses.push(AClass::new(&mut self.nodes));
|
||||||
Variable::new(Ident::default(), ty::Id::VOID, false, MEM, &mut self.nodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(&mut self, stack: &mut Vec<Nid>) {
|
fn finalize(&mut self, stack: &mut Vec<Nid>) {
|
||||||
|
@ -1927,9 +1983,11 @@ impl<'a> Codegen<'a> {
|
||||||
);
|
);
|
||||||
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
|
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
|
||||||
|
|
||||||
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
|
let index = self.aclass_index(region);
|
||||||
let mut vc = Vc::from([VOID, value, region, self.ci.scope.store.value()]);
|
let aclass = &mut self.ci.scope.aclasses[index];
|
||||||
for load in self.ci.scope.loads.drain(..) {
|
self.ci.nodes.load_loop_aclass(index, aclass, &mut self.ci.loops);
|
||||||
|
let mut vc = Vc::from([VOID, value, region, aclass.last_store.get()]);
|
||||||
|
for load in aclass.loads.drain(..) {
|
||||||
if load.get() == value {
|
if load.get() == value {
|
||||||
load.soft_remove(&mut self.ci.nodes);
|
load.soft_remove(&mut self.ci.nodes);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1939,9 +1997,9 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let store = self.ci.nodes.new_node_nop(ty, Kind::Stre, vc);
|
let store = self.ci.nodes.new_node_nop(ty, Kind::Stre, vc);
|
||||||
self.ci.scope.store.set_value(store, &mut self.ci.nodes);
|
aclass.last_store.set(store, &mut self.ci.nodes);
|
||||||
let opted = self.ci.nodes.late_peephole(store).unwrap_or(store);
|
let opted = self.ci.nodes.late_peephole(store).unwrap_or(store);
|
||||||
self.ci.scope.store.set_value_remove(opted, &mut self.ci.nodes);
|
aclass.last_store.set_remove(opted, &mut self.ci.nodes);
|
||||||
opted
|
opted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1959,13 +2017,26 @@ impl<'a> Codegen<'a> {
|
||||||
self.ty_display(self.ci.nodes[region].ty)
|
self.ty_display(self.ci.nodes[region].ty)
|
||||||
);
|
);
|
||||||
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
|
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
|
||||||
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
|
let index = self.aclass_index(region);
|
||||||
let vc = [VOID, region, self.ci.scope.store.value()];
|
let aclass = &mut self.ci.scope.aclasses[index];
|
||||||
|
self.ci.nodes.load_loop_aclass(index, aclass, &mut self.ci.loops);
|
||||||
|
let vc = [VOID, region, aclass.last_store.get()];
|
||||||
let load = self.ci.nodes.new_node(ty, Kind::Load, vc);
|
let load = self.ci.nodes.new_node(ty, Kind::Load, vc);
|
||||||
self.ci.scope.loads.push(StrongRef::new(load, &mut self.ci.nodes));
|
aclass.loads.push(StrongRef::new(load, &mut self.ci.nodes));
|
||||||
load
|
load
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn aclass_index(&mut self, mut region: Nid) -> usize {
|
||||||
|
loop {
|
||||||
|
region = match self.ci.nodes[region].kind {
|
||||||
|
Kind::BinOp { op: TokenKind::Add | TokenKind::Sub } | Kind::Phi => {
|
||||||
|
self.ci.nodes[region].inputs[1]
|
||||||
|
}
|
||||||
|
_ => break self.ci.nodes[region].aclass,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate(&mut self, entry: FileId) {
|
pub fn generate(&mut self, entry: FileId) {
|
||||||
self.find_type(0, entry, entry, Err("main"), self.files);
|
self.find_type(0, entry, entry, Err("main"), self.files);
|
||||||
if self.tys.ins.funcs.is_empty() {
|
if self.tys.ins.funcs.is_empty() {
|
||||||
|
@ -2114,8 +2185,10 @@ impl<'a> Codegen<'a> {
|
||||||
if self.ci.inline_depth == 0 {
|
if self.ci.inline_depth == 0 {
|
||||||
debug_assert_ne!(self.ci.ctrl.get(), VOID);
|
debug_assert_ne!(self.ci.ctrl.get(), VOID);
|
||||||
let mut inps = Vc::from([self.ci.ctrl.get(), value.id]);
|
let mut inps = Vc::from([self.ci.ctrl.get(), value.id]);
|
||||||
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
|
for (i, aclass) in self.ci.scope.aclasses.iter_mut().enumerate() {
|
||||||
inps.push(self.ci.scope.store.value());
|
self.ci.nodes.load_loop_aclass(i, aclass, &mut self.ci.loops);
|
||||||
|
inps.push(aclass.last_store.get());
|
||||||
|
}
|
||||||
|
|
||||||
self.ci.ctrl.set(
|
self.ci.ctrl.set(
|
||||||
self.ci.nodes.new_node(ty::Id::VOID, Kind::Return, inps),
|
self.ci.nodes.new_node(ty::Id::VOID, Kind::Return, inps),
|
||||||
|
@ -2453,9 +2526,17 @@ impl<'a> Codegen<'a> {
|
||||||
let mut inps = Vc::from([NEVER]);
|
let mut inps = Vc::from([NEVER]);
|
||||||
let arg_base = self.tys.tmp.args.len();
|
let arg_base = self.tys.tmp.args.len();
|
||||||
let mut has_ptr_arg = false;
|
let mut has_ptr_arg = false;
|
||||||
|
let mut clobbered_aliases = vec![];
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let value = self.expr(arg)?;
|
let value = self.expr(arg)?;
|
||||||
has_ptr_arg |= value.ty.has_pointers(self.tys);
|
if let Some(base) = self.tys.base_of(value.ty) {
|
||||||
|
clobbered_aliases.push(self.aclass_index(value.id));
|
||||||
|
if base.has_pointers(self.tys) {
|
||||||
|
clobbered_aliases.push(0);
|
||||||
|
}
|
||||||
|
} else if value.ty.has_pointers(self.tys) {
|
||||||
|
clobbered_aliases.push(0);
|
||||||
|
}
|
||||||
self.tys.tmp.args.push(value.ty);
|
self.tys.tmp.args.push(value.ty);
|
||||||
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
|
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
|
||||||
self.ci.nodes.lock(value.id);
|
self.ci.nodes.lock(value.id);
|
||||||
|
@ -2468,9 +2549,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.ci.nodes.unlock(n);
|
self.ci.nodes.unlock(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_ptr_arg {
|
for &clobbered in clobbered_aliases.iter() {
|
||||||
inps.push(self.ci.scope.store.value());
|
let aclass = &mut self.ci.scope.aclasses[clobbered];
|
||||||
self.ci.scope.loads.retain_mut(|load| {
|
inps.push(aclass.last_store.get());
|
||||||
|
aclass.loads.retain_mut(|load| {
|
||||||
if inps.contains(&load.get()) {
|
if inps.contains(&load.get()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2498,10 +2580,6 @@ impl<'a> Codegen<'a> {
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
);
|
);
|
||||||
|
|
||||||
if has_ptr_arg {
|
|
||||||
self.store_mem(VOID, ty::Id::VOID, VOID);
|
|
||||||
}
|
|
||||||
|
|
||||||
alt_value.or(Some(Value::new(self.ci.ctrl.get()).ty(ty)))
|
alt_value.or(Some(Value::new(self.ci.ctrl.get()).ty(ty)))
|
||||||
}
|
}
|
||||||
Expr::Call { func, args, .. } => {
|
Expr::Call { func, args, .. } => {
|
||||||
|
@ -2541,16 +2619,25 @@ impl<'a> Codegen<'a> {
|
||||||
let mut cargs = cargs.iter();
|
let mut cargs = cargs.iter();
|
||||||
let mut args = args.iter();
|
let mut args = args.iter();
|
||||||
let mut has_ptr_arg = false;
|
let mut has_ptr_arg = false;
|
||||||
|
let mut clobbered_aliases = vec![];
|
||||||
while let Some(ty) = tys.next(self.tys) {
|
while let Some(ty) = tys.next(self.tys) {
|
||||||
let carg = cargs.next().unwrap();
|
let carg = cargs.next().unwrap();
|
||||||
let Some(arg) = args.next() else { break };
|
let Some(arg) = args.next() else { break };
|
||||||
let Arg::Value(ty) = ty else { continue };
|
let Arg::Value(ty) = ty else { continue };
|
||||||
has_ptr_arg |= ty.has_pointers(self.tys);
|
|
||||||
|
|
||||||
let mut value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
let mut value = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
||||||
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
|
debug_assert_ne!(self.ci.nodes[value.id].kind, Kind::Stre);
|
||||||
self.assert_ty(arg.pos(), &mut value, ty, fa!("argument {}", carg.name));
|
self.assert_ty(arg.pos(), &mut value, ty, fa!("argument {}", carg.name));
|
||||||
|
|
||||||
|
if let Some(base) = self.tys.base_of(value.ty) {
|
||||||
|
clobbered_aliases.push(self.aclass_index(value.id));
|
||||||
|
if base.has_pointers(self.tys) {
|
||||||
|
clobbered_aliases.push(0);
|
||||||
|
}
|
||||||
|
} else if value.ty.has_pointers(self.tys) {
|
||||||
|
clobbered_aliases.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
self.ci.nodes.lock(value.id);
|
self.ci.nodes.lock(value.id);
|
||||||
inps.push(value.id);
|
inps.push(value.id);
|
||||||
}
|
}
|
||||||
|
@ -2559,9 +2646,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.ci.nodes.unlock(n);
|
self.ci.nodes.unlock(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_ptr_arg {
|
for &clobbered in clobbered_aliases.iter() {
|
||||||
inps.push(self.ci.scope.store.value());
|
let aclass = &mut self.ci.scope.aclasses[clobbered];
|
||||||
self.ci.scope.loads.retain_mut(|load| {
|
inps.push(aclass.last_store.get());
|
||||||
|
aclass.loads.retain_mut(|load| {
|
||||||
if inps.contains(&load.get()) {
|
if inps.contains(&load.get()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2589,10 +2677,6 @@ impl<'a> Codegen<'a> {
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
);
|
);
|
||||||
|
|
||||||
if has_ptr_arg {
|
|
||||||
self.store_mem(VOID, ty::Id::VOID, VOID);
|
|
||||||
}
|
|
||||||
|
|
||||||
alt_value.or(Some(Value::new(self.ci.ctrl.get()).ty(sig.ret)))
|
alt_value.or(Some(Value::new(self.ci.ctrl.get()).ty(sig.ret)))
|
||||||
}
|
}
|
||||||
Expr::Directive { name: "inline", args: [func, args @ ..], .. } => {
|
Expr::Directive { name: "inline", args: [func, args @ ..], .. } => {
|
||||||
|
@ -2893,10 +2977,14 @@ impl<'a> Codegen<'a> {
|
||||||
scope: self.ci.scope.dup(&mut self.ci.nodes),
|
scope: self.ci.scope.dup(&mut self.ci.nodes),
|
||||||
});
|
});
|
||||||
|
|
||||||
for var in &mut self.ci.scope.iter_mut() {
|
for var in self.ci.scope.vars.iter_mut() {
|
||||||
var.set_value(VOID, &mut self.ci.nodes);
|
var.set_value(VOID, &mut self.ci.nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for aclass in self.ci.scope.aclasses.iter_mut() {
|
||||||
|
aclass.last_store.set(VOID, &mut self.ci.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
self.expr(body);
|
self.expr(body);
|
||||||
|
|
||||||
let Loop { ctrl: [con, ..], ctrl_scope: [cons, ..], .. } =
|
let Loop { ctrl: [con, ..], ctrl_scope: [cons, ..], .. } =
|
||||||
|
@ -2931,7 +3019,9 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(bre) = bre.unwrap(&mut self.ci.nodes) else {
|
let Some(bre) = bre.unwrap(&mut self.ci.nodes) else {
|
||||||
for (loop_var, scope_var) in self.ci.scope.iter_mut().zip(scope.iter_mut()) {
|
for (loop_var, scope_var) in
|
||||||
|
self.ci.scope.vars.iter_mut().zip(scope.vars.iter_mut())
|
||||||
|
{
|
||||||
if self.ci.nodes[scope_var.value()].is_lazy_phi(node) {
|
if self.ci.nodes[scope_var.value()].is_lazy_phi(node) {
|
||||||
if loop_var.value() != scope_var.value() {
|
if loop_var.value() != scope_var.value() {
|
||||||
scope_var.set_value(
|
scope_var.set_value(
|
||||||
|
@ -2950,6 +3040,29 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (loop_class, scope_class) in
|
||||||
|
self.ci.scope.aclasses.iter_mut().zip(scope.aclasses.iter_mut())
|
||||||
|
{
|
||||||
|
if self.ci.nodes[scope_class.last_store.get()].is_lazy_phi(node) {
|
||||||
|
if loop_class.last_store.get() != scope_class.last_store.get() {
|
||||||
|
scope_class.last_store.set(
|
||||||
|
self.ci.nodes.modify_input(
|
||||||
|
scope_class.last_store.get(),
|
||||||
|
2,
|
||||||
|
loop_class.last_store.get(),
|
||||||
|
),
|
||||||
|
&mut self.ci.nodes,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let phi = &self.ci.nodes[scope_class.last_store.get()];
|
||||||
|
let prev = phi.inputs[1];
|
||||||
|
self.ci.nodes.replace(scope_class.last_store.get(), prev);
|
||||||
|
scope_class.last_store.set(prev, &mut self.ci.nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scope.clear(&mut self.ci.nodes);
|
scope.clear(&mut self.ci.nodes);
|
||||||
self.ci.ctrl.set(NEVER, &mut self.ci.nodes);
|
self.ci.ctrl.set(NEVER, &mut self.ci.nodes);
|
||||||
|
|
||||||
|
@ -2965,8 +3078,13 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
self.ci.nodes.lock(node);
|
self.ci.nodes.lock(node);
|
||||||
|
|
||||||
for ((dest_var, scope_var), loop_var) in
|
for ((dest_var, scope_var), loop_var) in self
|
||||||
self.ci.scope.iter_mut().zip(scope.iter_mut()).zip(bres.iter_mut())
|
.ci
|
||||||
|
.scope
|
||||||
|
.vars
|
||||||
|
.iter_mut()
|
||||||
|
.zip(scope.vars.iter_mut())
|
||||||
|
.zip(bres.vars.iter_mut())
|
||||||
{
|
{
|
||||||
if self.ci.nodes[scope_var.value()].is_lazy_phi(node) {
|
if self.ci.nodes[scope_var.value()].is_lazy_phi(node) {
|
||||||
if loop_var.value() != scope_var.value() {
|
if loop_var.value() != scope_var.value() {
|
||||||
|
@ -2992,9 +3110,44 @@ impl<'a> Codegen<'a> {
|
||||||
debug_assert!(!self.ci.nodes[dest_var.value()].is_lazy_phi(node));
|
debug_assert!(!self.ci.nodes[dest_var.value()].is_lazy_phi(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ((dest_class, scope_class), loop_class) in self
|
||||||
|
.ci
|
||||||
|
.scope
|
||||||
|
.aclasses
|
||||||
|
.iter_mut()
|
||||||
|
.zip(scope.aclasses.iter_mut())
|
||||||
|
.zip(bres.aclasses.iter_mut())
|
||||||
|
{
|
||||||
|
if self.ci.nodes[scope_class.last_store.get()].is_lazy_phi(node) {
|
||||||
|
if loop_class.last_store.get() != scope_class.last_store.get() {
|
||||||
|
scope_class.last_store.set(
|
||||||
|
self.ci.nodes.modify_input(
|
||||||
|
scope_class.last_store.get(),
|
||||||
|
2,
|
||||||
|
loop_class.last_store.get(),
|
||||||
|
),
|
||||||
|
&mut self.ci.nodes,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if dest_class.last_store.get() == scope_class.last_store.get() {
|
||||||
|
dest_class.last_store.set(VOID, &mut self.ci.nodes);
|
||||||
|
}
|
||||||
|
let phi = &self.ci.nodes[scope_class.last_store.get()];
|
||||||
|
let prev = phi.inputs[1];
|
||||||
|
self.ci.nodes.replace(scope_class.last_store.get(), prev);
|
||||||
|
scope_class.last_store.set(prev, &mut self.ci.nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dest_class.last_store.get() == VOID {
|
||||||
|
dest_class.last_store.set(scope_class.last_store.get(), &mut self.ci.nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(!self.ci.nodes[dest_class.last_store.get()].is_lazy_phi(node));
|
||||||
|
}
|
||||||
|
|
||||||
scope.clear(&mut self.ci.nodes);
|
scope.clear(&mut self.ci.nodes);
|
||||||
bres.clear(&mut self.ci.nodes);
|
bres.clear(&mut self.ci.nodes);
|
||||||
self.ci.scope.loads.drain(..).for_each(|l| _ = l.remove(&mut self.ci.nodes));
|
|
||||||
|
|
||||||
self.ci.nodes.unlock(node);
|
self.ci.nodes.unlock(node);
|
||||||
let rpl = self.ci.nodes.late_peephole(node).unwrap_or(node);
|
let rpl = self.ci.nodes.late_peephole(node).unwrap_or(node);
|
||||||
|
@ -3029,8 +3182,11 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.nodes.load_loop_store(&mut self.ci.scope.store, &mut self.ci.loops);
|
let mut orig_classes = vec![];
|
||||||
let orig_store = self.ci.scope.store.dup(&mut self.ci.nodes);
|
for (i, aclass) in self.ci.scope.aclasses.iter_mut().enumerate() {
|
||||||
|
self.ci.nodes.load_loop_aclass(i, aclass, &mut self.ci.loops);
|
||||||
|
orig_classes.push(aclass.dup(&mut self.ci.nodes));
|
||||||
|
}
|
||||||
let else_scope = self.ci.scope.dup(&mut self.ci.nodes);
|
let else_scope = self.ci.scope.dup(&mut self.ci.nodes);
|
||||||
|
|
||||||
self.ci.ctrl.set(
|
self.ci.ctrl.set(
|
||||||
|
@ -3050,7 +3206,7 @@ impl<'a> Codegen<'a> {
|
||||||
self.ci.ctrl.get()
|
self.ci.ctrl.get()
|
||||||
};
|
};
|
||||||
|
|
||||||
orig_store.remove(&mut self.ci.nodes);
|
orig_classes.into_iter().for_each(|c| c.remove(&mut self.ci.nodes));
|
||||||
|
|
||||||
if lcntrl == Nid::MAX && rcntrl == Nid::MAX {
|
if lcntrl == Nid::MAX && rcntrl == Nid::MAX {
|
||||||
then_scope.clear(&mut self.ci.nodes);
|
then_scope.clear(&mut self.ci.nodes);
|
||||||
|
|
|
@ -1,26 +1,24 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -36d
|
ADDI64 r254, r254, -44d
|
||||||
ST r31, r254, 28a, 8h
|
ST r31, r254, 28a, 16h
|
||||||
LI8 r2, 0b
|
LI64 r32, 1d
|
||||||
ST r2, r254, 0a, 1h
|
ADDI64 r2, r254, 0d
|
||||||
ST r2, r254, 1a, 1h
|
ST r32, r254, 0a, 8h
|
||||||
LI16 r4, 511h
|
LI64 r8, 2d
|
||||||
ST r4, r254, 2a, 1h
|
ST r8, r254, 8a, 8h
|
||||||
LI16 r8, 1h
|
LI64 r11, 4d
|
||||||
ST r8, r254, 3a, 1h
|
ST r11, r254, 16a, 8h
|
||||||
LI64 r11, 1d
|
|
||||||
ADDI64 r2, r254, 4d
|
|
||||||
ST r11, r254, 4a, 8h
|
|
||||||
LI64 r3, 2d
|
|
||||||
ST r3, r254, 12a, 8h
|
|
||||||
LI64 r6, 4d
|
|
||||||
ST r6, r254, 20a, 8h
|
|
||||||
JAL r31, r0, :pass
|
JAL r31, r0, :pass
|
||||||
LD r12, r254, 3a, 1h
|
LI8 r10, 0b
|
||||||
ANDI r2, r12, 255d
|
ST r10, r254, 24a, 1h
|
||||||
ADD64 r1, r1, r2
|
ST r10, r254, 25a, 1h
|
||||||
LD r31, r254, 28a, 8h
|
LI16 r12, 511h
|
||||||
ADDI64 r254, r254, 36d
|
ST r12, r254, 26a, 1h
|
||||||
|
LI16 r4, 1h
|
||||||
|
ST r4, r254, 27a, 1h
|
||||||
|
ADD64 r1, r1, r32
|
||||||
|
LD r31, r254, 28a, 16h
|
||||||
|
ADDI64 r254, r254, 44d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
pass:
|
pass:
|
||||||
LD r4, r2, 8a, 8h
|
LD r4, r2, 8a, 8h
|
||||||
|
@ -31,6 +29,6 @@ pass:
|
||||||
LD r1, r10, 0a, 8h
|
LD r1, r10, 0a, 8h
|
||||||
ADD64 r1, r1, r9
|
ADD64 r1, r1, r9
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 318
|
code size: 294
|
||||||
ret: 8
|
ret: 8
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,48 +1,44 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -12d
|
||||||
LI8 r3, 255b
|
LI8 r1, 255b
|
||||||
ADDI64 r2, r254, 12d
|
ST r1, r254, 0a, 1h
|
||||||
ST r3, r254, 12a, 1h
|
LI8 r4, 0b
|
||||||
LI8 r6, 0b
|
ST r4, r254, 1a, 1h
|
||||||
ST r6, r254, 13a, 1h
|
ST r4, r254, 2a, 1h
|
||||||
ST r6, r254, 14a, 1h
|
ST r1, r254, 3a, 1h
|
||||||
ST r3, r254, 15a, 1h
|
LI32 r9, 0w
|
||||||
LI32 r11, 0w
|
ST r9, r254, 4a, 4h
|
||||||
ST r11, r254, 16a, 4h
|
LI32 r12, 2w
|
||||||
LI32 r3, 2w
|
ST r12, r254, 8a, 4h
|
||||||
ST r3, r254, 20a, 4h
|
LD r3, r254, 8a, 4h
|
||||||
ADDI64 r5, r254, 0d
|
|
||||||
BMC r2, r5, 12h
|
|
||||||
LD r8, r254, 8a, 4h
|
|
||||||
ANDI r8, r8, 4294967295d
|
|
||||||
ANDI r3, r3, 4294967295d
|
ANDI r3, r3, 4294967295d
|
||||||
JEQ r8, r3, :0
|
ANDI r12, r12, 4294967295d
|
||||||
|
JEQ r3, r12, :0
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: LD r2, r254, 4a, 4h
|
0: LD r10, r254, 4a, 4h
|
||||||
ANDI r2, r2, 4294967295d
|
ANDI r10, r10, 4294967295d
|
||||||
ANDI r11, r11, 4294967295d
|
ANDI r9, r9, 4294967295d
|
||||||
JEQ r2, r11, :2
|
JEQ r10, r9, :2
|
||||||
LI64 r1, 64d
|
LI64 r1, 64d
|
||||||
JMP :1
|
JMP :1
|
||||||
2: LD r11, r254, 0a, 1h
|
2: LD r4, r254, 0a, 1h
|
||||||
LD r9, r254, 4a, 4h
|
LD r7, r254, 1a, 1h
|
||||||
LD r12, r254, 8a, 4h
|
ANDI r8, r4, 255d
|
||||||
LD r5, r254, 1a, 1h
|
LD r6, r254, 4a, 4h
|
||||||
ANDI r4, r11, 255d
|
LD r1, r254, 2a, 1h
|
||||||
ADD32 r3, r12, r9
|
ANDI r2, r7, 255d
|
||||||
LD r11, r254, 2a, 1h
|
ADD32 r7, r6, r8
|
||||||
ANDI r10, r5, 255d
|
|
||||||
ADD32 r9, r3, r4
|
|
||||||
LD r5, r254, 3a, 1h
|
LD r5, r254, 3a, 1h
|
||||||
ANDI r4, r11, 255d
|
ANDI r6, r1, 255d
|
||||||
ADD32 r3, r9, r10
|
ADD32 r11, r7, r2
|
||||||
ANDI r9, r5, 255d
|
ANDI r9, r5, 255d
|
||||||
ADD32 r8, r3, r4
|
ADD32 r2, r11, r6
|
||||||
ADD32 r12, r8, r9
|
ADD32 r4, r2, r9
|
||||||
ANDI r1, r12, 4294967295d
|
ADD32 r6, r4, r12
|
||||||
1: ADDI64 r254, r254, 24d
|
ANDI r1, r6, 4294967295d
|
||||||
|
1: ADDI64 r254, r254, 12d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 427
|
code size: 387
|
||||||
ret: 512
|
ret: 512
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -23,25 +23,21 @@ scalar_values:
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
structs:
|
structs:
|
||||||
ADDI64 r254, r254, -48d
|
ADDI64 r254, r254, -48d
|
||||||
LI64 r1, 0d
|
LI64 r3, 5d
|
||||||
ST r1, r254, 40a, 8h
|
ST r3, r254, 0a, 8h
|
||||||
LI64 r4, 20d
|
ST r3, r254, 8a, 8h
|
||||||
ST r4, r254, 0a, 8h
|
LD r7, r254, 0a, 8h
|
||||||
LI64 r7, 5d
|
ADDI64 r9, r7, 15d
|
||||||
ST r7, r254, 8a, 8h
|
ST r9, r254, 24a, 8h
|
||||||
ST r7, r254, 16a, 8h
|
LI64 r8, 20d
|
||||||
LD r11, r254, 0a, 8h
|
ST r8, r254, 32a, 8h
|
||||||
LD r1, r254, 8a, 8h
|
LI64 r9, 0d
|
||||||
ADD64 r3, r1, r11
|
LD r3, r254, 24a, 8h
|
||||||
SUB64 r5, r3, r7
|
ST r8, r254, 16a, 8h
|
||||||
ST r5, r254, 24a, 8h
|
ST r9, r254, 40a, 8h
|
||||||
ST r4, r254, 32a, 8h
|
SUB64 r1, r3, r8
|
||||||
LD r9, r254, 40a, 8h
|
|
||||||
LD r11, r254, 24a, 8h
|
|
||||||
ADD64 r1, r11, r9
|
|
||||||
SUB64 r1, r1, r4
|
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 48d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 373
|
code size: 346
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -24d
|
||||||
ST r31, r254, 16a, 8h
|
ST r31, r254, 16a, 8h
|
||||||
|
ADDI64 r3, r254, 0d
|
||||||
ADDI64 r2, r254, 8d
|
ADDI64 r2, r254, 8d
|
||||||
LI64 r4, 0d
|
LI64 r4, 0d
|
||||||
ST r4, r254, 8a, 8h
|
|
||||||
ADDI64 r3, r254, 0d
|
|
||||||
ST r4, r254, 0a, 8h
|
ST r4, r254, 0a, 8h
|
||||||
|
ST r4, r254, 8a, 8h
|
||||||
LI64 r4, 1024d
|
LI64 r4, 1024d
|
||||||
JAL r31, r0, :set
|
JAL r31, r0, :set
|
||||||
ANDI r1, r1, 4294967295d
|
ANDI r1, r1, 4294967295d
|
||||||
|
|
Loading…
Reference in a new issue