diff --git a/lang/README.md b/lang/README.md index ccf6ed73..0e1fa7ec 100644 --- a/lang/README.md +++ b/lang/README.md @@ -1166,3 +1166,18 @@ main := fn(): uint { return *mem } ``` + +#### global_aliasing_overptimization +```hb +var := 0 + +main := fn(): uint { + var = 2 + clobber() + return var +} + +clobber := fn(): void { + var = 0 +} +``` diff --git a/lang/src/son.rs b/lang/src/son.rs index fc4b1be9..75ea7939 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -33,6 +33,8 @@ const ENTRY: Nid = 2; const MEM: Nid = 3; const LOOPS: Nid = 4; const ARG_START: usize = 3; +const DEFAULT_ACLASS: usize = 0; +const GLOBAL_ACLASS: usize = 1; pub mod hbvm; @@ -1819,7 +1821,8 @@ impl ItemCtx { let loops = self.nodes.new_node(ty::Id::VOID, Kind::Loops, [VOID]); debug_assert_eq!(loops, LOOPS); self.nodes.lock(loops); - self.scope.aclasses.push(AClass::new(&mut self.nodes)); + self.scope.aclasses.push(AClass::new(&mut self.nodes)); // DEFAULT + self.scope.aclasses.push(AClass::new(&mut self.nodes)); // GLOBAL } fn finalize(&mut self, stack: &mut Vec, _tys: &Types, _files: &[parser::Ast]) { @@ -2264,6 +2267,7 @@ impl<'a> Codegen<'a> { ty::Kind::Global(global) => { let gl = &self.tys.ins.globals[global as usize]; let value = self.ci.nodes.new_node(gl.ty, Kind::Global { global }, [VOID]); + self.ci.nodes[value].aclass = GLOBAL_ACLASS; Some(Value::ptr(value).ty(gl.ty)) } _ => Some(Value::new(Nid::MAX).ty(decl)), @@ -2296,6 +2300,7 @@ impl<'a> Codegen<'a> { } }; let global = self.ci.nodes.new_node(ty, Kind::Global { global }, [VOID]); + self.ci.nodes[global].aclass = GLOBAL_ACLASS; Some(Value::new(global).ty(ty)) } Expr::Return { pos, val } => { @@ -2365,6 +2370,7 @@ impl<'a> Codegen<'a> { let gl = &self.tys.ins.globals[global as usize]; let value = self.ci.nodes.new_node(gl.ty, Kind::Global { global }, [VOID]); + self.ci.nodes[value].aclass = GLOBAL_ACLASS; Some(Value::ptr(value).ty(gl.ty)) } v => Some(Value::new(Nid::MAX).ty(v.compress())), @@ -2739,7 +2745,7 @@ impl<'a> Codegen<'a> { let mut inps = Vc::from([NEVER]); let arg_base = self.tys.tmp.args.len(); - let mut clobbered_aliases = vec![]; + let mut clobbered_aliases = vec![GLOBAL_ACLASS]; for arg in args { let value = self.expr(arg)?; if let Some(base) = self.tys.base_of(value.ty) { @@ -2764,6 +2770,7 @@ impl<'a> Codegen<'a> { for &clobbered in clobbered_aliases.iter() { let aclass = &mut self.ci.scope.aclasses[clobbered]; + self.ci.nodes.load_loop_aclass(clobbered, aclass, &mut self.ci.loops); inps.push(aclass.last_store.get()); aclass.loads.retain_mut(|load| { if inps.contains(&load.get()) { @@ -2794,10 +2801,13 @@ impl<'a> Codegen<'a> { ); for &clobbered in clobbered_aliases.iter() { - if clobbered == 0 { + if clobbered == DEFAULT_ACLASS { continue; } let aclass = self.ci.scope.aclasses[clobbered].last_store.get(); + if aclass == MEM { + continue; + } self.store_mem(self.ci.nodes[aclass].inputs[2], ty::Id::VOID, VOID); } @@ -2839,7 +2849,7 @@ impl<'a> Codegen<'a> { let mut tys = sig.args.args(); let mut cargs = cargs.iter(); let mut args = args.iter(); - let mut clobbered_aliases = vec![]; + let mut clobbered_aliases = vec![GLOBAL_ACLASS]; while let Some(ty) = tys.next(self.tys) { let carg = cargs.next().unwrap(); let Some(arg) = args.next() else { break }; @@ -2868,6 +2878,7 @@ impl<'a> Codegen<'a> { for &clobbered in clobbered_aliases.iter() { let aclass = &mut self.ci.scope.aclasses[clobbered]; + self.ci.nodes.load_loop_aclass(clobbered, aclass, &mut self.ci.loops); inps.push(aclass.last_store.get()); aclass.loads.retain_mut(|load| { if inps.contains(&load.get()) { @@ -2898,10 +2909,13 @@ impl<'a> Codegen<'a> { ); for &clobbered in clobbered_aliases.iter() { - if clobbered == 0 { + if clobbered == DEFAULT_ACLASS { continue; } let aclass = self.ci.scope.aclasses[clobbered].last_store.get(); + if aclass == MEM { + continue; + } self.store_mem(self.ci.nodes[aclass].inputs[2], ty::Id::VOID, VOID); } @@ -4085,5 +4099,6 @@ mod tests { dead_code_in_loop; infinite_loop_after_peephole; aliasing_overoptimization; + global_aliasing_overptimization; } } diff --git a/lang/tests/son_tests_global_aliasing_overptimization.txt b/lang/tests/son_tests_global_aliasing_overptimization.txt new file mode 100644 index 00000000..5d1a573e --- /dev/null +++ b/lang/tests/son_tests_global_aliasing_overptimization.txt @@ -0,0 +1,19 @@ +clobber: + LRA r1, r0, :var + LI64 r3, 0d + ST r3, r1, 0a, 8h + JALA r0, r31, 0a +main: + ADDI64 r254, r254, -16d + ST r31, r254, 0a, 16h + LRA r32, r0, :var + LI64 r3, 2d + ST r3, r32, 0a, 8h + JAL r31, r0, :clobber + LD r1, r32, 0a, 8h + LD r31, r254, 0a, 16h + ADDI64 r254, r254, 16d + JALA r0, r31, 0a +code size: 166 +ret: 0 +status: Ok(()) diff --git a/lang/tests/son_tests_struct_operators.txt b/lang/tests/son_tests_struct_operators.txt index 0cad319a..37995cd6 100644 --- a/lang/tests/son_tests_struct_operators.txt +++ b/lang/tests/son_tests_struct_operators.txt @@ -1,21 +1,21 @@ main: ADDI64 r254, r254, -64d LI64 r3, 1d - ADDI64 r2, r254, 48d - ST r3, r254, 48a, 8h + ADDI64 r2, r254, 32d + ST r3, r254, 32a, 8h LI64 r6, 2d - ST r6, r254, 56a, 8h + ST r6, r254, 40a, 8h LI64 r6, -3d ADDI64 r5, r254, 0d - ADDI64 r11, r254, 32d + ADDI64 r11, r254, 48d ST r6, r254, 0a, 8h LI64 r6, -4d BMC r2, r11, 16h ST r6, r254, 8a, 8h ADDI64 r3, r5, 16d - LD r9, r254, 40a, 8h + LD r9, r254, 56a, 8h LI64 r8, 4d - LD r10, r254, 32a, 8h + LD r10, r254, 48a, 8h LI64 r11, 3d BMC r2, r3, 16h SUB64 r4, r8, r9