From 4b9decbbfa2c5e2675e922579dc24c081d797703 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 12 Feb 2024 09:40:17 -0800 Subject: [PATCH 1/2] Precompute: Optimize array.len --- src/passes/Precompute.cpp | 2 +- test/lit/passes/precompute-gc-immutable.wast | 92 +++++++++++++++++++- test/lit/passes/precompute-gc.wast | 2 - 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 5baf2331f14..d2f3543ad1b 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -178,7 +178,7 @@ class PrecomputingExpressionRunner // Otherwise, we've failed to precompute. return Flow(NONCONSTANT_FLOW); } - Flow visitArrayLen(ArrayLen* curr) { return Flow(NONCONSTANT_FLOW); } + // ArrayLen is not disallowed here as it is an immutable property. Flow visitArrayCopy(ArrayCopy* curr) { return Flow(NONCONSTANT_FLOW); } // Generates heap info for a heap-allocating expression. diff --git a/test/lit/passes/precompute-gc-immutable.wast b/test/lit/passes/precompute-gc-immutable.wast index c2a96bd2371..a3bef210f6c 100644 --- a/test/lit/passes/precompute-gc-immutable.wast +++ b/test/lit/passes/precompute-gc-immutable.wast @@ -9,7 +9,14 @@ ;; CHECK: (type $struct-mut (struct (field (mut i32)))) (type $struct-mut (struct (mut i32))) - ;; CHECK: (func $propagate (type $2) + ;; CHECK: (type $array-mut (array (mut i32))) + + ;; CHECK: (type $array-imm (array i32)) + (type $array-imm (array i32)) + + (type $array-mut (array (mut i32))) + + ;; CHECK: (func $propagate-struct (type $2) ;; CHECK-NEXT: (local $ref-imm (ref null $struct-imm)) ;; CHECK-NEXT: (local $ref-mut (ref null $struct-mut)) ;; CHECK-NEXT: (local.set $ref-imm @@ -31,7 +38,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $propagate + (func $propagate-struct (local $ref-imm (ref null $struct-imm)) (local $ref-mut (ref null $struct-mut)) ;; We can propagate from an immutable field of a struct created in this @@ -59,6 +66,85 @@ ) ) + ;; CHECK: (func $propagate-array (type $2) + ;; CHECK-NEXT: (local $ref-imm (ref null $array-imm)) + ;; CHECK-NEXT: (local $ref-mut (ref null $array-mut)) + ;; CHECK-NEXT: (local.set $ref-imm + ;; CHECK-NEXT: (array.new_fixed $array-imm 3 + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $helper + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $helper + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $ref-mut + ;; CHECK-NEXT: (array.new_fixed $array-mut 3 + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $helper + ;; CHECK-NEXT: (array.get $array-mut + ;; CHECK-NEXT: (local.get $ref-mut) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $helper + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $propagate-array + (local $ref-imm (ref null $array-imm)) + (local $ref-mut (ref null $array-mut)) + ;; We can propagate from a slot in an immutable array created in this + ;; function, and also get the length. + (local.set $ref-imm + (array.new_fixed $array-imm 3 + (i32.const 10) + (i32.const 20) + (i32.const 30) + ) + ) + (call $helper + (array.get $array-imm ;; this returns 30 + (local.get $ref-imm) + (i32.const 2) + ) + ) + (call $helper + (array.len ;; this returns 3 + (local.get $ref-imm) + ) + ) + ;; But the same thing on a mutable array fails. + (local.set $ref-mut + (array.new_fixed $array-mut 3 + (i32.const 10) + (i32.const 20) + (i32.const 30) + ) + ) + (call $helper + (array.get $array-mut + (local.get $ref-mut) + (i32.const 2) + ) + ) + ;; We can, however, optimize array.len in both cases as that is an + ;; immutable property. + (call $helper + (array.len ;; this returns 3 + (local.get $ref-mut) + ) + ) + ) + ;; CHECK: (func $non-constant (type $1) (param $param i32) ;; CHECK-NEXT: (local $ref (ref null $struct-imm)) ;; CHECK-NEXT: (local.set $ref @@ -118,7 +204,7 @@ ) ) - ;; CHECK: (func $param (type $4) (param $ref-imm (ref null $struct-imm)) + ;; CHECK: (func $param (type $6) (param $ref-imm (ref null $struct-imm)) ;; CHECK-NEXT: (call $helper ;; CHECK-NEXT: (struct.get $struct-imm 0 ;; CHECK-NEXT: (local.get $ref-imm) diff --git a/test/lit/passes/precompute-gc.wast b/test/lit/passes/precompute-gc.wast index 8d4b56ce760..824587df980 100644 --- a/test/lit/passes/precompute-gc.wast +++ b/test/lit/passes/precompute-gc.wast @@ -20,8 +20,6 @@ (type $struct_i8 (struct (field i8))) - (type $array16 (array (mut i16))) - (type $func-return-i32 (func (result i32))) ;; CHECK: (import "fuzzing-support" "log-i32" (func $log (type $4) (param i32))) From 84038f44b2ffc424a0fc33c47e3e4becdae6548c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 12 Feb 2024 12:57:38 -0800 Subject: [PATCH 2/2] Improvements to existing tests --- test/passes/Oz_fuzz-exec_all-features.txt | 30 +++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/test/passes/Oz_fuzz-exec_all-features.txt b/test/passes/Oz_fuzz-exec_all-features.txt index 2f14281609d..20cbca924dc 100644 --- a/test/passes/Oz_fuzz-exec_all-features.txt +++ b/test/passes/Oz_fuzz-exec_all-features.txt @@ -100,16 +100,15 @@ ) (func $arrays (type $void_func) (; has Stack IR ;) (local $0 (ref $bytes)) - (call $log - (array.len - (local.tee $0 - (array.new $bytes - (i32.const 42) - (i32.const 50) - ) - ) + (local.set $0 + (array.new $bytes + (i32.const 42) + (i32.const 50) ) ) + (call $log + (i32.const 50) + ) (call $log (array.get_u $bytes (local.get $0) @@ -271,16 +270,15 @@ ) (func $array.new_fixed (type $void_func) (; has Stack IR ;) (local $0 (ref $bytes)) - (call $log - (array.len - (local.tee $0 - (array.new_fixed $bytes 2 - (i32.const 42) - (i32.const 50) - ) - ) + (local.set $0 + (array.new_fixed $bytes 2 + (i32.const 42) + (i32.const 50) ) ) + (call $log + (i32.const 2) + ) (call $log (array.get_u $bytes (local.get $0)