From 0ebb330b29293b2d34a9b2abba90492b8b24ee02 Mon Sep 17 00:00:00 2001 From: Cr0a3 <127748753+Cr0a3@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:08:25 +0000 Subject: [PATCH 1/4] [OPT] implementing #35 --- src/IR/nodes/br.rs | 12 ++++++++++-- tests/Optimizations/const_eval/br1.yl | 28 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/Optimizations/const_eval/br1.yl diff --git a/src/IR/nodes/br.rs b/src/IR/nodes/br.rs index d9ef2a3a..6aec6c9e 100644 --- a/src/IR/nodes/br.rs +++ b/src/IR/nodes/br.rs @@ -110,8 +110,16 @@ impl Ir for BrCond { compiler.compile_br_cond(&self, &block, module) } - fn maybe_inline(&self, _: &HashMap) -> Option> { - None + fn maybe_inline(&self, vars: &HashMap) -> Option> { + if let Some(check) = vars.get(&self.inner1.name) { + let value = check.val() as i64; + + if value == 0 { + Some(Br::new(self.inner3.to_owned())) + } else { + Some(Br::new(self.inner2.to_owned())) + } + } else { None } } fn eval(&self) -> Option> { diff --git a/tests/Optimizations/const_eval/br1.yl b/tests/Optimizations/const_eval/br1.yl new file mode 100644 index 00000000..74e96dd1 --- /dev/null +++ b/tests/Optimizations/const_eval/br1.yl @@ -0,0 +1,28 @@ +# RUN: +cargo run -p ylc -- -in=%s -O -fmt -passes=cp +# IN: + +define i32 @main() { + entry: + %0 = i32 1 + br cond %0 yes, no + + yes: + ret i32 0 + + no: + ret i32 0 +} + +# STDERR: +define i32 @main() { + entry: + %0 = i32 1 + br yes + + yes: + ret i32 0 + + no: + ret i32 0 +} \ No newline at end of file From 4a69b31c315794ba18dcdd3cceb6e31faa1aa790 Mon Sep 17 00:00:00 2001 From: Cr0a3 <127748753+Cr0a3@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:37:00 +0000 Subject: [PATCH 2/4] [OPT] implementing #34 --- src/IR/module.rs | 6 ++- .../Passes/DeadBlockElimination.rs | 45 +++++++++++++++++++ src/Optimizations/Passes/mod.rs | 5 ++- src/Optimizations/mngr.rs | 2 +- src/Optimizations/template.rs | 9 ++-- tests/Optimizations/dbe/dbe0.yl | 23 ++++++++++ tools/ylc/main.rs | 2 + 7 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 src/Optimizations/Passes/DeadBlockElimination.rs create mode 100644 tests/Optimizations/dbe/dbe0.yl diff --git a/src/IR/module.rs b/src/IR/module.rs index 2e212b92..edbbf36a 100644 --- a/src/IR/module.rs +++ b/src/IR/module.rs @@ -147,7 +147,11 @@ impl Module { /// Runs the pass manager over all functions pub fn runPassMngr(&mut self, mngr: PassManager) { for (_, func) in &mut self.funcs { - func.runPassMngr(&mngr) + func.runPassMngr(&mngr); + + for opt in &mngr.passes { + opt.run_func(func); + } } } diff --git a/src/Optimizations/Passes/DeadBlockElimination.rs b/src/Optimizations/Passes/DeadBlockElimination.rs new file mode 100644 index 00000000..7a015f1e --- /dev/null +++ b/src/Optimizations/Passes/DeadBlockElimination.rs @@ -0,0 +1,45 @@ +use crate::Optimizations::Pass; +use crate::IR::{ir::Br, ir::BrCond, BlockId, Var}; + +/// ## Pass DeadBlockElimination
+/// deletes unused blocks +pub(crate) struct DeadBlockElimination { +} + +/// Creates a new DeadBlockElimination pass which is heap allocated +pub fn DeadBlockElimination() -> Box { + Box::from( DeadBlockElimination {} ) +} + +impl Pass for DeadBlockElimination { + fn run_func(&self, func: &mut crate::prelude::Function) { + let mut used_blocks = Vec::new(); + + // CHECK FOR ALL USED BLOCKS + + for block in &func.blocks { + for node in &block.nodes { + if let Some(br) = node.as_any().downcast_ref::>() { + used_blocks.push(br.inner1.name.to_owned()); + } + + if let Some(br) = node.as_any().downcast_ref::>() { + used_blocks.push(br.inner2.name.to_owned()); + used_blocks.push(br.inner3.name.to_owned()); + } + } + } + + // REMOVE UNUSED BLOCKS + + let mut index = 0; + + for block in func.blocks.clone() { + if !used_blocks.contains(&block.name) && index != 0 { // do not remove first block + func.blocks.remove(index); + } + + index += 1; + } + } +} \ No newline at end of file diff --git a/src/Optimizations/Passes/mod.rs b/src/Optimizations/Passes/mod.rs index 46dbb2ea..c9eddce2 100644 --- a/src/Optimizations/Passes/mod.rs +++ b/src/Optimizations/Passes/mod.rs @@ -2,6 +2,9 @@ mod ConstantEvaluation; #[allow(hidden_glob_reexports)] mod DeadNodeElimination; +#[allow(hidden_glob_reexports)] +mod DeadBlockElimination; pub use ConstantEvaluation::*; -pub use DeadNodeElimination::*; \ No newline at end of file +pub use DeadNodeElimination::*; +pub use DeadBlockElimination::*; \ No newline at end of file diff --git a/src/Optimizations/mngr.rs b/src/Optimizations/mngr.rs index 6a3e3a3c..9c397f04 100644 --- a/src/Optimizations/mngr.rs +++ b/src/Optimizations/mngr.rs @@ -4,7 +4,7 @@ use super::Pass; /// The manager of all passes (PassManager) pub struct PassManager { - passes: VecDeque>, + pub(crate) passes: VecDeque>, } impl PassManager { diff --git a/src/Optimizations/template.rs b/src/Optimizations/template.rs index 627f0197..210b3aba 100644 --- a/src/Optimizations/template.rs +++ b/src/Optimizations/template.rs @@ -1,7 +1,10 @@ -use crate::IR::Block; +use crate::IR::{Block, Function}; /// The trait all Passes need to implement pub trait Pass { - /// Returns the pass - fn run(&self, block: &mut Block); + /// Runs the pass on a block + fn run(&self, _block: &mut Block) {} + + /// Runs the pass on the entire function + fn run_func(&self, _func: &mut Function) {} } \ No newline at end of file diff --git a/tests/Optimizations/dbe/dbe0.yl b/tests/Optimizations/dbe/dbe0.yl new file mode 100644 index 00000000..54054865 --- /dev/null +++ b/tests/Optimizations/dbe/dbe0.yl @@ -0,0 +1,23 @@ +# RUN: +cargo run -p ylc -- -in=%s -passes=dbe -fmt +# IN: + +define i32 @main() { + entry: + br ret + + ret: + ret i32 5 + + should_be_removed: + ret i32 1 +} + +# STDOUT: +define i32 @main() { + entry: + br ret + + ret: + ret i32 5 +} \ No newline at end of file diff --git a/tools/ylc/main.rs b/tools/ylc/main.rs index d813ab61..5ec18c1d 100644 --- a/tools/ylc/main.rs +++ b/tools/ylc/main.rs @@ -170,6 +170,7 @@ fn main() -> Result<(), Box> { let pass = match pass.to_lowercase().as_str() { "cp" | "const_eval" | "const_evaluation" | "const-eval" | "const-evaluation" => Some( Passes::ConstantEvaluation() ), "dne" | "dead_node" | "dead_node_elim" | "dead-node" | "dead-node-elimination" => Some( Passes::DeadNodeElimination() ), + "dbe" | "dead_block" | "dead_block_elim" | "dead-block" | "dead-block-elimination" => Some( Passes::DeadBlockElimination() ), _ => {eprintln!("unkown pass: {}", pass); None }, }; @@ -183,6 +184,7 @@ fn main() -> Result<(), Box> { let mut opts = PassManager::new(); opts.add( Passes::ConstantEvaluation() ); + opts.add( Passes::DeadBlockElimination() ); opts.add( Passes::DeadNodeElimination() ); module.runPassMngr(opts); From 0ac65aead7d411be1512a5b0273ee782f1fbf75d Mon Sep 17 00:00:00 2001 From: Cr0a3 <127748753+Cr0a3@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:53:05 +0000 Subject: [PATCH 3/4] [FIX] fixed function call offsets --- src/Obj/wrapper.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Obj/wrapper.rs b/src/Obj/wrapper.rs index 4b70bee5..030c648b 100644 --- a/src/Obj/wrapper.rs +++ b/src/Obj/wrapper.rs @@ -346,9 +346,12 @@ impl ObjectBuilder { for link in &self.links { let (_, off, _, _, _, _) = syms.get(&link.from).expect("expectd valid link source"); - let (_, _, to_sym, _, _, _) = syms.get(&link.to).expect("expected valid link destination"); + let (_, _, to_sym, decl, _, _) = syms.get(&link.to).expect("expected valid link destination"); - let addend = 0; + let addend = match decl { + Decl::Function => 4, + _ => 0, + }; let offset = -3; obj.add_relocation(secText, Relocation { From 600d2bf4f8b1ee021d92ee47a25fdc45293aef0b Mon Sep 17 00:00:00 2001 From: Cr0a3 <127748753+Cr0a3@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:54:40 +0000 Subject: [PATCH 4/4] [TESTS] commented out jit absolute adr test cuz it is unsuported --- src/Target/x64/abs_jit.rs | 2 ++ tests/jit.rs | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Target/x64/abs_jit.rs b/src/Target/x64/abs_jit.rs index 72463ddb..defed286 100644 --- a/src/Target/x64/abs_jit.rs +++ b/src/Target/x64/abs_jit.rs @@ -63,6 +63,8 @@ impl AbsSymDealer for X64AbsSymDealer { for fix in fixup { code.insert(pos - bytes_to_remove, fix); } + + todo!("unsupported"); } fn dbg(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/tests/jit.rs b/tests/jit.rs index 0068df16..08753c0c 100644 --- a/tests/jit.rs +++ b/tests/jit.rs @@ -69,6 +69,9 @@ pub fn call() -> Result<(), Box> { Ok(()) } +/* + +// NOT YET SUPPORTED #[no_mangle] extern "C" fn custom_func(ls: i32, rs: i32) -> i32 { @@ -105,4 +108,4 @@ pub fn extern_symbol() -> Result<(), Box> { } Ok(()) -} \ No newline at end of file +}*/ \ No newline at end of file