summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/properties.h4
-rw-r--r--src/passes/Precompute.cpp14
-rw-r--r--test/lit/passes/precompute-gc.wast37
-rw-r--r--test/passes/Oz_fuzz-exec_all-features.txt98
4 files changed, 62 insertions, 91 deletions
diff --git a/src/ir/properties.h b/src/ir/properties.h
index 8ae7befba..c4deac9d5 100644
--- a/src/ir/properties.h
+++ b/src/ir/properties.h
@@ -259,6 +259,10 @@ inline Expression* getFallthrough(Expression* curr,
if (!EffectAnalyzer(passOptions, features, tryy->body).throws) {
return getFallthrough(tryy->body, passOptions, features);
}
+ } else if (auto* as = curr->dynCast<RefAs>()) {
+ return getFallthrough(as->value, passOptions, features);
+ } else if (auto* br = curr->dynCast<BrOn>()) {
+ return getFallthrough(br->ref, passOptions, features);
}
return curr;
}
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index ae488a01f..85e09f875 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -173,13 +173,13 @@ struct Precompute
if (flow.getType().hasVector()) {
return;
}
+ if (!canEmitConstantFor(flow.values)) {
+ return;
+ }
if (flow.breaking()) {
if (flow.breakTo == NONCONSTANT_FLOW) {
return;
}
- if (!canEmitConstantFor(flow.values)) {
- return;
- }
if (flow.breakTo == RETURN_FLOW) {
// this expression causes a return. if it's already a return, reuse the
// node
@@ -365,15 +365,17 @@ private:
if (value.type.isFunction()) {
return true;
}
+ // All other reference types cannot be precomputed.
+ if (value.type.isRef()) {
+ return false;
+ }
return canEmitConstantFor(value.type);
}
bool canEmitConstantFor(Type type) {
- // Don't try to precompute a reference. We can't replace it with a constant
- // expression, as that would make a copy of it by value.
// For now, don't try to precompute an Rtt. TODO figure out when that would
// be safe and useful.
- return !type.isRef() && !type.isRtt();
+ return !type.isRtt();
}
};
diff --git a/test/lit/passes/precompute-gc.wast b/test/lit/passes/precompute-gc.wast
new file mode 100644
index 000000000..9402aa068
--- /dev/null
+++ b/test/lit/passes/precompute-gc.wast
@@ -0,0 +1,37 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate -all -S -o - \
+;; RUN: | filecheck %s
+
+(module
+ ;; CHECK: (func $test-fallthrough (result i32)
+ ;; CHECK-NEXT: (local $x funcref)
+ ;; CHECK-NEXT: (local.set $x
+ ;; CHECK-NEXT: (block (result funcref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (call $test-fallthrough)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (ref.null func)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ (func $test-fallthrough (result i32)
+ (local $x funcref)
+ (local.set $x
+ ;; the fallthrough value should be used. for that to be possible with a block
+ ;; we need for it not to have a name, which is why --remove-unused-names is
+ ;; run
+ (block (result (funcref))
+ ;; make a call so the block is not trivially removable
+ (drop
+ (call $test-fallthrough)
+ )
+ (ref.null func)
+ )
+ )
+ ;; the null in the local should be propagated to here
+ (ref.is_null
+ (local.get $x)
+ )
+ )
+)
diff --git a/test/passes/Oz_fuzz-exec_all-features.txt b/test/passes/Oz_fuzz-exec_all-features.txt
index 0da22edbd..b7c7688b5 100644
--- a/test/passes/Oz_fuzz-exec_all-features.txt
+++ b/test/passes/Oz_fuzz-exec_all-features.txt
@@ -35,13 +35,11 @@
[fuzz-exec] calling array-alloc-failure
[host limit allocation failure]
(module
- (type $struct (struct (field (mut i32))))
(type $void_func (func))
- (type $extendedstruct (struct (field (mut i32)) (field f64)))
- (type $bytes (array (mut i8)))
(type $i32_=>_none (func (param i32)))
(type $anyref_=>_none (func (param anyref)))
(type $int_func (func (result i32)))
+ (type $struct (struct (field (mut i32))))
(import "fuzzing-support" "log-i32" (func $log (param i32)))
(elem declare func $a-void-func)
(export "structs" (func $0))
@@ -53,85 +51,37 @@
(export "rtt-and-cast-on-func" (func $8))
(export "array-alloc-failure" (func $9))
(func $0 (; has Stack IR ;)
- (local $0 (ref null $struct))
(call $log
- (struct.get $struct 0
- (local.tee $0
- (struct.new_default_with_rtt $struct
- (rtt.canon $struct)
- )
- )
- )
+ (i32.const 0)
)
- (struct.set $struct 0
- (local.get $0)
+ (call $log
(i32.const 42)
)
(call $log
- (struct.get $struct 0
- (local.get $0)
- )
- )
- (struct.set $struct 0
- (local.get $0)
(i32.const 100)
)
(call $log
- (struct.get $struct 0
- (local.get $0)
- )
- )
- (call $log
- (struct.get $struct 0
- (local.get $0)
- )
+ (i32.const 100)
)
)
(func $1 (; has Stack IR ;)
- (local $0 (ref null $bytes))
(call $log
- (array.len $bytes
- (local.tee $0
- (array.new_with_rtt $bytes
- (i32.const 42)
- (i32.const 50)
- (rtt.canon $bytes)
- )
- )
- )
+ (i32.const 50)
)
(call $log
- (array.get_u $bytes
- (local.get $0)
- (i32.const 10)
- )
- )
- (array.set $bytes
- (local.get $0)
- (i32.const 10)
- (i32.const 128)
+ (i32.const 42)
)
(call $log
- (array.get_u $bytes
- (local.get $0)
- (i32.const 10)
- )
+ (i32.const 128)
)
(call $log
- (array.get_s $bytes
- (local.get $0)
- (i32.const 10)
- )
+ (i32.const -128)
)
(call $log
- (array.get_s $bytes
- (local.get $0)
- (i32.const 20)
- )
+ (i32.const 42)
)
)
(func $2 (; has Stack IR ;)
- (local $0 anyref)
(call $log
(i32.const 1)
)
@@ -148,30 +98,13 @@
(i32.const 0)
)
(call $log
- (ref.test
- (local.tee $0
- (struct.new_default_with_rtt $extendedstruct
- (rtt.sub $extendedstruct
- (rtt.canon $struct)
- )
- )
- )
- (rtt.sub $extendedstruct
- (rtt.canon $struct)
- )
- )
+ (i32.const 1)
)
(call $log
- (ref.test
- (local.get $0)
- (rtt.canon $extendedstruct)
- )
+ (i32.const 0)
)
(call $log
- (ref.test
- (local.get $0)
- (rtt.canon $struct)
- )
+ (i32.const 1)
)
)
(func $3 (; has Stack IR ;)
@@ -217,12 +150,7 @@
(call $log
(i32.const 2)
)
- (call_ref
- (ref.cast
- (ref.func $a-void-func)
- (rtt.canon $void_func)
- )
- )
+ (call $a-void-func)
(call $log
(i32.const 3)
)