Skip to content

Commit eeaf800

Browse files
committed
First load store analysis pass test
1 parent 7a3940e commit eeaf800

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

zjit/src/hir.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4604,6 +4604,63 @@ impl Function {
46044604
self.infer_types();
46054605
}
46064606

4607+
fn optimize_load_store(&mut self) {
4608+
// TODO: Add specific tests for load_store
4609+
// TODO: Add dead store elimination
4610+
// The key for the hashmap should be type and offset, with a value of value
4611+
// This lets us to index in with both load and store fields since insn_ids are probably always going to be different and we can't easily match on that
4612+
// So... how do we match against and store the enum label without all the data?? not sure yet :/
4613+
let mut compile_time_heap: HashMap<(InsnId, i32), InsnId> = HashMap::new();
4614+
for block in self.rpo() {
4615+
let old_insns = std::mem::take(&mut self.blocks[block.0].insns);
4616+
let mut new_insns = vec![];
4617+
for insn_id in old_insns {
4618+
let replacement_insn: InsnId = match self.find(insn_id) {
4619+
Insn::StoreField { recv, offset, val, .. } => {
4620+
let key = (recv, offset);
4621+
4622+
let heap_entry = compile_time_heap.get(&key).copied();
4623+
// TODO(Jacob): Switch from actual to partial equality
4624+
if Some(val) == heap_entry {
4625+
// TODO(Jacob): Add TBAA to avoid removing so many entries
4626+
compile_time_heap.retain(|(_, off), _| *off == offset);
4627+
// If the value is already stored, short circuit and don't add an instruction to the block
4628+
continue
4629+
}
4630+
// TODO(Jacob): Add TBAA to avoid removing so many entries
4631+
compile_time_heap.retain(|(_, off), _| *off == offset);
4632+
compile_time_heap.insert(key, val);
4633+
insn_id
4634+
},
4635+
Insn::LoadField { recv, offset, .. } => {
4636+
let key = (recv, offset);
4637+
match compile_time_heap.entry(key) {
4638+
std::collections::hash_map::Entry::Occupied(entry) => {
4639+
// If the value is already saved, we can't short circuit like we can with a store.
4640+
// However, we can avoid the load with a reference to the representative to the union from SSA.
4641+
self.make_equal_to(insn_id, *entry.get());
4642+
}
4643+
std::collections::hash_map::Entry::Vacant(_) => {
4644+
// TODO(Jacob): Make sure this is correct, could be wrong?
4645+
compile_time_heap.insert(key, insn_id);
4646+
}
4647+
}
4648+
insn_id
4649+
},
4650+
insn => {
4651+
// If an instruction affects memory and we haven't modeled it, the compile_time_heap is invalidated
4652+
if insn.effects_of().includes(Effect::write(abstract_heaps::Memory)) {
4653+
compile_time_heap.clear();
4654+
}
4655+
insn_id
4656+
}
4657+
};
4658+
new_insns.push(replacement_insn);
4659+
}
4660+
self.blocks[block.0].insns = new_insns;
4661+
}
4662+
}
4663+
46074664
/// Fold a binary operator on fixnums.
46084665
fn fold_fixnum_bop(&mut self, insn_id: InsnId, left: InsnId, right: InsnId, f: impl FnOnce(Option<i64>, Option<i64>) -> Option<i64>) -> InsnId {
46094666
f(self.type_of(left).fixnum_value(), self.type_of(right).fixnum_value())
@@ -5450,6 +5507,7 @@ impl Function {
54505507
run_pass!(inline);
54515508
run_pass!(optimize_getivar);
54525509
run_pass!(optimize_c_calls);
5510+
run_pass!(optimize_load_store);
54535511
run_pass!(fold_constants);
54545512
run_pass!(clean_cfg);
54555513
run_pass!(remove_redundant_patch_points);

0 commit comments

Comments
 (0)