Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate new inst #69

Merged
merged 84 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
cfd27cf
Add verifier crate (#63)
emhane Sep 15, 2024
2ae935e
Rename `Value` to `ValueId`
Y-Nak Sep 16, 2024
20598f2
Rename `ValueData` to `Value`
Y-Nak Sep 16, 2024
20df298
Rename `Block` to `BlockId`
Y-Nak Sep 16, 2024
0b8dbd7
Rename `BlockData` to `Block`
Y-Nak Sep 16, 2024
0abd655
Define `InstId`
Y-Nak Sep 16, 2024
d467fb6
Add `value_` module temporarily for the inst transition
Y-Nak Sep 16, 2024
652f7ec
Add `dfg_` module temporarily for the inst transition
Y-Nak Sep 16, 2024
81b5955
Use `value_::ValueId` instead of `value::ValueId`
Y-Nak Sep 18, 2024
ea01ff2
Add `function_` module temporarily for the inst transition
Y-Nak Sep 18, 2024
ddb0724
Finish inst transition for IR structures
Y-Nak Sep 19, 2024
be13093
Refine `IrWrite` trait for the inst transition
Y-Nak Sep 21, 2024
bf52beb
Implement `IrWrite` to instructions
Y-Nak Sep 21, 2024
b0ca05a
Fix tests in graphviz module
Y-Nak Sep 21, 2024
976d21c
Remove `IrWrite`, add `DisplayWithFunc`
Y-Nak Sep 24, 2024
87b0a48
[wip] Finish refactoring `ir_writer`
Y-Nak Sep 24, 2024
2705241
Refine `Isa` definition
Y-Nak Sep 25, 2024
0a5ffba
Fix a bug in `InstDowncast` implementation
Y-Nak Sep 25, 2024
05917eb
Fix missing pred analyzation in ssa builder
Y-Nak Sep 25, 2024
9e7fbf2
Fix `ir_writer`
Y-Nak Sep 25, 2024
da71923
Fix `BranchInfo::iter_dests`
Y-Nak Sep 25, 2024
a51732c
Fix test cases
Y-Nak Sep 25, 2024
255e0bf
Fix graphviz module
Y-Nak Sep 25, 2024
ba8267d
Remove old instruction defs
Y-Nak Sep 25, 2024
9fc00f3
Make it mandatory for inst set to include jump inst
Y-Nak Sep 25, 2024
e60a162
Add `BranchInfoMut`
Y-Nak Sep 25, 2024
bfb967a
Add some utility methods to build IR
Y-Nak Sep 25, 2024
da01ba0
Inst transition in critical edge splitter
Y-Nak Sep 25, 2024
d2307dd
Inst transition in dom tree
Y-Nak Sep 25, 2024
5ff17a5
Inst transition in licm
Y-Nak Sep 25, 2024
15805c0
Inst rewrite in post domtree
Y-Nak Sep 25, 2024
0996a28
Inst rewrite in loop analysis
Y-Nak Sep 26, 2024
c249779
Inst rewrite in ADCE
Y-Nak Sep 26, 2024
d29b340
Interpret for arith insts
Y-Nak Sep 26, 2024
8fe0f55
`Interpret` for cmp insts
Y-Nak Sep 27, 2024
4314609
`Interpret` for cast insts
Y-Nak Sep 27, 2024
a46c3a9
`Interpret` for logical insts
Y-Nak Sep 27, 2024
50d8156
[WIP][Experimental] Subset by comprehension using trait as property
Y-Nak Sep 27, 2024
a8eb77e
Subset by comprehension using trait as property
Y-Nak Sep 28, 2024
0c0c80d
Rewrite `BranchInfo` by `inst_prop`
Y-Nak Sep 28, 2024
e91e8a7
Enable to use `inst_prop` outside of `sonatina-ir`
Y-Nak Sep 30, 2024
8ba2d1f
Enable to use `&mut self` in `inst_prop`
Y-Nak Sep 30, 2024
c169d49
Extend `Branch` trait
Y-Nak Sep 30, 2024
ecf8bd8
Define `Interpret` and `Interpretable` with `inst_prop`
Y-Nak Sep 30, 2024
c335e9d
Inst rewrite in sccp
Y-Nak Sep 30, 2024
dd0e27b
Farewell to GVN, insn-simplify and isle
Y-Nak Sep 30, 2024
e103e64
Finish inst transition in codegen
Y-Nak Oct 1, 2024
792831e
Finish inst transition in verifier
Y-Nak Oct 1, 2024
4bf6913
Modify `Interpret` definition
Y-Nak Oct 4, 2024
521e5eb
Move `intepret` module into `ir`
Y-Nak Oct 4, 2024
5b59e36
Implement `Interpret` for control flow related instructions
Y-Nak Oct 4, 2024
27294dc
Fix missing `set_action` in some instructions
Y-Nak Oct 4, 2024
f6f93df
Implement new interpreter
Y-Nak Oct 4, 2024
63d7b8e
Add `size_of` method in `TypeLayout`
Y-Nak Oct 5, 2024
b2780ea
Implement `Interpret` for `Load/Store`
Y-Nak Oct 5, 2024
0e25581
Obtain Endianness from isa
Y-Nak Oct 5, 2024
6123dfe
Finish inst transition in interpreter
Y-Nak Oct 5, 2024
92d25cb
Refactor `inst_prop`
Y-Nak Oct 7, 2024
2ea6a5c
Refactor `Branch` trait
Y-Nak Oct 7, 2024
4982ce9
Modify pest file for new inst
Y-Nak Oct 7, 2024
aeed76a
Syntax for new inst
Y-Nak Oct 7, 2024
4d6992c
Parser error for new inst
Y-Nak Oct 7, 2024
8cb0643
Implement `InstBuild` for basic instructions
Y-Nak Oct 7, 2024
dbdda8a
Implement `InstBuild` for evm specific instructions
Y-Nak Oct 7, 2024
5cb9b38
Refine `Inst` derive macro
Y-Nak Oct 7, 2024
5d753ac
Extend `inst_set_base` macro to geenrate a macro that match string to…
Y-Nak Oct 8, 2024
9d3958d
Finish inst transition in parser
Y-Nak Oct 8, 2024
104d238
Redefine triples
Y-Nak Oct 8, 2024
83bb6c3
Support defining `inst_prop` for all instructions
Y-Nak Oct 9, 2024
593bb5f
Add doc for macros
Y-Nak Oct 9, 2024
2a1af78
use `io::Write` intensively
Y-Nak Oct 9, 2024
14b39a1
Finish transition to new inst
Y-Nak Oct 10, 2024
7a57c4d
Make clippy happy
Y-Nak Oct 10, 2024
b29ddbc
Fix parser
Y-Nak Oct 10, 2024
476039a
Change type name prefix to `@`
Y-Nak Oct 11, 2024
60ffc1d
Change some inst test format for more precise information
Y-Nak Oct 11, 2024
131ca78
Fix bug in licm
Y-Nak Oct 11, 2024
c3670ad
Make clippy satisfy
Y-Nak Oct 11, 2024
073e003
Resolve verifier confilict
Y-Nak Oct 11, 2024
9aec926
Rename `void` to `unit`
Y-Nak Oct 11, 2024
d1ff92d
Remove `dyn-clone` dependency
Y-Nak Oct 11, 2024
3d3284d
Port old tests of interpreter
Y-Nak Oct 11, 2024
b3b56e5
Implement `Interpret` for Gep
Y-Nak Oct 11, 2024
8ca415a
Hide spans from ast debug output to fix insta tests on windows part 2
Y-Nak Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ smallvec = "1.7.0"
rustc-hash = "2.0.0"
sonatina-ir = { path = "../ir", version = "0.0.3-alpha" }
sonatina-triple = { path = "../triple", version = "0.0.3-alpha" }
sonatina-macros = { path = "../macros", version = "0.0.3-alpha" }
149 changes: 89 additions & 60 deletions crates/codegen/src/critical_edge.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use sonatina_ir::{func_cursor::FuncCursor, ControlFlowGraph};

use sonatina_ir::{
func_cursor::{CursorLocation, InsnInserter},
insn::InsnData,
Block, Function, Insn,
func_cursor::{CursorLocation, FuncCursor, InstInserter},
inst::control_flow::Jump,
BlockId, ControlFlowGraph, Function, InstId,
};

#[derive(Debug)]
Expand All @@ -28,8 +26,8 @@ impl CriticalEdgeSplitter {
self.clear();

for block in func.layout.iter_block() {
if let Some(last_insn) = func.layout.last_insn_of(block) {
self.add_critical_edges(last_insn, func, cfg);
if let Some(last_inst) = func.layout.last_inst_of(block) {
self.add_critical_edges(last_inst, func, cfg);
}
}

Expand All @@ -43,47 +41,55 @@ impl CriticalEdgeSplitter {
self.critical_edges.clear();
}

fn add_critical_edges(&mut self, insn: Insn, func: &Function, cfg: &ControlFlowGraph) {
let branch_info = func.dfg.analyze_branch(insn);
if branch_info.dests_num() < 2 {
fn add_critical_edges(&mut self, inst_id: InstId, func: &Function, cfg: &ControlFlowGraph) {
let Some(branch_info) = func.dfg.branch_info(inst_id) else {
return;
};

if branch_info.num_dests() < 2 {
return;
}

for dest in branch_info.iter_dests() {
for dest in branch_info.dests() {
if cfg.pred_num_of(dest) > 1 {
self.critical_edges.push(CriticalEdge::new(insn, dest));
self.critical_edges.push(CriticalEdge::new(inst_id, dest));
}
}
}

fn split_edge(&mut self, edge: CriticalEdge, func: &mut Function, cfg: &mut ControlFlowGraph) {
let insn = edge.insn;
let inst = edge.inst;
let original_dest = edge.to;
let source_block = func.layout.insn_block(insn);
let source_block = func.layout.inst_block(inst);

// Create a new block that contains only a jump insn to the destinating block of the
// critical edge.
// Create a new block that contains only a jump inst to the destinating block of
// the critical edge.
let inserted_dest = func.dfg.make_block();
let jump = func.dfg.make_insn(InsnData::jump(original_dest));
let mut cursor = InsnInserter::at_location(CursorLocation::BlockTop(original_dest));
let jump = Jump::new(func.dfg.inst_set().jump(), original_dest);
let mut cursor = InstInserter::at_location(CursorLocation::BlockTop(original_dest));
cursor.append_block(func, inserted_dest);
cursor.set_location(CursorLocation::BlockTop(inserted_dest));
cursor.append_insn(func, jump);
cursor.append_inst_data(func, jump);

// Rewrite branch destination to the new block.
func.dfg
.rewrite_branch_dest(insn, original_dest, inserted_dest);
.rewrite_branch_dest(inst, original_dest, inserted_dest);
self.modify_cfg(cfg, source_block, original_dest, inserted_dest);
self.modify_phi_blocks(func, original_dest, inserted_dest);
}

fn modify_phi_blocks(&self, func: &mut Function, original_dest: Block, inserted_dest: Block) {
for insn in func.layout.iter_insn(original_dest) {
if !func.dfg.is_phi(insn) {
fn modify_phi_blocks(
&self,
func: &mut Function,
original_dest: BlockId,
inserted_dest: BlockId,
) {
for inst in func.layout.iter_inst(original_dest) {
let Some(phi) = func.dfg.cast_phi_mut(inst) else {
continue;
}
};

for block in func.dfg.phi_blocks_mut(insn) {
for (_, block) in phi.args_mut() {
if *block == original_dest {
*block = inserted_dest;
}
Expand All @@ -94,9 +100,9 @@ impl CriticalEdgeSplitter {
fn modify_cfg(
&self,
cfg: &mut ControlFlowGraph,
source_block: Block,
original_dest: Block,
inserted_dest: Block,
source_block: BlockId,
original_dest: BlockId,
inserted_dest: BlockId,
) {
cfg.remove_edge(source_block, original_dest);
cfg.add_edge(source_block, inserted_dest);
Expand All @@ -106,38 +112,51 @@ impl CriticalEdgeSplitter {

#[derive(Debug)]
struct CriticalEdge {
insn: Insn,
to: Block,
inst: InstId,
to: BlockId,
}

impl CriticalEdge {
fn new(insn: Insn, to: Block) -> Self {
Self { insn, to }
fn new(inst: InstId, to: BlockId) -> Self {
Self { inst, to }
}
}

#[cfg(test)]
mod tests {
use sonatina_ir::{
builder::test_util::*,
inst::{
arith::Add,
control_flow::{Br, BrTable, Phi, Return},
},
isa::Isa,
Type,
};

use super::*;
use sonatina_ir::{builder::test_util::*, Type};

#[test]
fn critical_edge_basic() {
let mut builder = test_func_builder(&[], Type::Void);
let (evm, mut builder) = test_func_builder(&[], Type::Unit);
let is = evm.inst_set();

let a = builder.append_block();
let b = builder.append_block();
let c = builder.append_block();

builder.switch_to_block(a);
let v0 = builder.make_imm_value(1i32);
builder.br(v0, c, b);
let br = Br::new(is, v0, c, b);
builder.insert_inst_no_result(br);

builder.switch_to_block(b);
builder.jump(c);
let jump = Jump::new(is, c);
builder.insert_inst_no_result(jump);

builder.switch_to_block(c);
builder.ret(None);
let ret = Return::new(is, None);
builder.insert_inst_no_result(ret);

builder.seal_all();
let mut module = builder.finish().build();
Expand All @@ -149,7 +168,7 @@ mod tests {

assert_eq!(
dump_func(&module, func_ref),
"func public %test_func() -> void {
"func public %test_func() -> unit {
block0:
br 1.i32 block3 block1;

Expand All @@ -175,7 +194,8 @@ mod tests {
#[test]
#[allow(clippy::many_single_char_names)]
fn critical_edge_to_same_block() {
let mut builder = test_func_builder(&[], Type::Void);
let (evm, mut builder) = test_func_builder(&[], Type::Unit);
let is = evm.inst_set();

let a = builder.append_block();
let b = builder.append_block();
Expand All @@ -185,19 +205,24 @@ mod tests {

builder.switch_to_block(a);
let v0 = builder.make_imm_value(1i8);
builder.br(v0, d, b);
let br = Br::new(is, v0, d, b);
builder.insert_inst_no_result(br);

builder.switch_to_block(b);
builder.jump(c);
let jump = Jump::new(is, c);
builder.insert_inst_no_result(jump);

builder.switch_to_block(c);
builder.br(v0, e, d);
let br = Br::new(is, v0, e, d);
builder.insert_inst_no_result(br);

builder.switch_to_block(d);
builder.ret(None);
let ret = Return::new(is, None);
builder.insert_inst_no_result(ret);

builder.switch_to_block(e);
builder.ret(None);
let ret = Return::new(is, None);
builder.insert_inst_no_result(ret);

builder.seal_all();
let mut module = builder.finish().build();
Expand All @@ -209,7 +234,7 @@ mod tests {

assert_eq!(
dump_func(&module, func_ref),
"func public %test_func() -> void {
"func public %test_func() -> unit {
block0:
br 1.i8 block5 block1;

Expand Down Expand Up @@ -243,24 +268,26 @@ mod tests {

#[test]
fn critical_edge_phi() {
let mut builder = test_func_builder(&[], Type::Void);
let (evm, mut builder) = test_func_builder(&[], Type::Unit);
let is = evm.inst_set();

let a = builder.append_block();
let b = builder.append_block();
let c = builder.append_block();

builder.switch_to_block(a);
let v1 = builder.make_imm_value(1i8);
builder.jump(b);
builder.insert_inst_no_result_with(|| Jump::new(is, b));

builder.switch_to_block(b);
let phi_value = builder.phi(Type::I8, &[(v1, a)]);
let v2 = builder.add(phi_value, v1);
builder.append_phi_arg(phi_value, v2, b);
builder.br(phi_value, c, b);
let phi_res = builder.insert_inst_with(|| Phi::new(is, vec![(v1, a)]), Type::I8);
let add_res = builder.insert_inst_with(|| Add::new(is, phi_res, v1), Type::I8);

builder.append_phi_arg(phi_res, add_res, b);
builder.insert_inst_no_result_with(|| Br::new(is, phi_res, c, b));

builder.switch_to_block(c);
builder.ret(None);
builder.insert_inst_no_result_with(|| Return::new(is, None));

builder.seal_all();
let mut module = builder.finish().build();
Expand All @@ -272,7 +299,7 @@ mod tests {

assert_eq!(
dump_func(&module, func_ref),
"func public %test_func() -> void {
"func public %test_func() -> unit {
block0:
jump block1;

Expand All @@ -299,7 +326,8 @@ mod tests {

#[test]
fn critical_edge_br_table() {
let mut builder = test_func_builder(&[], Type::Void);
let (evm, mut builder) = test_func_builder(&[], Type::Unit);
let is = evm.inst_set();

let a = builder.append_block();
let b = builder.append_block();
Expand All @@ -309,22 +337,23 @@ mod tests {

builder.switch_to_block(a);
let cond = builder.make_imm_value(true);
builder.br(cond, b, e);
builder.insert_inst_no_result_with(|| Br::new(is, cond, b, e));

builder.switch_to_block(b);
let v0 = builder.make_imm_value(0i32);
let v1 = builder.make_imm_value(1i32);
let v2 = builder.make_imm_value(2i32);
builder.br_table(v0, Some(c), &[(v1, d), (v2, e)]);
builder
.insert_inst_no_result_with(|| BrTable::new(is, v0, Some(c), vec![(v1, d), (v2, e)]));

builder.switch_to_block(c);
builder.jump(b);
builder.insert_inst_no_result_with(|| Jump::new(is, b));

builder.switch_to_block(d);
builder.ret(None);
builder.insert_inst_no_result_with(|| Return::new(is, None));

builder.switch_to_block(e);
builder.ret(None);
builder.insert_inst_no_result_with(|| Return::new(is, None));

builder.seal_all();
let mut module = builder.finish().build();
Expand All @@ -336,7 +365,7 @@ mod tests {

assert_eq!(
dump_func(&module, func_ref),
"func public %test_func() -> void {
"func public %test_func() -> unit {
block0:
br 1.i1 block5 block6;

Expand Down
Loading