summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/DeadArgumentElimination.cpp18
-rw-r--r--test/lit/passes/dae-refine-params-and-optimize.wast42
2 files changed, 53 insertions, 7 deletions
diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp
index ab4c8b8eb..d0705961b 100644
--- a/src/passes/DeadArgumentElimination.cpp
+++ b/src/passes/DeadArgumentElimination.cpp
@@ -216,6 +216,8 @@ struct DAE : public Pass {
allDroppedCalls[name] = calls;
}
}
+ // Track which functions we changed, and optimize them later if necessary.
+ std::unordered_set<Function*> changed;
// If we refine return types then we will need to do more type updating
// at the end.
bool refinedReturnTypes = false;
@@ -230,7 +232,9 @@ struct DAE : public Pass {
// Refine argument types before doing anything else. This does not
// affect whether an argument is used or not, it just refines the type
// where possible.
- refineArgumentTypes(func, calls, module, infoMap[name]);
+ if (refineArgumentTypes(func, calls, module, infoMap[name])) {
+ changed.insert(func);
+ }
// Refine return types as well.
if (refineReturnTypes(func, calls, module)) {
refinedReturnTypes = true;
@@ -249,8 +253,6 @@ struct DAE : public Pass {
// TODO: We could track in which functions we actually make changes.
ReFinalize().run(getPassRunner(), module);
}
- // Track which functions we changed, and optimize them later if necessary.
- std::unordered_set<Function*> changed;
// We now know which parameters are unused, and can potentially remove them.
for (auto& [name, calls] : allCalls) {
if (infoMap[name].hasUnseenCalls) {
@@ -358,12 +360,12 @@ private:
//
// This assumes that the function has no calls aside from |calls|, that is, it
// is not exported or called from the table or by reference.
- void refineArgumentTypes(Function* func,
+ bool refineArgumentTypes(Function* func,
const std::vector<Call*>& calls,
Module* module,
const DAEFunctionInfo& info) {
if (!module->features.hasGC()) {
- return;
+ return false;
}
auto numParams = func->getNumParams();
std::vector<Type> newParamTypes;
@@ -393,7 +395,7 @@ private:
// Nothing is sent here at all; leave such optimizations to DCE.
if (!lub.noted()) {
- return;
+ return false;
}
newParamTypes.push_back(lub.getLUB());
}
@@ -402,7 +404,7 @@ private:
// function body.
auto newParams = Type(newParamTypes);
if (newParams == func->getParams()) {
- return;
+ return false;
}
// We can do this!
@@ -410,6 +412,8 @@ private:
// Update the function's type.
func->setParams(newParams);
+
+ return true;
}
// See if the types returned from a function allow us to define a more refined
diff --git a/test/lit/passes/dae-refine-params-and-optimize.wast b/test/lit/passes/dae-refine-params-and-optimize.wast
new file mode 100644
index 000000000..65611908a
--- /dev/null
+++ b/test/lit/passes/dae-refine-params-and-optimize.wast
@@ -0,0 +1,42 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+
+;; RUN: foreach %s %t wasm-opt -all --dae-optimizing -S -o - | filecheck %s
+
+;; The br_on_cast_fail is optimized away thanks to the refined type. The output still has some unoptimized code (an additional --dce pass would get rid of the drop-return pattern here), but that is not directly relevant to this test.
+(module
+ ;; CHECK: (type $ref|array|_=>_i32 (func (param (ref array)) (result i32)))
+
+ ;; CHECK: (func $len (type $ref|array|_=>_i32) (param $0 (ref array)) (result i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (return
+ ;; CHECK-NEXT: (array.len
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $len (param (ref eq)) (result i32)
+ (drop
+ (block $not_array (result (ref eq))
+ (return
+ (array.len
+ (br_on_cast_fail $not_array (ref eq) (ref array)
+ (local.get 0)
+ )
+ )
+ )
+ )
+ )
+ (i32.const -1)
+ )
+ ;; CHECK: (func $optimize-after-refinement (type $ref|array|_=>_i32) (param $0 (ref array)) (result i32)
+ ;; CHECK-NEXT: (call $len
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $optimize-after-refinement (param (ref array)) (result i32)
+ (call $len
+ (local.get 0)
+ )
+ )
+)