Skip to content

Commit

Permalink
Remove unused locals (FuelLabs#4458)
Browse files Browse the repository at this point in the history
  • Loading branch information
vaivaswatha authored Apr 18, 2023
1 parent 7011edd commit 2e494f3
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 12 deletions.
9 changes: 9 additions & 0 deletions sway-ir/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,15 @@ impl Function {
context.functions[self.0].local_storage.iter()
}

/// Remove given list of locals
pub fn remove_locals(&self, context: &mut Context, removals: &Vec<String>) {
for remove in removals {
if let Some(local) = context.functions[self.0].local_storage.remove(remove) {
context.local_vars.remove(local.0);
}
}
}

/// Merge values from another [`Function`] into this one.
///
/// The names of the merged values are guaranteed to be unique via the use of
Expand Down
31 changes: 28 additions & 3 deletions sway-ir/src/optimize/dce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//! This pass does not do CFG transformations. That is handled by simplify_cfg.
use crate::{
AnalysisResults, Block, Context, Function, Instruction, IrError, Module, Pass, PassMutability,
ScopedPass, Value, ValueDatum,
AnalysisResults, Block, Context, Function, Instruction, IrError, LocalVar, Module, Pass,
PassMutability, ScopedPass, Value, ValueDatum,
};

use std::collections::{HashMap, HashSet};
Expand Down Expand Up @@ -47,10 +47,18 @@ pub fn dce(
) -> Result<bool, IrError> {
// Number of uses that an instruction has.
let mut num_uses: HashMap<Value, (Block, u32)> = HashMap::new();
let mut num_local_uses: HashMap<LocalVar, u32> = HashMap::new();

// Go through each instruction and update use_count.
for (block, inst) in function.instruction_iter(context) {
let opds = inst.get_instruction(context).unwrap().get_operands();
let inst = inst.get_instruction(context).unwrap();
if let Instruction::GetLocal(local) = inst {
num_local_uses
.entry(*local)
.and_modify(|count| *count += 1)
.or_insert(1);
}
let opds = inst.get_operands();
for v in opds {
match context.values[v.0].value {
ValueDatum::Instruction(_) => {
Expand Down Expand Up @@ -94,7 +102,24 @@ pub fn dce(
}

in_block.remove_instruction(context, dead);

if let ValueDatum::Instruction(Instruction::GetLocal(local)) = context.values[dead.0].value
{
let count = num_local_uses.get_mut(&local).unwrap();
*count -= 1;
}
modified = true;
}

let local_removals: Vec<_> = function
.locals_iter(context)
.filter_map(|(name, local)| {
(num_local_uses.get(local).cloned().unwrap_or(0) == 0).then_some(name.clone())
})
.collect();
if !local_removals.is_empty() {
modified = true;
function.remove_locals(context, &local_removals);
}

Ok(modified)
Expand Down
12 changes: 12 additions & 0 deletions sway-ir/tests/dce/dce2.ir
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// regex: ID=[[:alpha:]0-9]+

script {
fn main() -> bool {
// not: local u64 i
local u64 i

entry():
v9 = const bool false
ret bool v9
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use array_of_structs_abi::{Id, TestContract, Wrapper};
use std::hash::sha256;

fn main() -> u64 {
let addr = abi(TestContract, 0xa5d354e58efd316c2eb3f4b273a2143e7d534952fae5e191e057b27403ae829e);
let addr = abi(TestContract, 0xfd87acbc9cfdbae40894dc1be15c8f5f07a5775ca110df2584f053ac6ad10672);

let input = [Wrapper {
id: Id {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ script;
use basic_storage_abi::{BasicStorage, Quad};

fn main() -> u64 {
let addr = abi(BasicStorage, 0xc98246b75472af9196be66b65a979ebbe5cd5975d1331f18ce2cda66a9819379);
let addr = abi(BasicStorage, 0x6906bdbccb7ca8e66c11ce16518c2f946da094d3e2c8561ca38d5a6d9a13e996);
let key = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
let value = 4242;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ script;
use contract_with_type_aliases_abi::*;

fn main() {
let caller = abi(MyContract, 0xaa380eacd28dbfba42ee88a1df59544f5cbc3e862a5b12bc2af894923ec4f5e8);
let caller = abi(MyContract, 0xf5030df8b9336a88f24afa90afe33aea6affd5295821aeb4eade84cd1fee4345);

let x = AssetId::from(0x0101010101010101010101010101010101010101010101010101010101010101);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ script;
use increment_abi::Incrementor;

fn main() -> bool {
let the_abi = abi(Incrementor, 0xc9baa3acb84a53e91b31b2ecc514d5ad8a715083282dc16d520b5d40a9fc94a7);
let the_abi = abi(Incrementor, 0x6b259c454583b3995b9e35effa476f8cb2155ff44d1d8d567a83108b4fe65444);
the_abi.increment(5);
the_abi.increment(5);
let result = the_abi.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn main() -> bool {
let zero = b256::min();
let gas: u64 = u64::max();
let amount: u64 = 11;
let other_contract_id = ContractId::from(0xc29171776f4d174a9e338d12c3b84e1de1694ba8bd64fb725d9eaf2842c7c6f1);
let other_contract_id = ContractId::from(0x338000acdb5764cdaaf90a70b2fa73c68fed43ce2b7bdb329d361cb6b5393a43);
let base_asset_id = BASE_ASSET_ID;

let test_contract = abi(ContextTesting, other_contract_id.into());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ script;
use get_storage_key_abi::TestContract;

fn main() -> u64 {
let caller = abi(TestContract, 0x79fd3f7662e227f8ff7bef65b683fa4417b7e9f6d6bdbc0eb4d899ea2d73cad3);
let caller = abi(TestContract, 0xfd77b8770d4b9ad2402e8d6c838c8a837d2a56dd02ec4445c4c212bfce66b143);

// Get the storage keys directly by calling the contract methods from_f1,
// from_f2, from_f3, from_f4. The keys correspond to different entries in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ script;
use nested_struct_args_abi::*;

fn main() -> bool {
let contract_id = 0xc07c133be5867020f483c34e045c9162867d6b40accc022525e50c048d17d679;
let contract_id = 0x1ce4c30fc1fe5d4639683ad1330de7739efd297671a540ffe9012e9cf3953fe7;
let caller = abi(NestedStructArgs, contract_id);

let param_one = StructOne {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use storage_access_abi::*;
use std::hash::sha256;

fn main() -> bool {
let contract_id = 0x9ec7ac3cce15b1b75adabd598a374e96b606471a56229486a2d0ca26c08ed994;
let contract_id = 0x8982d742b1f313818d24516f7410519ca4fd4bbab470012809ffde710c45c0a4;
let caller = abi(StorageAccess, contract_id);

// Test initializers
Expand Down
1 change: 0 additions & 1 deletion test/src/ir_generation/tests/simple_contract_call.sw
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ fn main() -> u64 {
// check: local b256 $(asset_id_2_const=$ID) = const b256 0x0000000000000000000000000000000000000000000000000000000000000000

// check: local u64 a
// check: local b256 arg_for_get_b256
// check: local { u64, b256 } args_struct_for_get_s
// check: local b256 b
// check: local { u64, b256 } s
Expand Down

0 comments on commit 2e494f3

Please sign in to comment.