diff options
-rw-r--r-- | src/passes/Precompute.cpp | 22 | ||||
-rw-r--r-- | test/lit/passes/precompute-strings.wast | 52 |
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) + ) + ) ) |