summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Precompute.cpp22
-rw-r--r--test/lit/passes/precompute-strings.wast52
2 files changed, 72 insertions, 2 deletions
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index 822b8ab16..4f9ad046d 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -195,6 +195,28 @@ public:
return Literal(canonical, curr->type.getHeapType());
}
+ Flow visitStringNew(StringNew* curr) {
+ if (curr->op != StringNewWTF16Array) {
+ // TODO: handle other string ops. For now we focus on JS-like strings.
+ return Flow(NONCONSTANT_FLOW);
+ }
+
+ // string.encode_wtf16_array is effectively an Array read operation, so
+ // just like ArrayGet above we must check for immutability.
+ auto ptrType = curr->ptr->type;
+ if (ptrType.isRef()) {
+ auto heapType = ptrType.getHeapType();
+ if (heapType.isArray()) {
+ if (heapType.getArray().element.mutable_ == Immutable) {
+ return Super::visitStringNew(curr);
+ }
+ }
+ }
+
+ // Otherwise, this is mutable or unreachable or otherwise uninteresting.
+ return Flow(NONCONSTANT_FLOW);
+ }
+
Flow visitStringEncode(StringEncode* curr) {
// string.encode_wtf16_array is effectively an Array write operation, so
// just like ArraySet and ArrayCopy above we must mark it as disallowed
diff --git a/test/lit/passes/precompute-strings.wast b/test/lit/passes/precompute-strings.wast
index 6046ee6b1..a9d065fdc 100644
--- a/test/lit/passes/precompute-strings.wast
+++ b/test/lit/passes/precompute-strings.wast
@@ -8,9 +8,13 @@
;; CHECK: (type $array16 (array (mut i16)))
(type $array16 (array (mut i16)))
+ (type $array16-imm (array i16))
+
;; CHECK: (type $2 (func (result (ref string))))
- ;; CHECK: (type $3 (func (result (ref any))))
+ ;; CHECK: (type $3 (func (result anyref)))
+
+ ;; CHECK: (type $4 (func (result (ref any))))
;; CHECK: (export "get_codepoint-unicode" (func $get_codepoint-unicode))
@@ -169,7 +173,7 @@
)
)
- ;; CHECK: (func $encode-stashed (type $3) (result (ref any))
+ ;; CHECK: (func $encode-stashed (type $4) (result (ref any))
;; CHECK-NEXT: (local $1 (ref $array16))
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (array.new_default $array16
@@ -234,4 +238,48 @@
(i32.const 6)
)
)
+
+ ;; CHECK: (func $string.new-mutable (type $3) (result anyref)
+ ;; CHECK-NEXT: (string.new_wtf16_array
+ ;; CHECK-NEXT: (array.new_fixed $array16 4
+ ;; CHECK-NEXT: (i32.const 65)
+ ;; CHECK-NEXT: (i32.const 66)
+ ;; CHECK-NEXT: (i32.const 67)
+ ;; CHECK-NEXT: (i32.const 68)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $string.new-mutable (result anyref)
+ ;; We do not precompute this because the array is mutable, and we do not yet
+ ;; do an analysis to see that it does not "escape" into places that modify it.
+ (string.new_wtf16_array
+ (array.new_fixed $array16 4
+ (i32.const 65)
+ (i32.const 66)
+ (i32.const 67)
+ (i32.const 68)
+ )
+ (i32.const 0)
+ (i32.const 4)
+ )
+ )
+
+ ;; CHECK: (func $string.new-immutable (type $3) (result anyref)
+ ;; CHECK-NEXT: (string.const "ABCD")
+ ;; CHECK-NEXT: )
+ (func $string.new-immutable (result anyref)
+ ;; This array is immutable and we can optimize here.
+ (string.new_wtf16_array
+ (array.new_fixed $array16-imm 4
+ (i32.const 65)
+ (i32.const 66)
+ (i32.const 67)
+ (i32.const 68)
+ )
+ (i32.const 0)
+ (i32.const 4)
+ )
+ )
)