diff --git a/src/passes/PostAssemblyScript.cpp b/src/passes/PostAssemblyScript.cpp index eeb077ce902..8691771f7b1 100644 --- a/src/passes/PostAssemblyScript.cpp +++ b/src/passes/PostAssemblyScript.cpp @@ -364,8 +364,16 @@ struct OptimizeARC : public WalkerPass> { return (*releaseLocation)->cast()->operands[0]->cast(); } + // Tests if the given retain is generally eliminable (does not retain an + // allocation and does not reach an escape) + bool testRetainEliminable(LocalSet* retain, AliasGraph& graph) { + return !testRetainsAllocation(getRetainedExpression(retain), graph) && + !testReachesEscape(retain, graph); + } + // Tests if a release has balanced retains, that is it is being retained in - // any path leading to the release. For example + // any path leading to the release and that each path is generally eliminable. + // For example // // var c = somethingElse() || a; // ... @@ -395,7 +403,8 @@ struct OptimizeARC : public WalkerPass> { if (localSet == nullptr) { return cache[release] = false; } - if (retains.find(localSet) == retains.end()) { + auto it = retains.find(localSet); + if (it == retains.end()) { if (auto* localGet = localSet->value->dynCast()) { if (seen.find(localGet) == seen.end()) { seen.insert(localGet); @@ -408,6 +417,8 @@ struct OptimizeARC : public WalkerPass> { } else { return cache[release] = false; } + } else if (!testRetainEliminable(it->first, graph)) { + return cache[release] = false; } } return cache[release] = true; @@ -441,71 +452,60 @@ struct OptimizeARC : public WalkerPass> { Set redundantReleases; Map balancedRetainsCache; - // For each retain, check that it - // - // * doesn't reach an escape - // * doesn't retain an allocation + // For each retain, check that it is + // * generally eliminable (does not retain an allocation / reach an escape) // * reaches at least one release - // * reaches only releases with balanced retains - // + // * reaches only releases with balanced (generally eliminable) retains for (auto& pair : retains) { auto* retain = pair.first; auto** retainLocation = pair.second; - if (!testReachesEscape(retain, graph)) { - if (!testRetainsAllocation(getRetainedExpression(retain), graph)) { - Set releaseLocations; - collectReleases(retain, graph, releaseLocations); - if (!releaseLocations.empty()) { - bool allBalanced = true; - for (auto** releaseLocation : releaseLocations) { - if (!testBalancedRetains(getReleaseByLocation(releaseLocation), - graph, - balancedRetainsCache)) { - allBalanced = false; - break; - } + if (testRetainEliminable(retain, graph)) { + Set releaseLocations; + collectReleases(retain, graph, releaseLocations); + if (!releaseLocations.empty()) { + bool allBalanced = true; + for (auto** releaseLocation : releaseLocations) { + if (!testBalancedRetains(getReleaseByLocation(releaseLocation), + graph, + balancedRetainsCache)) { + allBalanced = false; + break; } - if (allBalanced) { -#ifdef POST_ASSEMBLYSCRIPT_DEBUG - std::cerr << " eliminating "; - WasmPrinter::printExpression(retain, std::cerr, true); - std::cerr << " reaching\n"; -#endif - redundantRetains.insert(retainLocation); - for (auto** getLocation : releaseLocations) { + } + if (allBalanced) { #ifdef POST_ASSEMBLYSCRIPT_DEBUG - std::cerr << " "; - WasmPrinter::printExpression(*getLocation, std::cerr, true); - std::cerr << "\n"; + std::cerr << " eliminating "; + WasmPrinter::printExpression(retain, std::cerr, true); + std::cerr << " reaching\n"; #endif - redundantReleases.insert(getLocation); - } + redundantRetains.insert(retainLocation); + for (auto** getLocation : releaseLocations) { #ifdef POST_ASSEMBLYSCRIPT_DEBUG - } else { - std::cerr << " cannot eliminate "; - WasmPrinter::printExpression(retain, std::cerr, true); - std::cerr << " - unbalanced\n"; + std::cerr << " "; + WasmPrinter::printExpression(*getLocation, std::cerr, true); + std::cerr << "\n"; #endif + redundantReleases.insert(getLocation); } #ifdef POST_ASSEMBLYSCRIPT_DEBUG } else { std::cerr << " cannot eliminate "; WasmPrinter::printExpression(retain, std::cerr, true); - std::cerr << " - zero releases\n"; + std::cerr << " - unbalanced\n"; #endif } #ifdef POST_ASSEMBLYSCRIPT_DEBUG } else { std::cerr << " cannot eliminate "; WasmPrinter::printExpression(retain, std::cerr, true); - std::cerr << " - retains allocation\n"; + std::cerr << " - zero releases\n"; #endif } #ifdef POST_ASSEMBLYSCRIPT_DEBUG } else { std::cerr << " cannot eliminate "; WasmPrinter::printExpression(retain, std::cerr, true); - std::cerr << " - reaches return\n"; + std::cerr << " - not eliminable\n"; #endif } } diff --git a/test/passes/post-assemblyscript.txt b/test/passes/post-assemblyscript.txt index 2b3111e91b3..7e024b8c0b5 100644 --- a/test/passes/post-assemblyscript.txt +++ b/test/passes/post-assemblyscript.txt @@ -3,10 +3,11 @@ (type $i32_=>_none (func (param i32))) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) - (type $none_=>_i32 (func (result i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (type $none_=>_i32 (func (result i32))) (import "rt" "retain" (func $~lib/rt/pure/__retain (param i32) (result i32))) (import "rt" "release" (func $~lib/rt/pure/__release (param i32))) + (import "rt" "alloc" (func $~lib/rt/tlsf/__alloc (param i32 i32) (result i32))) (import "rc" "getRetainedRef" (func $getRetainedRef (result i32))) (func $eliminates.linearArgument (param $0 i32) (local.set $0 @@ -260,4 +261,40 @@ ) ) ) + (func $keeps.balancedRetainsWithAllocation (param $0 i32) (param $cond1 i32) (param $cond2 i32) + (local $3 i32) + (local $flat i32) + (if + (local.get $cond1) + (if + (local.get $cond2) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (block $block + (local.set $flat + (call $~lib/rt/tlsf/__alloc + (i32.const 16) + (i32.const 0) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $flat) + ) + ) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (call $~lib/rt/pure/__release + (local.get $3) + ) + ) ) diff --git a/test/passes/post-assemblyscript.wast b/test/passes/post-assemblyscript.wast index c79bfe1d98f..6aee3fa7e86 100644 --- a/test/passes/post-assemblyscript.wast +++ b/test/passes/post-assemblyscript.wast @@ -3,6 +3,7 @@ (module (import "rt" "retain" (func $~lib/rt/pure/__retain (param i32) (result i32))) (import "rt" "release" (func $~lib/rt/pure/__release (param i32))) + (import "rt" "alloc" (func $~lib/rt/tlsf/__alloc (param i32 i32) (result i32))) (func $eliminates.linearArgument (param $0 i32) (local.set $0 (call $~lib/rt/pure/__retain @@ -339,4 +340,40 @@ ) ) ) + (func $keeps.balancedRetainsWithAllocation (param $0 i32) (param $cond1 i32) (param $cond2 i32) + (local $3 i32) + (local $flat i32) + (if + (local.get $cond1) + (if + (local.get $cond2) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + (block + (local.set $flat + (call $~lib/rt/tlsf/__alloc + (i32.const 16) + (i32.const 0) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $flat) + ) + ) + ) + ) + (local.set $3 + (call $~lib/rt/pure/__retain + (local.get $0) + ) + ) + ) + (call $~lib/rt/pure/__release + (local.get $3) + ) + ) )