Add a readonly flag for loads (#562)

* Add readonly MemFlag

* Add readonly flag verifier check

* Make global loads readonly

* Fix gvn to consider readonly loads
This commit is contained in:
Lachlan Sneff
2018-10-23 00:50:09 -04:00
committed by Dan Gohman
parent 3ec21459c5
commit 586a8835e9
9 changed files with 120 additions and 16 deletions

View File

@@ -18,10 +18,19 @@ fn trivially_unsafe_for_gvn(opcode: Opcode) -> bool {
|| opcode.can_trap()
|| opcode.other_side_effects()
|| opcode.can_store()
|| opcode.can_load()
|| opcode.writes_cpu_flags()
}
/// Test that, if the specified instruction is a load, it doesn't have the `readonly` memflag.
fn is_load_and_not_readonly(inst_data: &InstructionData) -> bool {
match *inst_data {
InstructionData::Load { flags, .. } | InstructionData::LoadComplex { flags, .. } => {
!flags.readonly()
}
_ => inst_data.opcode().can_load(),
}
}
/// Wrapper around `InstructionData` which implements `Eq` and `Hash`
#[derive(Clone)]
struct HashKey<'a, 'f: 'a> {
@@ -91,14 +100,23 @@ pub fn do_simple_gvn(func: &mut Function, domtree: &mut DominatorTree) {
let func = Ref::map(pos.borrow(), |pos| &pos.func);
let opcode = func.dfg[inst].opcode();
if opcode.is_branch() && !opcode.is_terminator() {
scope_stack.push(func.layout.next_inst(inst).unwrap());
visible_values.increment_depth();
}
if trivially_unsafe_for_gvn(opcode) {
continue;
}
let inst_data = func.dfg[inst].clone();
// These are split up to separate concerns.
if is_load_and_not_readonly(&inst_data) {
continue;
}
let ctrl_typevar = func.dfg.ctrl_typevar(inst);
let key = HashKey {
inst: func.dfg[inst].clone(),