some cleanump and ironing out bugs in new regalloc

This commit is contained in:
Jakub Doka 2024-11-15 12:04:05 +01:00
parent 81cf39b602
commit bb625a9e19
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
5 changed files with 39 additions and 43 deletions

View file

@ -1106,7 +1106,7 @@ trait TypeParser {
files: &[parser::Ast], files: &[parser::Ast],
) -> ty::Id { ) -> ty::Id {
match *expr { match *expr {
Expr::Mod { id, .. } => ty::Kind::Module(id).compress(), Expr::Mod { id, .. } => id.into(),
Expr::UnOp { op: TokenKind::Xor, val, .. } => { Expr::UnOp { op: TokenKind::Xor, val, .. } => {
let base = self.parse_ty(file, val, None, files); let base = self.parse_ty(file, val, None, files);
self.tys().make_ptr(base) self.tys().make_ptr(base)

View file

@ -4064,10 +4064,7 @@ impl<'a> Codegen<'a> {
if !self.struct_op(pos, op, is, dst, lhs, rhs) { if !self.struct_op(pos, op, is, dst, lhs, rhs) {
self.report( self.report(
pos, pos,
fa!( fa!("... when appliing '{0} {op} {0}'", self.ty_display(s.into())),
"... when appliing '{0} {op} {0}'",
self.ty_display(ty::Kind::Struct(s).compress())
),
); );
} }
} }

View file

@ -104,7 +104,7 @@ impl Backend for HbvmBackend {
self.globals.shadow(types.ins.globals.len()); self.globals.shadow(types.ins.globals.len());
self.asm.frontier.push(ty::Kind::Func(from).compress()); self.asm.frontier.push(from.into());
while let Some(itm) = self.asm.frontier.pop() { while let Some(itm) = self.asm.frontier.pop() {
match itm.expand() { match itm.expand() {
ty::Kind::Func(func) => { ty::Kind::Func(func) => {
@ -341,6 +341,14 @@ impl Backend for HbvmBackend {
} }
impl Nodes { impl Nodes {
fn cond_op(&self, cnd: Nid) -> CondRet {
let Kind::BinOp { op } = self[cnd].kind else { return None };
if self[cnd].lock_rc == 0 {
return None;
}
op.cond_op(self[self[cnd].inputs[1]].ty)
}
fn strip_offset(&self, region: Nid, ty: ty::Id, tys: &Types) -> (Nid, Offset) { fn strip_offset(&self, region: Nid, ty: ty::Id, tys: &Types) -> (Nid, Offset) {
if matches!(self[region].kind, Kind::BinOp { op: TokenKind::Add | TokenKind::Sub }) if matches!(self[region].kind, Kind::BinOp { op: TokenKind::Add | TokenKind::Sub })
&& self[region].lock_rc != 0 && self[region].lock_rc != 0
@ -493,9 +501,7 @@ impl HbvmBackend {
match node.kind { match node.kind {
Kind::If => { Kind::If => {
let &[_, cnd] = node.inputs.as_slice() else { unreachable!() }; let &[_, cnd] = node.inputs.as_slice() else { unreachable!() };
if let Kind::BinOp { op } = nodes[cnd].kind if let Some((op, swapped)) = nodes.cond_op(cnd) {
&& let Some((op, swapped)) = op.cond_op(nodes[nodes[cnd].inputs[1]].ty)
{
let &[lhs, rhs] = allocs else { unreachable!() }; let &[lhs, rhs] = allocs else { unreachable!() };
let &[_, lh, rh] = nodes[cnd].inputs.as_slice() else { unreachable!() }; let &[_, lh, rh] = nodes[cnd].inputs.as_slice() else { unreachable!() };
@ -584,7 +590,6 @@ impl HbvmBackend {
let &[dst, oper] = allocs else { unreachable!() }; let &[dst, oper] = allocs else { unreachable!() };
self.emit(op(dst, oper)); self.emit(op(dst, oper));
} }
Kind::BinOp { .. } if node.lock_rc != 0 => {}
Kind::BinOp { op } => { Kind::BinOp { op } => {
let &[.., lh, rh] = node.inputs.as_slice() else { unreachable!() }; let &[.., lh, rh] = node.inputs.as_slice() else { unreachable!() };
@ -649,7 +654,7 @@ impl HbvmBackend {
self.emit(instrs::eca()); self.emit(instrs::eca());
} else { } else {
self.relocs.push(TypedReloc { self.relocs.push(TypedReloc {
target: ty::Kind::Func(func).compress(), target: func.into(),
reloc: Reloc::new(self.code.len(), 3, 4), reloc: Reloc::new(self.code.len(), 3, 4),
}); });
self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0)); self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
@ -663,7 +668,7 @@ impl HbvmBackend {
} }
Kind::Global { global } => { Kind::Global { global } => {
let reloc = Reloc::new(self.code.len(), 3, 4); let reloc = Reloc::new(self.code.len(), 3, 4);
self.relocs.push(TypedReloc { target: ty::Kind::Global(global).compress(), reloc }); self.relocs.push(TypedReloc { target: global.into(), reloc });
self.emit(instrs::lra(allocs[0], 0, 0)); self.emit(instrs::lra(allocs[0], 0, 0));
} }
Kind::Stck => { Kind::Stck => {
@ -724,12 +729,14 @@ impl Node {
} }
} }
type CondRet = Option<(fn(u8, u8, i16) -> EncodedInstr, bool)>;
impl TokenKind { impl TokenKind {
fn cmp_against(self) -> Option<u64> { fn cmp_against(self) -> Option<u64> {
Some(match self { Some(match self {
TokenKind::Le | TokenKind::Gt => 1, Self::Le | Self::Gt => 1,
TokenKind::Ne | TokenKind::Eq => 0, Self::Ne | Self::Eq => 0,
TokenKind::Ge | TokenKind::Lt => (-1i64) as _, Self::Ge | Self::Lt => (-1i64) as _,
_ => return None, _ => return None,
}) })
} }
@ -741,22 +748,21 @@ impl TokenKind {
let size = ty.simple_size().unwrap(); let size = ty.simple_size().unwrap();
let ops = match self { let ops = match self {
TokenKind::Gt => [instrs::fcmpgt32, instrs::fcmpgt64], Self::Gt => [instrs::fcmpgt32, instrs::fcmpgt64],
TokenKind::Lt => [instrs::fcmplt32, instrs::fcmplt64], Self::Lt => [instrs::fcmplt32, instrs::fcmplt64],
_ => return None, _ => return None,
}; };
Some(ops[size.ilog2() as usize - 2]) Some(ops[size.ilog2() as usize - 2])
} }
#[expect(clippy::type_complexity)] fn cond_op(self, ty: ty::Id) -> CondRet {
fn cond_op(self, ty: ty::Id) -> Option<(fn(u8, u8, i16) -> EncodedInstr, bool)> {
if ty.is_float() {
return None;
}
let signed = ty.is_signed(); let signed = ty.is_signed();
Some(( Some((
match self { match self {
Self::Eq => instrs::jne,
Self::Ne => instrs::jeq,
_ if ty.is_float() => return None,
Self::Le if signed => instrs::jgts, Self::Le if signed => instrs::jgts,
Self::Le => instrs::jgtu, Self::Le => instrs::jgtu,
Self::Lt if signed => instrs::jlts, Self::Lt if signed => instrs::jlts,
@ -765,11 +771,9 @@ impl TokenKind {
Self::Ge => instrs::jltu, Self::Ge => instrs::jltu,
Self::Gt if signed => instrs::jgts, Self::Gt if signed => instrs::jgts,
Self::Gt => instrs::jgtu, Self::Gt => instrs::jgtu,
Self::Eq => instrs::jne,
Self::Ne => instrs::jeq,
_ => return None, _ => return None,
}, },
matches!(self, Self::Lt | TokenKind::Gt), matches!(self, Self::Lt | Self::Gt),
)) ))
} }

View file

@ -127,9 +127,7 @@ impl HbvmBackend {
match node.kind { match node.kind {
Kind::If => { Kind::If => {
let &[_, cnd] = node.inputs.as_slice() else { unreachable!() }; let &[_, cnd] = node.inputs.as_slice() else { unreachable!() };
if let Kind::BinOp { op } = fuc.nodes[cnd].kind if fuc.nodes.cond_op(cnd).is_some() {
&& op.cond_op(fuc.nodes[fuc.nodes[cnd].inputs[1]].ty).is_some()
{
let &[_, lh, rh] = fuc.nodes[cnd].inputs.as_slice() else { let &[_, lh, rh] = fuc.nodes[cnd].inputs.as_slice() else {
unreachable!() unreachable!()
}; };
@ -475,12 +473,10 @@ impl<'a> Function<'a> {
self.emit_node(node.outputs[0]) self.emit_node(node.outputs[0])
} }
Kind::If => { Kind::If => {
let &[_, cond] = node.inputs.as_slice() else { unreachable!() }; let &[_, cnd] = node.inputs.as_slice() else { unreachable!() };
let &[mut then, mut else_] = node.outputs.as_slice() else { unreachable!() }; let &[mut then, mut else_] = node.outputs.as_slice() else { unreachable!() };
if let Kind::BinOp { op } = self.nodes[cond].kind if let Some((_, swapped)) = self.nodes.cond_op(cnd) {
&& let Some((_, swapped)) = op.cond_op(node.ty)
{
if swapped { if swapped {
mem::swap(&mut then, &mut else_); mem::swap(&mut then, &mut else_);
} }
@ -506,6 +502,11 @@ impl<'a> Function<'a> {
} }
Kind::Entry => { Kind::Entry => {
let (ret, mut parama) = self.tys.parama(self.sig.ret); let (ret, mut parama) = self.tys.parama(self.sig.ret);
if let Some(PLoc::Ref(..)) = ret {
self.add_instr(MEM);
}
let mut typs = self.sig.args.args(); let mut typs = self.sig.args.args();
#[expect(clippy::unnecessary_to_owned)] #[expect(clippy::unnecessary_to_owned)]
let mut args = self.nodes[VOID].outputs[ARG_START..].to_owned().into_iter(); let mut args = self.nodes[VOID].outputs[ARG_START..].to_owned().into_iter();
@ -518,10 +519,6 @@ impl<'a> Function<'a> {
} }
} }
if let Some(PLoc::Ref(..)) = ret {
self.add_instr(MEM);
}
self.nodes.reschedule_block(nid, &mut node.outputs); self.nodes.reschedule_block(nid, &mut node.outputs);
for o in node.outputs.into_iter().rev() { for o in node.outputs.into_iter().rev() {
self.emit_node(o); self.emit_node(o);
@ -649,7 +646,7 @@ impl<'a> Env<'a> {
); );
range.end = new; range.end = new;
debug_assert!(range.start < range.end, "{:?}", range); debug_assert!(range.start < range.end, "{:?} {inst} {uinst}", range);
bundle.add(range); bundle.add(range);
}); });

View file

@ -332,21 +332,19 @@ impl<'a> Function<'a> {
Kind::If => { Kind::If => {
self.backrefs[nid as usize] = self.backrefs[prev as usize]; self.backrefs[nid as usize] = self.backrefs[prev as usize];
let &[_, cond] = node.inputs.as_slice() else { unreachable!() }; let &[_, cnd] = node.inputs.as_slice() else { unreachable!() };
let &[mut then, mut else_] = node.outputs.as_slice() else { unreachable!() }; let &[mut then, mut else_] = node.outputs.as_slice() else { unreachable!() };
if let Kind::BinOp { op } = self.nodes[cond].kind if let Some((_, swapped)) = self.nodes.cond_op(cnd) {
&& let Some((_, swapped)) = op.cond_op(node.ty)
{
if swapped { if swapped {
mem::swap(&mut then, &mut else_); mem::swap(&mut then, &mut else_);
} }
let &[_, lhs, rhs] = self.nodes[cond].inputs.as_slice() else { unreachable!() }; let &[_, lhs, rhs] = self.nodes[cnd].inputs.as_slice() else { unreachable!() };
let ops = vec![self.urg(lhs), self.urg(rhs)]; let ops = vec![self.urg(lhs), self.urg(rhs)];
self.add_instr(nid, ops); self.add_instr(nid, ops);
} else { } else {
mem::swap(&mut then, &mut else_); mem::swap(&mut then, &mut else_);
let ops = vec![self.urg(cond)]; let ops = vec![self.urg(cnd)];
self.add_instr(nid, ops); self.add_instr(nid, ops);
} }