Skip to content

Commit

Permalink
Fix wrong exit blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak committed Oct 13, 2024
1 parent 2d5c0a7 commit 211b909
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 22 deletions.
4 changes: 4 additions & 0 deletions src/bitset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ impl<const SIZE: usize> Bitset<SIZE> {
pub const fn is_empty(&self) -> bool {
self.len() == 0
}

pub const fn clear(&mut self) {
self.0 = [0; SIZE];
}
}

impl<const SIZE: usize> Default for Bitset<SIZE> {
Expand Down
42 changes: 27 additions & 15 deletions src/jit/assembler/block_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,17 @@ impl<'a> BlockAsm<'a> {
}
}

fn resolve_actual_block_count(already_processed: &mut NoHashSet<usize>, basic_blocks: &mut [BasicBlock], block_i: usize, count: &mut usize) {
*count += 1;
already_processed.insert(block_i);
for i in 0..basic_blocks[block_i].exit_blocks.len() {
let exit_i = basic_blocks[block_i].exit_blocks[i];
if !already_processed.contains(&exit_i) {
Self::resolve_actual_block_count(already_processed, basic_blocks, exit_i, count);
}
}
}

fn resolve_df_ordering(
already_processed: &mut Bitset<{ 1024 / 32 }>,
completed: &mut Bitset<{ 1024 / 32 }>,
Expand Down Expand Up @@ -697,7 +708,7 @@ impl<'a> BlockAsm<'a> {
*completed += block_i;
}

fn assemble_basic_blocks(&mut self, block_start_pc: u32, thumb: bool) -> (Vec<BasicBlock>, Vec<usize>) {
fn assemble_basic_blocks(&mut self, block_start_pc: u32, thumb: bool) -> (Vec<BasicBlock>, Vec<usize>, NoHashSet<usize>) {
for i in 0..self.buf.insts.len() {
self.insts_link.insert_end(i);
}
Expand Down Expand Up @@ -737,7 +748,7 @@ impl<'a> BlockAsm<'a> {
}
last_label = None;
}
BlockInstKind::Call { has_return: false, .. } | BlockInstKind::Epilogue { .. } => {
BlockInstKind::Call { has_return: false, .. } | BlockInstKind::CallCommon { has_return: false, .. } | BlockInstKind::Epilogue { .. } => {
basic_blocks.push(BasicBlock::new(self, basic_block_start, current_node));
basic_block_start = BlockInstList::deref(current_node).next;
if let Some(last_label) = last_label {
Expand Down Expand Up @@ -773,16 +784,13 @@ impl<'a> BlockAsm<'a> {
}
}
// Don't add exit when last command in basic block is a breakout
BlockInstKind::Call { has_return: false, .. } | BlockInstKind::Epilogue { .. } => {
if i + 1 < basic_blocks_len {
basic_block.exit_blocks.push(i + 1);
}
}
_ => {
if i + 1 < basic_blocks_len {
BlockInstKind::Call { has_return: false, .. } | BlockInstKind::CallCommon { has_return: false, .. } | BlockInstKind::Epilogue { .. } => {
if cond != Cond::AL && i + 1 < basic_blocks_len {
basic_block.exit_blocks.push(i + 1);
}
}
_ if i + 1 < basic_blocks_len => basic_block.exit_blocks.push(i + 1),
_ => {}
}
}

Expand Down Expand Up @@ -828,11 +836,15 @@ impl<'a> BlockAsm<'a> {
basic_block.remove_dead_code(self);
}

let mut reachable_blocks = NoHashSet::default();
let mut actual_block_count = 0;
Self::resolve_actual_block_count(&mut reachable_blocks, &mut basic_blocks, 0, &mut actual_block_count);

let mut df_already_processed = Bitset::<{ 1024 / 32 }>::new();
let mut df_completed = Bitset::<{ 1024 / 32 }>::new();
let mut df_ordering = vec![0; basic_blocks_len];
let mut df_ordering = vec![0; actual_block_count];
let mut df_ordering_start = 0;
let mut df_ordering_end = basic_blocks_len - 1;
let mut df_ordering_end = actual_block_count - 1;
Self::resolve_df_ordering(
&mut df_already_processed,
&mut df_completed,
Expand All @@ -843,7 +855,7 @@ impl<'a> BlockAsm<'a> {
&mut df_ordering_end,
);

(basic_blocks, df_ordering)
(basic_blocks, df_ordering, reachable_blocks)
}

fn assemble_intervals(basic_blocks: &[BasicBlock], ordering: &[usize]) -> NoHashMap<u16, (usize, usize)> {
Expand Down Expand Up @@ -872,7 +884,7 @@ impl<'a> BlockAsm<'a> {
}

pub fn emit_opcodes(&mut self, block_start_pc: u32, thumb: bool) -> usize {
let (mut basic_blocks, basic_blocks_order) = self.assemble_basic_blocks(block_start_pc, thumb);
let (mut basic_blocks, basic_blocks_order, reachable_blocks) = self.assemble_basic_blocks(block_start_pc, thumb);

if IS_DEBUG && unsafe { BLOCK_LOG } {
for (i, basic_block) in basic_blocks.iter().enumerate() {
Expand Down Expand Up @@ -919,7 +931,7 @@ impl<'a> BlockAsm<'a> {
}

for (i, basic_block) in basic_blocks.iter_mut().enumerate() {
if unlikely(i != 0 && basic_block.enter_blocks.is_empty()) {
if unlikely(i != 0 && !reachable_blocks.contains(&i)) {
continue;
}
self.buf.reg_allocator.init_inputs(*basic_block.get_required_inputs());
Expand All @@ -944,7 +956,7 @@ impl<'a> BlockAsm<'a> {
for (i, basic_block) in basic_blocks.iter().enumerate() {
let opcodes_len = self.buf.opcodes.len();
self.buf.block_opcode_offsets.push(opcodes_len);
if unlikely(i != 0 && basic_block.enter_blocks.is_empty()) {
if unlikely(i != 0 && !reachable_blocks.contains(&i)) {
continue;
}
let opcodes = basic_block.emit_opcodes(self, opcodes_len, used_host_regs);
Expand Down
6 changes: 3 additions & 3 deletions src/jit/emitter/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
block_asm.load_u32(guest_pc_reg, block_asm.thread_regs_addr_reg, Reg::PC as u32 * 4);
self.emit_branch_return_stack_common(block_asm, guest_pc_reg);
block_asm.free_reg(guest_pc_reg);
} else {
self.emit_branch_out_metadata(block_asm);
block_asm.epilogue();
}

self.emit_branch_out_metadata(block_asm);
block_asm.epilogue();
}

block_asm.end_cond_block();
Expand Down
6 changes: 3 additions & 3 deletions src/jit/emitter/thumb/emit_thumb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
block_asm.load_u32(guest_pc_reg, block_asm.thread_regs_addr_reg, Reg::PC as u32 * 4);
self.emit_branch_return_stack_common(block_asm, guest_pc_reg);
block_asm.free_reg(guest_pc_reg);
} else {
self.emit_branch_out_metadata(block_asm);
block_asm.epilogue();
}

self.emit_branch_out_metadata(block_asm);
block_asm.epilogue();
}
}
}
2 changes: 1 addition & 1 deletion src/jit/jit_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ fn emit_code_block_internal<const CPU: CpuType, const THUMB: bool>(asm: &mut Jit
}

let jit_entry = {
// unsafe { BLOCK_LOG = guest_pc == 0x206d6d8 };
// unsafe { BLOCK_LOG = guest_pc == 0x20027ac };

let mut block_asm = asm.new_block_asm(false);

Expand Down

0 comments on commit 211b909

Please sign in to comment.