removing offset from stores and loads
This commit is contained in:
parent
3a494147ec
commit
c900f4ef5c
|
@ -17,6 +17,7 @@ log = "0.4.22"
|
||||||
git = "https://github.com/jakubDoka/regalloc2"
|
git = "https://github.com/jakubDoka/regalloc2"
|
||||||
branch = "reuse-allocations"
|
branch = "reuse-allocations"
|
||||||
optional = true
|
optional = true
|
||||||
|
features = ["trace-log"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "opts"]
|
default = ["std", "opts"]
|
||||||
|
|
|
@ -368,8 +368,8 @@ impl Nodes {
|
||||||
Kind::Then => write!(out, "ctrl: {:<5}", "then"),
|
Kind::Then => write!(out, "ctrl: {:<5}", "then"),
|
||||||
Kind::Else => write!(out, "ctrl: {:<5}", "else"),
|
Kind::Else => write!(out, "ctrl: {:<5}", "else"),
|
||||||
Kind::Stck => write!(out, "stck: "),
|
Kind::Stck => write!(out, "stck: "),
|
||||||
Kind::Load { offset } => write!(out, "load: {offset:<5}"),
|
Kind::Load => write!(out, "load: "),
|
||||||
Kind::Stre { offset } => write!(out, "stre: {offset:<5}"),
|
Kind::Stre => write!(out, "stre: "),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
@ -691,13 +691,9 @@ pub enum Kind {
|
||||||
// [ctrl]
|
// [ctrl]
|
||||||
Stck,
|
Stck,
|
||||||
// [ctrl, memory]
|
// [ctrl, memory]
|
||||||
Load {
|
Load,
|
||||||
offset: Offset,
|
|
||||||
},
|
|
||||||
// [ctrl, value, memory]
|
// [ctrl, value, memory]
|
||||||
Stre {
|
Stre,
|
||||||
offset: Offset,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Kind {
|
impl Kind {
|
||||||
|
@ -959,7 +955,7 @@ impl Codegen {
|
||||||
log::info!("{out}");
|
log::info!("{out}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn store_mem(&mut self, region: Nid, offset: Offset, value: Nid) -> Nid {
|
fn store_mem(&mut self, region: Nid, value: Nid) -> Nid {
|
||||||
let mut vc = Vc::from([VOID, value, region]);
|
let mut vc = Vc::from([VOID, value, region]);
|
||||||
if let Some(str) = self.ci.store {
|
if let Some(str) = self.ci.store {
|
||||||
self.ci.nodes.unlock(str);
|
self.ci.nodes.unlock(str);
|
||||||
|
@ -974,18 +970,18 @@ impl Codegen {
|
||||||
vc.push(load);
|
vc.push(load);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let store = self.ci.nodes.new_node(self.tof(value), Kind::Stre { offset }, vc);
|
let store = self.ci.nodes.new_node(self.tof(value), Kind::Stre, vc);
|
||||||
self.ci.nodes.lock(store);
|
self.ci.nodes.lock(store);
|
||||||
self.ci.store = Some(store);
|
self.ci.store = Some(store);
|
||||||
store
|
store
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_mem(&mut self, region: Nid, offset: Offset, ty: ty::Id) -> Nid {
|
fn load_mem(&mut self, region: Nid, ty: ty::Id) -> Nid {
|
||||||
let mut vc = Vc::from([VOID, region]);
|
let mut vc = Vc::from([VOID, region]);
|
||||||
if let Some(str) = self.ci.store {
|
if let Some(str) = self.ci.store {
|
||||||
vc.push(str);
|
vc.push(str);
|
||||||
}
|
}
|
||||||
let load = self.ci.nodes.new_node(ty, Kind::Load { offset }, vc);
|
let load = self.ci.nodes.new_node(ty, Kind::Load, vc);
|
||||||
self.ci.nodes.lock(load);
|
self.ci.nodes.lock(load);
|
||||||
self.ci.loads.push(load);
|
self.ci.loads.push(load);
|
||||||
load
|
load
|
||||||
|
@ -1105,21 +1101,12 @@ impl Codegen {
|
||||||
if val.ptr {
|
if val.ptr {
|
||||||
val.ptr = false;
|
val.ptr = false;
|
||||||
val.ty = self.tys.make_ptr(val.ty);
|
val.ty = self.tys.make_ptr(val.ty);
|
||||||
if val.off != 0 {
|
self.offset(&mut val);
|
||||||
let off = self.ci.nodes.new_node_nop(
|
|
||||||
ty::Id::INT,
|
|
||||||
Kind::CInt { value: val.off as i64 },
|
|
||||||
[VOID],
|
|
||||||
);
|
|
||||||
let inps = [VOID, val.id, off];
|
|
||||||
val.id =
|
|
||||||
self.ci.nodes.new_node(val.ty, Kind::UnOp { op: TokenKind::Add }, inps)
|
|
||||||
}
|
|
||||||
return Some(val);
|
return Some(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
let stack = self.ci.nodes.new_node_nop(val.ty, Kind::Stck, [VOID, MEM]);
|
let stack = self.ci.nodes.new_node_nop(val.ty, Kind::Stck, [VOID, MEM]);
|
||||||
self.store_mem(stack, 0, val.id);
|
self.store_mem(stack, val.id);
|
||||||
|
|
||||||
Some(Value::new(stack).ty(self.tys.make_ptr(val.ty)))
|
Some(Value::new(stack).ty(self.tys.make_ptr(val.ty)))
|
||||||
}
|
}
|
||||||
|
@ -1152,7 +1139,7 @@ impl Codegen {
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
Expr::BinOp { left, op: TokenKind::Assign, right } => {
|
Expr::BinOp { left, op: TokenKind::Assign, right } => {
|
||||||
let dest = self.raw_expr(left)?;
|
let mut dest = self.raw_expr(left)?;
|
||||||
let value = self.expr(right)?;
|
let value = self.expr(right)?;
|
||||||
|
|
||||||
_ = self.assert_ty(left.pos(), value.ty, dest.ty, true, "assignment dest");
|
_ = self.assert_ty(left.pos(), value.ty, dest.ty, true, "assignment dest");
|
||||||
|
@ -1163,7 +1150,8 @@ impl Codegen {
|
||||||
let prev = core::mem::replace(&mut var.value, value);
|
let prev = core::mem::replace(&mut var.value, value);
|
||||||
self.ci.nodes.unlock_remove(prev.id);
|
self.ci.nodes.unlock_remove(prev.id);
|
||||||
} else if dest.ptr {
|
} else if dest.ptr {
|
||||||
self.store_mem(dest.id, dest.off, value.id);
|
self.offset(&mut dest);
|
||||||
|
self.store_mem(dest.id, value.id);
|
||||||
} else {
|
} else {
|
||||||
self.report(left.pos(), "cannot assign to this expression");
|
self.report(left.pos(), "cannot assign to this expression");
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1257,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.store_mem(VOID, 0, VOID);
|
self.store_mem(VOID, VOID);
|
||||||
for load in self.ci.loads.drain(..) {
|
for load in self.ci.loads.drain(..) {
|
||||||
if !self.ci.nodes.unlock_remove(load) {
|
if !self.ci.nodes.unlock_remove(load) {
|
||||||
inps.push(load);
|
inps.push(load);
|
||||||
|
@ -1331,7 +1319,9 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?;
|
let value = self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?;
|
||||||
self.store_mem(mem, offset, value.id);
|
let mut mem = Value::ptr(mem).ty(ty).off(offset);
|
||||||
|
self.offset(&mut mem);
|
||||||
|
self.store_mem(mem.id, value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let field_list = self
|
let field_list = self
|
||||||
|
@ -1560,11 +1550,26 @@ impl Codegen {
|
||||||
let mut n = self.raw_expr_ctx(expr, ctx)?;
|
let mut n = self.raw_expr_ctx(expr, ctx)?;
|
||||||
self.strip_var(&mut n);
|
self.strip_var(&mut n);
|
||||||
if core::mem::take(&mut n.ptr) {
|
if core::mem::take(&mut n.ptr) {
|
||||||
n.id = self.load_mem(n.id, n.off, n.ty);
|
self.offset(&mut n);
|
||||||
|
n.id = self.load_mem(n.id, n.ty);
|
||||||
}
|
}
|
||||||
Some(n)
|
Some(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn offset(&mut self, val: &mut Value) {
|
||||||
|
if val.off == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let off = self.ci.nodes.new_node_nop(
|
||||||
|
ty::Id::INT,
|
||||||
|
Kind::CInt { value: core::mem::take(&mut val.off) as i64 },
|
||||||
|
[VOID],
|
||||||
|
);
|
||||||
|
let inps = [VOID, val.id, off];
|
||||||
|
val.id = self.ci.nodes.new_node(val.ty, Kind::BinOp { op: TokenKind::Add }, inps)
|
||||||
|
}
|
||||||
|
|
||||||
fn strip_var(&mut self, n: &mut Value) {
|
fn strip_var(&mut self, n: &mut Value) {
|
||||||
if core::mem::take(&mut n.var) {
|
if core::mem::take(&mut n.var) {
|
||||||
let id = (u16::MAX - n.id) as usize;
|
let id = (u16::MAX - n.id) as usize;
|
||||||
|
@ -1939,25 +1944,25 @@ impl Codegen {
|
||||||
let offset = func.nodes[nid].offset;
|
let offset = func.nodes[nid].offset;
|
||||||
self.ci.emit(instrs::addi64(atr(allocs[0]), base, offset as _));
|
self.ci.emit(instrs::addi64(atr(allocs[0]), base, offset as _));
|
||||||
}
|
}
|
||||||
Kind::Load { offset } => {
|
Kind::Load => {
|
||||||
let region = node.inputs[1];
|
let region = node.inputs[1];
|
||||||
let size = self.tys.size_of(node.ty);
|
let size = self.tys.size_of(node.ty);
|
||||||
if size <= 8 {
|
if size <= 8 {
|
||||||
let (base, offset) = match func.nodes[region].kind {
|
let (base, offset) = match func.nodes[region].kind {
|
||||||
Kind::Stck => (reg::STACK_PTR, func.nodes[region].offset + offset),
|
Kind::Stck => (reg::STACK_PTR, func.nodes[region].offset),
|
||||||
_ => (atr(allocs[1]), func.nodes[region].offset + offset),
|
_ => (atr(allocs[1]), func.nodes[region].offset),
|
||||||
};
|
};
|
||||||
self.ci.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _));
|
self.ci.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Stre { offset } => {
|
Kind::Stre => {
|
||||||
let region = node.inputs[2];
|
let region = node.inputs[2];
|
||||||
if region != VOID {
|
if region != VOID {
|
||||||
let size = u16::try_from(self.tys.size_of(node.ty)).expect("TODO");
|
let size = u16::try_from(self.tys.size_of(node.ty)).expect("TODO");
|
||||||
let nd = &func.nodes[region];
|
let nd = &func.nodes[region];
|
||||||
let (base, offset, src) = match nd.kind {
|
let (base, offset, src) = match nd.kind {
|
||||||
Kind::Stck => (reg::STACK_PTR, nd.offset + offset, allocs[0]),
|
Kind::Stck => (reg::STACK_PTR, nd.offset, allocs[0]),
|
||||||
_ => (atr(allocs[0]), offset, allocs[1]),
|
_ => (atr(allocs[0]), 0, allocs[1]),
|
||||||
};
|
};
|
||||||
if size > 8 {
|
if size > 8 {
|
||||||
self.ci.emit(instrs::bmc(base, atr(src), size));
|
self.ci.emit(instrs::bmc(base, atr(src), size));
|
||||||
|
@ -2769,15 +2774,13 @@ fn push_down(nodes: &mut Nodes, node: Nid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let prev = nodes[node].inputs[0];
|
let prev = nodes[node].inputs[0];
|
||||||
if min != prev {
|
debug_assert!(idepth(nodes, min) >= idepth(nodes, prev));
|
||||||
debug_assert!(idepth(nodes, min) > idepth(nodes, prev));
|
|
||||||
let index = nodes[prev].outputs.iter().position(|&p| p == node).unwrap();
|
let index = nodes[prev].outputs.iter().position(|&p| p == node).unwrap();
|
||||||
nodes[prev].outputs.remove(index);
|
nodes[prev].outputs.remove(index);
|
||||||
nodes[node].inputs[0] = min;
|
nodes[node].inputs[0] = min;
|
||||||
nodes[min].outputs.push(node);
|
nodes[min].outputs.push(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn use_block(target: Nid, from: Nid, nodes: &mut Nodes) -> Nid {
|
fn use_block(target: Nid, from: Nid, nodes: &mut Nodes) -> Nid {
|
||||||
if nodes[from].kind != Kind::Phi {
|
if nodes[from].kind != Kind::Phi {
|
||||||
|
|
Loading…
Reference in a new issue