From 15676786fa7f21d714b79f7875162258445d468d Mon Sep 17 00:00:00 2001 From: stevenfontanella Date: Sat, 25 Jul 2026 00:33:23 +0000 Subject: [PATCH] Make ref.i31 a constant expression --- src/ir/properties.h | 2 + src/passes/param-utils.cpp | 13 +++++ test/lit/passes/dae-gc.wast | 10 +--- test/lit/passes/dae-typessa-repeat-types.wast | 21 +++---- test/lit/passes/dae_all-features.wast | 55 +++---------------- test/lit/passes/dae_tnh.wast | 3 - test/lit/passes/signature-pruning.wast | 3 - 7 files changed, 33 insertions(+), 74 deletions(-) diff --git a/src/ir/properties.h b/src/ir/properties.h index 4b4126d750d..2926c5037f0 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -86,6 +86,8 @@ inline bool isSingleConstantExpression(const Expression* curr) { if (refAs->op == ExternConvertAny || refAs->op == AnyConvertExtern) { return isSingleConstantExpression(refAs->value); } + } else if (auto* i31 = curr->dynCast()) { + return isSingleConstantExpression(i31->value); } return curr->is() || curr->is() || curr->is() || curr->is(); diff --git a/src/passes/param-utils.cpp b/src/passes/param-utils.cpp index 6861756c475..f4381a09428 100644 --- a/src/passes/param-utils.cpp +++ b/src/passes/param-utils.cpp @@ -262,6 +262,19 @@ SortedVector applyConstantValues(const std::vector& funcs, continue; } + // If the parameter is not used in any of the functions, writing the + // constant value to it is redundant and creates a dead local set. + bool used = false; + for (auto* func : funcs) { + if (getUsedParams(func, module).count(i)) { + used = true; + break; + } + } + if (!used) { + continue; + } + // Optimize: write the constant value in the function bodies, making them // ignore the parameter's value. Builder builder(*module); diff --git a/test/lit/passes/dae-gc.wast b/test/lit/passes/dae-gc.wast index bdccf601edf..b4abdd4bf3f 100644 --- a/test/lit/passes/dae-gc.wast +++ b/test/lit/passes/dae-gc.wast @@ -179,15 +179,7 @@ ;; CHECK: (func $1 (type $0) ;; CHECK-NEXT: (local $0 (ref string)) ;; CHECK-NEXT: (local $1 (ref string)) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (string.const "929") - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (string.const "310") - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $1 (param $0 (ref string)) (param $1 (ref string)) ;; The parameters here will be removed, and the constant values placed in the diff --git a/test/lit/passes/dae-typessa-repeat-types.wast b/test/lit/passes/dae-typessa-repeat-types.wast index 7072d215cac..a50300f1dfe 100644 --- a/test/lit/passes/dae-typessa-repeat-types.wast +++ b/test/lit/passes/dae-typessa-repeat-types.wast @@ -11,11 +11,11 @@ ;; Trigger TypeSSA ;; CHECK: (type $2 (func)) - ;; CHECK: (type $3 (func (result i32 (ref (exact $struct))))) - ;; CHECK: (type $array_1 (sub $array (array (mut i32)))) - ;; CHECK: (type $5 (func (result i32 (ref $struct)))) + ;; CHECK: (type $4 (func (result i32 (ref $struct)))) + + ;; CHECK: (type $5 (func (result i32 (ref (exact $struct))))) ;; CHECK: (global $array (ref $array) (array.new $array_1 ;; CHECK-NEXT: (i32.const 0) @@ -43,15 +43,10 @@ ;; CHECK: (func $callee (type $2) ;; CHECK-NEXT: (local $0 anyref) ;; CHECK-NEXT: (tuple.drop 2 - ;; CHECK-NEXT: (block (type $3) (result i32 (ref (exact $struct))) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block (type $3) (result i32 (ref (exact $struct))) - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (struct.new_default $struct) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (type $5) (result i32 (ref (exact $struct))) + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (struct.new_default $struct) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -67,7 +62,7 @@ ) ) - ;; CHECK: (func $other (type $5) (result i32 (ref $struct)) + ;; CHECK: (func $other (type $4) (result i32 (ref $struct)) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $other (result i32 (ref $struct)) diff --git a/test/lit/passes/dae_all-features.wast b/test/lit/passes/dae_all-features.wast index 145ae1ff032..5cb0f032cdb 100644 --- a/test/lit/passes/dae_all-features.wast +++ b/test/lit/passes/dae_all-features.wast @@ -30,11 +30,6 @@ (elem (i32.const 0) $a9 $c8) ;; CHECK: (func $a (type $0) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $a (param $x i32)) ;; CHECK: (func $b (type $0) @@ -45,9 +40,6 @@ ) ;; CHECK: (func $a1 (type $0) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $a1 (param $x i32) @@ -112,11 +104,6 @@ ) ;; CHECK: (func $a4 (type $0) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $a4 (param $x i32) ;; This function is called with one constant and one unreachable. We can @@ -244,13 +231,8 @@ ) ;; CHECK: (func $a10 (type $0) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (call $a10) - ;; CHECK-NEXT: (call $a10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $a10) + ;; CHECK-NEXT: (call $a10) ;; CHECK-NEXT: ) (func $a10 (param $x i32) ;; recursion (call $a10 (i32.const 1)) @@ -417,9 +399,6 @@ ) ;; CHECK: (func $bar (type $1) (result i32) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 7) ;; CHECK-NEXT: ) (func $bar (param $x i32) (result i32) @@ -436,9 +415,6 @@ ;; CHECK: (func $foo (type $T) (result i32) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (return_call_indirect $0 (type $T) ;; CHECK-NEXT: (i32.const 0) @@ -669,22 +645,17 @@ ;; CHECK: (func $0 (type $0) ;; CHECK-NEXT: (local $0 i32) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) (func $0 (param $0 i32) (result i32) ;; The returns here are nested in each other, and one is a recursive call to @@ -835,15 +806,7 @@ ;; CHECK-NEXT: (local $0 i64) ;; CHECK-NEXT: (local $1 i64) ;; CHECK-NEXT: (local $2 v128) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $target (param $0 i64) (param $1 v128) (param $2 i64) (result f32) ;; All parameters here should vanish. diff --git a/test/lit/passes/dae_tnh.wast b/test/lit/passes/dae_tnh.wast index 6e78283fdce..b1f9d911b39 100644 --- a/test/lit/passes/dae_tnh.wast +++ b/test/lit/passes/dae_tnh.wast @@ -116,9 +116,6 @@ ;; CHECK: (func $target (type $0) (param $0 i32) ;; CHECK-NEXT: (local $1 f64) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f64.const 4.2) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/signature-pruning.wast b/test/lit/passes/signature-pruning.wast index d86e855dbe8..c2ffc51f90b 100644 --- a/test/lit/passes/signature-pruning.wast +++ b/test/lit/passes/signature-pruning.wast @@ -1309,9 +1309,6 @@ ;; CHECK: (func $other (type $other) ;; CHECK-NEXT: (local $0 anyref) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $other (type $other) (param anyref)