about summary refs log tree commit diff
path: root/src/optimize/stack2reg.rs
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2019-12-28 17:51:22 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2019-12-31 15:56:28 +0100
commitdf7f68236c7f64449e4b236cd95fb30c53f4cbec (patch)
tree1e2c967321739fc44be18995ef7a0b17c181f982 /src/optimize/stack2reg.rs
parent6320c65484b69b9141d9e47781a2e1b086be743a (diff)
Remove stack_store without following stack_load
Diffstat (limited to 'src/optimize/stack2reg.rs')
-rw-r--r--src/optimize/stack2reg.rs47
1 files changed, 32 insertions, 15 deletions
diff --git a/src/optimize/stack2reg.rs b/src/optimize/stack2reg.rs
index 8f27ad7c557..cbf95eae618 100644
--- a/src/optimize/stack2reg.rs
+++ b/src/optimize/stack2reg.rs
@@ -76,11 +76,9 @@ pub(super) fn optimize_function(
 
     // FIXME Repeat following instructions until fixpoint.
 
-    println!("{}:\nstack slot usage: {:?}", name, stack_slot_usage_map);
-
     remove_unused_stack_addr_and_stack_load(&mut ctx.func, &mut stack_slot_usage_map);
 
-    println!("stack slot usage (after): {:?}", stack_slot_usage_map);
+    println!("stack slot usage: {:?}", stack_slot_usage_map);
 
     for (stack_slot, users) in stack_slot_usage_map.iter_mut() {
         if users.stack_addr.is_empty().not() {
@@ -95,8 +93,6 @@ pub(super) fn optimize_function(
             let loaded_type = ctx.func.dfg.value_type(loaded_value);
 
             let potential_stores = users.stack_store.iter().cloned().filter(|&store| {
-                // Check if the store modified some memory accessed by the load.
-
                 match spatial_overlap(&ctx.func, load, store) {
                     SpatialOverlap::No => false, // Can never be the source of the loaded value.
                     SpatialOverlap::Partial | SpatialOverlap::Full => true,
@@ -107,6 +103,7 @@ pub(super) fn optimize_function(
                     TemporalOrder::MaybeBefore | TemporalOrder::DefinitivelyBefore => true,
                 }
             }).collect::<Vec<Inst>>();
+
             for &store in &potential_stores {
                 println!(
                     "Potential store -> load forwarding {} -> {} ({:?}, {:?})",
@@ -120,6 +117,7 @@ pub(super) fn optimize_function(
             match *potential_stores {
                 [] => println!("[{}] [BUG?] Reading uninitialized memory", name),
                 [store] if spatial_overlap(&ctx.func, store, load) == SpatialOverlap::Full && temporal_order(&ctx, store, load) == TemporalOrder::DefinitivelyBefore => {
+                    // Only one store could have been the origin of the value.
                     let store_ebb = ctx.func.layout.inst_ebb(store).unwrap();
                     let stored_value = ctx.func.dfg.inst_args(store)[0];
                     let stored_type = ctx.func.dfg.value_type(stored_value);
@@ -135,12 +133,35 @@ pub(super) fn optimize_function(
             }
         }
 
-        if users.stack_load.is_empty() {
-            // Never loaded; can safely remove all stores and the stack slot.
-            // FIXME also remove stores when there is always a next store before a load.
-            for user in users.stack_store.drain() {
-                println!("[{}] Remove dead stack store {} of {}", name, user, stack_slot.0);
-                ctx.func.dfg.replace(user).nop();
+        for store in users.stack_store.clone().drain() {
+            let potential_loads = users.stack_load.iter().cloned().filter(|&load| {
+                match spatial_overlap(&ctx.func, store, load) {
+                    SpatialOverlap::No => false, // Can never be the source of the loaded value.
+                    SpatialOverlap::Partial | SpatialOverlap::Full => true,
+                }
+            }).filter(|&load| {
+                match temporal_order(&*ctx, store, load) {
+                    TemporalOrder::NeverBefore => false, // Can never be the source of the loaded value.
+                    TemporalOrder::MaybeBefore | TemporalOrder::DefinitivelyBefore => true,
+                }
+            }).collect::<Vec<Inst>>();
+
+            for &load in &potential_loads {
+                println!(
+                    "Potential load from store {} <- {} ({:?}, {:?})",
+                    ctx.func.dfg.display_inst(load, None),
+                    ctx.func.dfg.display_inst(store, None),
+                    spatial_overlap(&ctx.func, store, load),
+                    temporal_order(&*ctx, store, load),
+                );
+            }
+
+            if potential_loads.is_empty() {
+                // Never loaded; can safely remove all stores and the stack slot.
+                // FIXME also remove stores when there is always a next store before a load.
+                println!("[{}] Remove dead stack store {} of {}", name, ctx.func.dfg.display_inst(store, None), stack_slot.0);
+                ctx.func.dfg.replace(store).nop();
+                users.stack_store.remove(&store);
             }
         }
 
@@ -205,8 +226,6 @@ fn remove_unused_stack_addr_and_stack_load(func: &mut Function, stack_slot_usage
         }
     }
 
-    println!("stack_addr/stack_load users: {:?}", stack_addr_load_insts_users);
-
     for inst in stack_addr_load_insts_users.keys() {
         let mut is_recorded_stack_addr_or_stack_load = false;
         for stack_slot_users in stack_slot_usage_map.values() {
@@ -220,7 +239,6 @@ fn remove_unused_stack_addr_and_stack_load(func: &mut Function, stack_slot_usage
         // FIXME remove clone
         for &inst in stack_slot_users.stack_addr.clone().iter() {
             if stack_addr_load_insts_users.get(&inst).map(|users| users.is_empty()).unwrap_or(true) {
-                println!("Removing unused stack_addr {}", inst);
                 func.dfg.detach_results(inst);
                 func.dfg.replace(inst).nop();
                 stack_slot_users.stack_addr.remove(&inst);
@@ -229,7 +247,6 @@ fn remove_unused_stack_addr_and_stack_load(func: &mut Function, stack_slot_usage
 
         for &inst in stack_slot_users.stack_load.clone().iter() {
             if stack_addr_load_insts_users.get(&inst).map(|users| users.is_empty()).unwrap_or(true) {
-                println!("Removing unused stack_addr {}", inst);
                 func.dfg.detach_results(inst);
                 func.dfg.replace(inst).nop();
                 stack_slot_users.stack_load.remove(&inst);