From f39cbc595ad7b2b749190bf31bbcd44819cb7ec4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 13:43:13 -0700 Subject: [PATCH 01/36] go? --- src/passes/ConstraintAnalysis.cpp | 14 + .../lit/passes/constraint-analysis-float.wast | 32 +- .../lit/passes/constraint-analysis-loops.wast | 14 +- .../constraint-analysis-propagation.wast | 8 +- test/lit/passes/constraint-analysis.wast | 1127 +++++++++++++---- 5 files changed, 934 insertions(+), 261 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 9e275665e9e..2c98b9f99a9 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -195,6 +195,11 @@ struct ConstraintAnalysis } } + void visitLocalGet(LocalGet* curr) { + addAction(); + relevantLocals[curr->index] = true; + } + void visitLocalSet(LocalSet* curr) { addAction(); @@ -444,6 +449,15 @@ struct ConstraintAnalysis void optimizeExpression(Expression** currp, const BasicBlockConstraintMap& constraints) { auto* curr = *currp; + + if (auto* get = curr->dynCast()) { + // A bare local.get can be optimized, if we know that local is a constant. + if (auto lit = constraints.get(get->index).getLiteral()) { + *currp = Builder(*getModule()).makeConstantExpression(*lit); + } + return; + } + // Note that we don't need to try to parse a series of constraints with // ParsedAndedConstraints: if there is a tree of ANDed things, we will // simply optimize it as we walk it, each time handling one. diff --git a/test/lit/passes/constraint-analysis-float.wast b/test/lit/passes/constraint-analysis-float.wast index 348ec8d5941..2fd9389ec69 100644 --- a/test/lit/passes/constraint-analysis-float.wast +++ b/test/lit/passes/constraint-analysis-float.wast @@ -11,8 +11,8 @@ ;; CHECK-NEXT: (local $f f64) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (local.get $f) - ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (nop) @@ -22,7 +22,10 @@ ;; FASTM: (func $float-zero (type $0) ;; FASTM-NEXT: (local $f f64) ;; FASTM-NEXT: (if - ;; FASTM-NEXT: (i32.const 1) + ;; FASTM-NEXT: (f64.eq + ;; FASTM-NEXT: (f64.const 0) + ;; FASTM-NEXT: (f64.const 0) + ;; FASTM-NEXT: ) ;; FASTM-NEXT: (then ;; FASTM-NEXT: (nop) ;; FASTM-NEXT: ) @@ -47,7 +50,7 @@ ;; CHECK-NEXT: (local $f f64) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (f64.const -0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then @@ -56,7 +59,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then @@ -67,13 +70,19 @@ ;; FASTM: (func $float-negative-zero (type $0) ;; FASTM-NEXT: (local $f f64) ;; FASTM-NEXT: (if - ;; FASTM-NEXT: (i32.const 1) + ;; FASTM-NEXT: (f64.eq + ;; FASTM-NEXT: (f64.const 0) + ;; FASTM-NEXT: (f64.const -0) + ;; FASTM-NEXT: ) ;; FASTM-NEXT: (then ;; FASTM-NEXT: (nop) ;; FASTM-NEXT: ) ;; FASTM-NEXT: ) ;; FASTM-NEXT: (if - ;; FASTM-NEXT: (i32.const 1) + ;; FASTM-NEXT: (f64.eq + ;; FASTM-NEXT: (f64.const 0) + ;; FASTM-NEXT: (f64.const 0) + ;; FASTM-NEXT: ) ;; FASTM-NEXT: (then ;; FASTM-NEXT: (nop) ;; FASTM-NEXT: ) @@ -110,8 +119,8 @@ ;; CHECK-NEXT: (f64.const nan:0x8000000000000) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $nan) - ;; CHECK-NEXT: (local.get $nan) + ;; CHECK-NEXT: (f64.const nan:0x8000000000000) + ;; CHECK-NEXT: (f64.const nan:0x8000000000000) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; FASTM: (func $float-ne-nan (type $1) (result i32) @@ -119,7 +128,10 @@ ;; FASTM-NEXT: (local.set $nan ;; FASTM-NEXT: (f64.const nan:0x8000000000000) ;; FASTM-NEXT: ) - ;; FASTM-NEXT: (i32.const 0) + ;; FASTM-NEXT: (f64.ne + ;; FASTM-NEXT: (f64.const nan:0x8000000000000) + ;; FASTM-NEXT: (f64.const nan:0x8000000000000) + ;; FASTM-NEXT: ) ;; FASTM-NEXT: ) (func $float-ne-nan (result i32) (local $nan f64) diff --git a/test/lit/passes/constraint-analysis-loops.wast b/test/lit/passes/constraint-analysis-loops.wast index 7c66ee84429..3cdb9ff6cdb 100644 --- a/test/lit/passes/constraint-analysis-loops.wast +++ b/test/lit/passes/constraint-analysis-loops.wast @@ -967,7 +967,7 @@ ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $len) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then @@ -1039,7 +1039,7 @@ ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $len) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then @@ -1526,7 +1526,10 @@ ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1551,7 +1554,10 @@ ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/constraint-analysis-propagation.wast b/test/lit/passes/constraint-analysis-propagation.wast index 4e953c9f8ab..53f0530291a 100644 --- a/test/lit/passes/constraint-analysis-propagation.wast +++ b/test/lit/passes/constraint-analysis-propagation.wast @@ -22,7 +22,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) @@ -83,12 +83,10 @@ ;; CHECK-NEXT: (local.set $2 ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $label - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 067845236dd..2b28b65a7e2 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -23,16 +23,28 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $simple (type $1) @@ -41,13 +53,19 @@ ;; OPTIN-NEXT: (i32.const 10) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.ne + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -119,7 +137,10 @@ ;; OPTIN-NEXT: (i32.const 30) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (i32.div_u @@ -175,22 +196,37 @@ ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (i32.const 15) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 15) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 15) + ;; CHECK-NEXT: (i32.const 15) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-local (type $1) @@ -203,22 +239,37 @@ ;; OPTIN-NEXT: (i32.const 20) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (i32.const 15) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 15) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 15) + ;; OPTIN-NEXT: (i32.const 15) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $multi-local @@ -278,17 +329,26 @@ ;; CHECK-NEXT: (local.get $param) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-block (type $0) (param $param i32) @@ -300,15 +360,24 @@ ;; OPTIN-NEXT: (if (result i32) ;; OPTIN-NEXT: (local.get $param) ;; OPTIN-NEXT: (then - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (else - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.ne + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $multi-block (param $param i32) @@ -525,10 +594,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-block-split-yes (type $0) (param $param i32) @@ -545,7 +620,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -587,10 +665,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $loop ;; CHECK-NEXT: (local.get $param) @@ -604,7 +688,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (loop $loop ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -725,10 +812,15 @@ ;; CHECK-NEXT: (local $eq eqref) ;; CHECK-NEXT: (local $nn-eq (ref eq)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.eq @@ -737,10 +829,15 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $default-var (type $0) (param $param i32) @@ -748,10 +845,14 @@ ;; OPTIN-NEXT: (local $eq eqref) ;; OPTIN-NEXT: (local $nn-eq (ref eq)) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.eqz @@ -759,10 +860,14 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (ref.is_null + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (ref.is_null + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $default-var (param $param i32) @@ -817,10 +922,15 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -910,10 +1020,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -1030,16 +1146,28 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1060,16 +1188,28 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1128,21 +1268,36 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1155,21 +1310,36 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (block + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (block + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1231,23 +1401,38 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1260,13 +1445,22 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1329,7 +1523,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) @@ -1347,7 +1544,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 30) @@ -1391,7 +1591,7 @@ ;; CHECK: (func $conditional-binary-contradiction-other-default (type $1) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) @@ -1402,7 +1602,7 @@ ;; OPTIN: (func $conditional-binary-contradiction-other-default (type $1) ;; OPTIN-NEXT: (local $x i32) ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 30) @@ -1434,7 +1634,10 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) @@ -1487,10 +1690,17 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1502,10 +1712,17 @@ ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (block + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1640,7 +1857,10 @@ ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $conditional-br_if_2 (type $0) (param $param i32) @@ -1663,7 +1883,10 @@ ;; OPTIN-NEXT: (return) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $conditional-br_if_2 (param $param i32) @@ -1753,7 +1976,9 @@ ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $br_on_null (type $6) (param $param anyref) @@ -1774,7 +1999,9 @@ ;; OPTIN-NEXT: (return) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (ref.is_null + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $br_on_null (param $param anyref) @@ -1818,7 +2045,9 @@ ;; CHECK-NEXT: (local.get $param) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) @@ -1839,7 +2068,9 @@ ;; OPTIN-NEXT: (local.get $param) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (ref.is_null + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (return) ;; OPTIN-NEXT: ) @@ -3236,13 +3467,19 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-local-copy (type $1) @@ -3252,13 +3489,19 @@ ;; OPTIN-NEXT: (i32.const 10) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $y - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 10) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $multi-local-copy @@ -3300,13 +3543,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -3418,15 +3667,21 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3437,15 +3692,21 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: (local.get $y) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -3487,14 +3748,20 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eq ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3505,15 +3772,21 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: (local.get $y) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -3769,14 +4042,14 @@ ;; CHECK: (func $iloop (type $9) (param $0 f32) ;; CHECK-NEXT: (local $1 f32) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (f32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (loop ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (f32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3794,14 +4067,14 @@ ;; OPTIN: (func $iloop (type $9) (param $0 f32) ;; OPTIN-NEXT: (local $1 f32) ;; OPTIN-NEXT: (local.set $0 - ;; OPTIN-NEXT: (local.get $1) + ;; OPTIN-NEXT: (f32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (loop ;; OPTIN-NEXT: (local.set $1 - ;; OPTIN-NEXT: (local.get $0) + ;; OPTIN-NEXT: (f32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -3855,8 +4128,11 @@ ;; CHECK-NEXT: (local $e eqref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3865,8 +4141,10 @@ ;; OPTIN-NEXT: (local $e eqref) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 1) - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (ref.is_null + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -3892,20 +4170,25 @@ ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $relevant-copy (type $1) ;; OPTIN-NEXT: (local $x i32) ;; OPTIN-NEXT: (local $y i32) ;; OPTIN-NEXT: (local.set $y - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $relevant-copy @@ -3930,16 +4213,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-lt_s (type $1) @@ -3948,13 +4243,22 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -3998,16 +4302,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.le_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-le_s (type $1) @@ -4016,16 +4332,28 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.le_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.le_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.le_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $constant-inequalities-le_s @@ -4065,16 +4393,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-gt_s (type $1) @@ -4083,16 +4423,28 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $constant-inequalities-gt_s @@ -4132,16 +4484,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ge_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ge_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ge_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ge_s + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-ge_s (type $1) @@ -4150,13 +4514,22 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -4199,16 +4572,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-lt_u (type $1) @@ -4217,13 +4602,22 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.lt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -4266,16 +4660,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.le_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.le_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.le_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.le_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-le_u (type $1) @@ -4284,13 +4690,22 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.le_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.le_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.le_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -4333,16 +4748,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-gt_u (type $1) @@ -4351,13 +4778,22 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -4400,16 +4836,28 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 41) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 43) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.ge_u + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-ge_u (type $1) @@ -4418,13 +4866,22 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 41) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.ge_u + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 43) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -4465,24 +4922,25 @@ ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $flipped-contradiction (type $4) (result i32) ;; OPTIN-NEXT: (local $x i32) ;; OPTIN-NEXT: (loop $loop ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (i32.const 1) - ;; OPTIN-NEXT: ) - ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (unreachable) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $flipped-contradiction (result i32) @@ -4528,7 +4986,7 @@ ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (i32.eqz ;; OPTIN-NEXT: (i32.const 0) @@ -4564,10 +5022,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $tee (type $1) @@ -4579,10 +5043,16 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $tee @@ -4617,7 +5087,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $fallthrough (type $1) @@ -4629,7 +5102,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $fallthrough @@ -4655,7 +5131,7 @@ ;; CHECK-NEXT: (local $w i32) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.get $z) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $z @@ -4663,11 +5139,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $w ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.get $z) + ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $fallthrough-get (type $1) @@ -4676,7 +5155,7 @@ ;; OPTIN-NEXT: (local $w i32) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (block (result i32) - ;; OPTIN-NEXT: (local.get $z) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $z @@ -4684,11 +5163,14 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $w ;; OPTIN-NEXT: (block (result i32) - ;; OPTIN-NEXT: (local.get $z) + ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $fallthrough-get @@ -4731,7 +5213,7 @@ ;; CHECK-NEXT: (local $w i32) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (local.tee $param - ;; CHECK-NEXT: (local.get $z) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $z @@ -4739,11 +5221,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $w ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.get $z) + ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $fallthrough-tee (type $0) (param $param i32) @@ -4752,7 +5237,7 @@ ;; OPTIN-NEXT: (local $w i32) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (local.tee $param - ;; OPTIN-NEXT: (local.get $z) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $z @@ -4760,11 +5245,14 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $w ;; OPTIN-NEXT: (block (result i32) - ;; OPTIN-NEXT: (local.get $z) + ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $fallthrough-tee (param $param i32) @@ -4802,7 +5290,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4814,7 +5305,9 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -4845,7 +5338,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i64.eq + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4857,7 +5353,9 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i64.eqz + ;; OPTIN-NEXT: (i64.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -5087,13 +5585,22 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -5134,13 +5641,21 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (else @@ -5485,7 +6000,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -5512,7 +6030,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (else @@ -5596,13 +6117,22 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.const 0) @@ -5645,13 +6175,22 @@ ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -5758,7 +6297,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5782,7 +6324,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (block + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -5925,7 +6470,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5940,7 +6487,9 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6059,7 +6608,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6076,7 +6628,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: (i32.const 42) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6288,7 +6843,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6302,7 +6859,9 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6444,7 +7003,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6461,7 +7023,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6511,10 +7076,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.eq @@ -6546,10 +7117,16 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.eq @@ -6630,13 +7207,22 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: (i32.const 20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6662,13 +7248,22 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: (i32.const 20) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6739,10 +7334,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: (i32.const 10) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: (i32.const 30) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6768,10 +7369,16 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: (i32.const 10) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: (i32.const 30) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6875,5 +7482,41 @@ ) ) ) + + ;; CHECK: (func $local.get (type $0) (param $x i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get (type $0) (param $x i32) + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + (func $local.get (param $x i32) + (if + (local.get $x) + (then + (drop + (local.get $x) + ) + ) + (else + (drop + (local.get $x) + ) + ) + ) + ) ) From eb1cf7ec2c6e421c47c148fe8761e8d19ca96631 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 14:11:35 -0700 Subject: [PATCH 02/36] work --- src/passes/ConstraintAnalysis.cpp | 21 ++++++++++++------ test/lit/passes/constraint-analysis.wast | 27 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 2c98b9f99a9..d1ebc091744 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -426,7 +426,9 @@ struct ConstraintAnalysis #endif if (!constraints.unreachable) { applyToConstraints(*currp, constraints); - optimizeExpression(currp, constraints); + if (optimizeExpression(currp, constraints)) { + refinalize = true; + } } else { // This is unreachable code: just mark it so. *currp = getDroppedChildrenAndAppend( @@ -445,17 +447,21 @@ struct ConstraintAnalysis } } - // Given an expression and the constraints on it, optimize it. - void optimizeExpression(Expression** currp, + // Given an expression and the constraints on it, optimize it. Returns whether + // we changed types (which requires refinalization). + bool optimizeExpression(Expression** currp, const BasicBlockConstraintMap& constraints) { auto* curr = *currp; if (auto* get = curr->dynCast()) { // A bare local.get can be optimized, if we know that local is a constant. if (auto lit = constraints.get(get->index).getLiteral()) { + auto old = curr->type; *currp = Builder(*getModule()).makeConstantExpression(*lit); + auto changed = (*currp)->type != old; + return changed; } - return; + return false; } // Note that we don't need to try to parse a series of constraints with @@ -463,7 +469,7 @@ struct ConstraintAnalysis // simply optimize it as we walk it, each time handling one. auto parsed = LocalConstraint::parse(curr); if (!parsed) { - return; + return false; } if (!checkRelevancy(*parsed)) { #ifndef NDEBUG @@ -472,14 +478,14 @@ struct ConstraintAnalysis // below on checkRelevancy. assert(originalActions.contains(curr)); #endif - return; + return false; } auto result = constraints.proves(*parsed); if (result == Unknown) { // If we parsed something using two locals, like x != y, we can also look // for the flipped condition among y's constraints TODO - return; + return false; } // We know the result! @@ -488,6 +494,7 @@ struct ConstraintAnalysis LiteralUtils::makeFromInt32(result == True ? 1 : 0, curr->type, wasm); *currp = getDroppedChildrenAndAppend( curr, wasm, getPassOptions(), value, DropMode::IgnoreParentEffects); + return false; } // Given a predecessor and one of its successors, find new constraints that diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 2b28b65a7e2..701b2a14138 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -7518,5 +7518,32 @@ ) ) ) + + ;; CHECK: (func $local.get.refinalize (type $1) + ;; CHECK-NEXT: (local $x anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result nullref) + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get.refinalize (type $1) + ;; OPTIN-NEXT: (local $x anyref) + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (block (result nullref) + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + (func $local.get.refinalize + (local $x anyref) + ;; The local.get below is null. After we apply a null there, we refinalize + ;; the block's type to nullref. + (drop + (block (result anyref) + (local.get $x) + ) + ) + ) ) From 6e64e104de5e2ac760bb7a570edb2d7e2306f1d1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 14:31:07 -0700 Subject: [PATCH 03/36] work --- src/passes/ConstraintAnalysis.cpp | 6 +++++ test/lit/passes/constraint-analysis.wast | 29 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index d1ebc091744..278bb4d2d5d 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -457,6 +457,12 @@ struct ConstraintAnalysis // A bare local.get can be optimized, if we know that local is a constant. if (auto lit = constraints.get(get->index).getLiteral()) { auto old = curr->type; + if (old.isNonNullable() && lit->isNull()) { + // This is a non-nullable local, into which we wrote an uninhabitable + // type (ref.as_non_null of a null). There is nothing to emit, and we + // would not validate if we did + return false; + } *currp = Builder(*getModule()).makeConstantExpression(*lit); auto changed = (*currp)->type != old; return changed; diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 701b2a14138..8f1d132d82a 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -7545,5 +7545,34 @@ ) ) ) + + ;; CHECK: (func $local.get.no (type $12) (result (ref any)) + ;; CHECK-NEXT: (local $x (ref any)) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (ref.as_non_null + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get.no (type $12) (result (ref any)) + ;; OPTIN-NEXT: (local $x (ref any)) + ;; OPTIN-NEXT: (local.set $x + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: ) + (func $local.get.no (result (ref any)) + (local $x (ref any)) + ;; An uninhabitable value is written into a non-nullable local, then we do + ;; a local.get of it. There is no value we can write for the local, so we do + ;; not emit one. + (local.set $x + (ref.as_non_null + (ref.null none) + ) + ) + (local.get $x) + ) ) From fbf0903198f4820937a7fe3b693f4e6b5579d872 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 14:45:23 -0700 Subject: [PATCH 04/36] work --- src/ir/constraint.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ir/constraint.cpp b/src/ir/constraint.cpp index 0c9cc14fefe..e6871a1b95c 100644 --- a/src/ir/constraint.cpp +++ b/src/ir/constraint.cpp @@ -201,6 +201,11 @@ Result provesConstantPair(Abstract::Op aOp, bool recursing = false) { using namespace Abstract; + // SIMD types cannot be operated on (wasm does not have v128.eq etc.). + if (aConstant.type == Type::v128) { + return Unknown; + } + // a == A =?=> a op B. Simply apply A to the operation against B. if (aOp == Eq) { switch (bOp) { From eb629161af6ff8808c132fb4dd55ff1356817b06 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 15:39:06 -0700 Subject: [PATCH 05/36] work --- src/passes/ConstraintAnalysis.cpp | 7 ++++++- test/lit/passes/constraint-analysis.wast | 21 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 278bb4d2d5d..71e3dc7ffc8 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -460,7 +460,12 @@ struct ConstraintAnalysis if (old.isNonNullable() && lit->isNull()) { // This is a non-nullable local, into which we wrote an uninhabitable // type (ref.as_non_null of a null). There is nothing to emit, and we - // would not validate if we did + // would not validate if we did. + return false; + } + if (old == Type::v128) { + // We also avoid writing v128 constants, which are large, the same as + // Precompute. return false; } *currp = Builder(*getModule()).makeConstantExpression(*lit); diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 8f1d132d82a..a30c4276505 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -7574,5 +7574,24 @@ ) (local.get $x) ) -) + ;; CHECK: (func $local.get.no.v128 (type $1) + ;; CHECK-NEXT: (local $x v128) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get.no.v128 (type $1) + ;; OPTIN-NEXT: (local $x v128) + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + (func $local.get.no.v128 + (local $x v128) + ;; We know the value here, but do not copy v128 constants, which are large. + (drop + (local.get $x) + ) + ) +) From f9ea3411ce09a5e765e7a3c957b0a1d683056d1c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 16:30:20 -0700 Subject: [PATCH 06/36] work --- src/passes/ConstraintAnalysis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 71e3dc7ffc8..9e9a3971b17 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -463,7 +463,7 @@ struct ConstraintAnalysis // would not validate if we did. return false; } - if (old == Type::v128) { + if (old == Type::v128) { // XXX remove old relevant locals - now all are relevant. just filter out types we can do nothing for, like v128 and remove thiss // We also avoid writing v128 constants, which are large, the same as // Precompute. return false; From 8d3cac81d9352b10031e7ac5ffbe99d0ce65b9d3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 17 Sep 2026 16:50:52 -0700 Subject: [PATCH 07/36] work --- test/lit/passes/constraint-analysis.wast | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index a30c4276505..aa2b5859a19 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -7594,4 +7594,39 @@ (local.get $x) ) ) + + ;; CHECK: (func $local.get.unreachable (type $1) + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get.unreachable (type $1) + ;; OPTIN-NEXT: (local $x i32) + ;; OPTIN-NEXT: (if + ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (then + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + (func $local.get.unreachable + (local $x i32) + (if + (local.get $x) + (then + ;; $x is 0, so we never get here, and this is unreachable. + (drop + (local.get $x) + ) + ) + ) + ) ) From 1ca0357d5b0c4db51e9f635179dc15eb925c4b09 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 09:48:52 -0700 Subject: [PATCH 08/36] fix --- src/passes/ConstraintAnalysis.cpp | 4 +- .../lit/passes/constraint-analysis-float.wast | 12 ++--- test/lit/passes/constraint-analysis.wast | 53 +++++++++++++++++-- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 9e9a3971b17..e0d4ad7be9a 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -197,7 +197,9 @@ struct ConstraintAnalysis void visitLocalGet(LocalGet* curr) { addAction(); - relevantLocals[curr->index] = true; + if (isRelevantType(curr->type)) { + relevantLocals[curr->index] = true; + } } void visitLocalSet(LocalSet* curr) { diff --git a/test/lit/passes/constraint-analysis-float.wast b/test/lit/passes/constraint-analysis-float.wast index 2fd9389ec69..2298cef7d31 100644 --- a/test/lit/passes/constraint-analysis-float.wast +++ b/test/lit/passes/constraint-analysis-float.wast @@ -11,8 +11,8 @@ ;; CHECK-NEXT: (local $f f64) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: (local.get $f) + ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (nop) @@ -50,7 +50,7 @@ ;; CHECK-NEXT: (local $f f64) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: (f64.const -0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then @@ -59,7 +59,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (f64.eq - ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: (f64.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then @@ -119,8 +119,8 @@ ;; CHECK-NEXT: (f64.const nan:0x8000000000000) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (f64.const nan:0x8000000000000) - ;; CHECK-NEXT: (f64.const nan:0x8000000000000) + ;; CHECK-NEXT: (local.get $nan) + ;; CHECK-NEXT: (local.get $nan) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; FASTM: (func $float-ne-nan (type $1) (result i32) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index aa2b5859a19..fdf357554ea 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -4042,14 +4042,14 @@ ;; CHECK: (func $iloop (type $9) (param $0 f32) ;; CHECK-NEXT: (local $1 f32) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (loop ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4067,14 +4067,14 @@ ;; OPTIN: (func $iloop (type $9) (param $0 f32) ;; OPTIN-NEXT: (local $1 f32) ;; OPTIN-NEXT: (local.set $0 - ;; OPTIN-NEXT: (f32.const 0) + ;; OPTIN-NEXT: (local.get $1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (loop ;; OPTIN-NEXT: (local.set $1 - ;; OPTIN-NEXT: (f32.const 0) + ;; OPTIN-NEXT: (local.get $0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -7629,4 +7629,49 @@ ) ) ) + + ;; CHECK: (func $local.get.float (type $1) + ;; CHECK-NEXT: (local $x f64) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (f64.eq + ;; CHECK-NEXT: (local.tee $x + ;; CHECK-NEXT: (f64.const nan:0x8000000000000) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get.float (type $1) + ;; OPTIN-NEXT: (local $x f64) + ;; OPTIN-NEXT: (if + ;; OPTIN-NEXT: (f64.eq + ;; OPTIN-NEXT: (local.tee $x + ;; OPTIN-NEXT: (f64.const nan:0x8000000000000) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (then + ;; OPTIN-NEXT: (nop) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + (func $local.get.float + (local $x f64) + ;; The condition here ends up comparing $x to itself. That is normally 1, + ;; but not with a nan. We do not optimize floats for this reason. + (if + (f64.eq + (local.tee $x + (f64.const nan) + ) + (local.get $x) + ) + (then + (nop) + ) + ) + ) ) From f23e45cb1ff5f08f0bed6936dab5528700db1e4c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 10:23:18 -0700 Subject: [PATCH 09/36] fix --- src/passes/ConstraintAnalysis.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index e0d4ad7be9a..0e49a8b97c9 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -161,6 +161,13 @@ struct ConstraintAnalysis bool fastMath; bool isRelevantType(Type type) { + if (type == Type::v128) { + // TODO optimize SIMD where it makes sense, but for now we don't want to + // do things like propagate v128 constants, which are large (the same as + // Precompute). + return false; + } + // Floating-point math does not follow the basic rules of logic (for // example, NaN < NaN and NaN >= NaN are both false, despite the law of the // excluded middle). Constraints follow the rules of logic, so we cannot @@ -465,11 +472,7 @@ struct ConstraintAnalysis // would not validate if we did. return false; } - if (old == Type::v128) { // XXX remove old relevant locals - now all are relevant. just filter out types we can do nothing for, like v128 and remove thiss - // We also avoid writing v128 constants, which are large, the same as - // Precompute. - return false; - } +waka *currp = Builder(*getModule()).makeConstantExpression(*lit); auto changed = (*currp)->type != old; return changed; From 9262af529fb2b3d24d4371be6dc407205b135434 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 10:31:30 -0700 Subject: [PATCH 10/36] work --- src/passes/ConstraintAnalysis.cpp | 21 +++++++++--------- test/lit/passes/constraint-analysis.wast | 28 ++++++++++++------------ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 0e49a8b97c9..58f321fcce5 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -163,8 +163,7 @@ struct ConstraintAnalysis bool isRelevantType(Type type) { if (type == Type::v128) { // TODO optimize SIMD where it makes sense, but for now we don't want to - // do things like propagate v128 constants, which are large (the same as - // Precompute). + // do things like propagate v128 constants, which are large. return false; } @@ -465,16 +464,16 @@ struct ConstraintAnalysis if (auto* get = curr->dynCast()) { // A bare local.get can be optimized, if we know that local is a constant. if (auto lit = constraints.get(get->index).getLiteral()) { - auto old = curr->type; - if (old.isNonNullable() && lit->isNull()) { - // This is a non-nullable local, into which we wrote an uninhabitable - // type (ref.as_non_null of a null). There is nothing to emit, and we - // would not validate if we did. - return false; + auto oldType = curr->type; + Builder builder(*getModule()); + auto* rep = builder.makeConstantExpression(*lit); + if (!Type::isSubType(rep->type, oldType)) { + // The value we know must exist here is impossible, which means it was + // cast in a way that traps at runtime. This code is unreachable. + rep = builder.makeUnreachable(); } -waka - *currp = Builder(*getModule()).makeConstantExpression(*lit); - auto changed = (*currp)->type != old; + auto changed = rep->type != oldType; + *currp = rep; return changed; } return false; diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index fdf357554ea..6d0cbe998fe 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -7546,30 +7546,30 @@ ) ) - ;; CHECK: (func $local.get.no (type $12) (result (ref any)) - ;; CHECK-NEXT: (local $x (ref any)) + ;; CHECK: (func $local.get.impossible.cast (type $12) (result (ref func)) + ;; CHECK-NEXT: (local $x (ref func)) ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: (ref.cast (ref nofunc) + ;; CHECK-NEXT: (ref.null nofunc) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) - ;; OPTIN: (func $local.get.no (type $12) (result (ref any)) - ;; OPTIN-NEXT: (local $x (ref any)) + ;; OPTIN: (func $local.get.impossible.cast (type $12) (result (ref func)) + ;; OPTIN-NEXT: (local $x (ref func)) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (unreachable) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.get $x) ;; OPTIN-NEXT: ) - (func $local.get.no (result (ref any)) - (local $x (ref any)) - ;; An uninhabitable value is written into a non-nullable local, then we do - ;; a local.get of it. There is no value we can write for the local, so we do - ;; not emit one. + (func $local.get.impossible.cast (result (ref func)) + (local $x (ref func)) + ;; The cast here traps at runtime. We do not have a valid value to put in + ;; place of the local.get (it is not refined enough), but we know it is + ;; unreachable. (local.set $x - (ref.as_non_null - (ref.null none) + (ref.cast (ref func) + (ref.null func) ) ) (local.get $x) From 7ce181cb67d32a14a6485a5723e38ed592a0814d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 10:38:27 -0700 Subject: [PATCH 11/36] work --- src/passes/ConstraintAnalysis.cpp | 90 ++----------------- .../lit/passes/constraint-analysis-float.wast | 4 +- test/lit/passes/constraint-analysis.wast | 8 +- 3 files changed, 14 insertions(+), 88 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 58f321fcce5..dacc78a4304 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -136,27 +136,8 @@ struct ConstraintAnalysis // state in the function. bool ignoreBranchesOutsideOfFunc = true; - // A relevant local is one that is used as part of an expression that we can - // optimize (often, many locals are irrelevant). + // A relevant local is one that we care about optimizing. std::vector relevantLocals; - // Track local copies too, as if one local is relevant, it can make another - // relevant. We store pairs here of key=target, value=sources, which is the - // direction we will flow in the analysis: if we check x == 10, making it - // relevant, and x = y earlier, then we must track that source, y, so that we - // know what it writes to x. - std::unordered_map> localCopySources; - - void maybeMarkRelevant(Expression* curr) { - // If this parses into a constraint on a local, that local is relevant. - for (auto& pair : ParsedAndedConstraints::parseCondition(curr)) { - if (isRelevantType(getFunction()->getLocalType(pair.local))) { - relevantLocals[pair.local] = true; - if (auto* other = std::get_if(&pair.constraint.term)) { - relevantLocals[*other] = true; - } - } - } - } bool fastMath; @@ -203,6 +184,10 @@ struct ConstraintAnalysis void visitLocalGet(LocalGet* curr) { addAction(); + + // To be relevant for optimization, there must be a local.get (otherwise, + // nothing can be optimized as this is not used), and the type must be + // relevant. if (isRelevantType(curr->type)) { relevantLocals[curr->index] = true; } @@ -211,48 +196,26 @@ struct ConstraintAnalysis void visitLocalSet(LocalSet* curr) { addAction(); - auto* value = curr->value; - while (true) { - if (auto* get = value->dynCast()) { - localCopySources[curr->index].push_back(get->index); - // No children to look into. - break; - } - - if (auto* tee = value->dynCast()) { - localCopySources[curr->index].push_back(tee->index); - value = tee->value; - continue; - } - - // Look for other possible tees and gets that fall through. - auto* next = Properties::getImmediateFallthrough( - value, getPassOptions(), *getModule()); - if (next == value) { - break; - } - value = next; + // A tee is also a get, so it can mark a local as relevant, like LocalGet. + if (isRelevantType(curr->type)) { + relevantLocals[curr->index] = true; } } void visitUnary(Unary* curr) { addAction(); - maybeMarkRelevant(curr); } void visitBinary(Binary* curr) { addAction(); - maybeMarkRelevant(curr); } void visitRefEq(RefEq* curr) { addAction(); - maybeMarkRelevant(curr); } void visitRefIsNull(RefIsNull* curr) { addAction(); - maybeMarkRelevant(curr); } static void doStartIfTrue(ConstraintAnalysis* self, Expression** currp) { @@ -261,9 +224,6 @@ struct ConstraintAnalysis if (self->currBasicBlock) { self->currBasicBlock->contents.brancher = *currp; } - if (auto* iff = (*currp)->dynCast()) { - self->maybeMarkRelevant(iff->condition); - } Super::doStartIfTrue(self, currp); } @@ -271,13 +231,6 @@ struct ConstraintAnalysis if (self->currBasicBlock) { self->currBasicBlock->contents.brancher = *currp; } - if (auto* br = (*currp)->dynCast()) { - if (br->condition) { - self->maybeMarkRelevant(br->condition); - } - } else if (auto* brOn = (*currp)->dynCast()) { - self->maybeMarkRelevant(brOn->ref); - } Super::doEndBranch(self, currp); } @@ -287,37 +240,10 @@ struct ConstraintAnalysis return; } - computeRelevantLocals(); flow(); optimize(); } - // Every relevant local makes the things it is copied to relevant as well. - void computeRelevantLocals() { - // We'll start from all relevant locals, and flow from there. - UniqueDeferredQueue work; - for (Index i = 0; i < relevantLocals.size(); i++) { - if (relevantLocals[i]) { - work.push(i); - } - } - - // Flow. - while (!work.empty()) { - auto curr = work.pop(); - assert(relevantLocals[curr]); - if (auto iter = localCopySources.find(curr); - iter != localCopySources.end()) { - for (auto source : iter->second) { - if (!relevantLocals[source]) { - relevantLocals[source] = true; - work.push(source); - } - } - } - } - } - // Flow infos around until we have inferred all we can about the constraints // in each location. void flow() { diff --git a/test/lit/passes/constraint-analysis-float.wast b/test/lit/passes/constraint-analysis-float.wast index 2298cef7d31..9bb30927d6e 100644 --- a/test/lit/passes/constraint-analysis-float.wast +++ b/test/lit/passes/constraint-analysis-float.wast @@ -119,8 +119,8 @@ ;; CHECK-NEXT: (f64.const nan:0x8000000000000) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.get $nan) - ;; CHECK-NEXT: (local.get $nan) + ;; CHECK-NEXT: (f64.const nan:0x8000000000000) + ;; CHECK-NEXT: (f64.const nan:0x8000000000000) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; FASTM: (func $float-ne-nan (type $1) (result i32) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 6d0cbe998fe..30feff0c07f 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -4042,14 +4042,14 @@ ;; CHECK: (func $iloop (type $9) (param $0 f32) ;; CHECK-NEXT: (local $1 f32) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (f32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (loop ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (f32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4067,14 +4067,14 @@ ;; OPTIN: (func $iloop (type $9) (param $0 f32) ;; OPTIN-NEXT: (local $1 f32) ;; OPTIN-NEXT: (local.set $0 - ;; OPTIN-NEXT: (local.get $1) + ;; OPTIN-NEXT: (f32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (loop ;; OPTIN-NEXT: (local.set $1 - ;; OPTIN-NEXT: (local.get $0) + ;; OPTIN-NEXT: (f32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) From 0eb6ad378c7d1474ba5dea9aa326b17bcdccb448 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 10:38:35 -0700 Subject: [PATCH 12/36] work --- src/passes/ConstraintAnalysis.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index dacc78a4304..adf820f718e 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -202,21 +202,13 @@ struct ConstraintAnalysis } } - void visitUnary(Unary* curr) { - addAction(); - } + void visitUnary(Unary* curr) { addAction(); } - void visitBinary(Binary* curr) { - addAction(); - } + void visitBinary(Binary* curr) { addAction(); } - void visitRefEq(RefEq* curr) { - addAction(); - } + void visitRefEq(RefEq* curr) { addAction(); } - void visitRefIsNull(RefIsNull* curr) { - addAction(); - } + void visitRefIsNull(RefIsNull* curr) { addAction(); } static void doStartIfTrue(ConstraintAnalysis* self, Expression** currp) { // We are right after the condition, so we are in the block before the If's From 87922a3d07b3f2218cf767172a89ecf757701099 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 10:38:51 -0700 Subject: [PATCH 13/36] work --- src/passes/ConstraintAnalysis.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index adf820f718e..31b30e8359f 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -203,11 +203,8 @@ struct ConstraintAnalysis } void visitUnary(Unary* curr) { addAction(); } - void visitBinary(Binary* curr) { addAction(); } - void visitRefEq(RefEq* curr) { addAction(); } - void visitRefIsNull(RefIsNull* curr) { addAction(); } static void doStartIfTrue(ConstraintAnalysis* self, Expression** currp) { From 02b062f2881c11d8d7d2d7bfb3f73cd5ff481c2d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 12:39:33 -0700 Subject: [PATCH 14/36] work --- src/passes/ConstraintAnalysis.cpp | 13 +++++++------ test/lit/passes/constraint-analysis-float.wast | 4 ++-- test/lit/passes/constraint-analysis.wast | 8 ++++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 31b30e8359f..688d794c0b0 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -183,22 +183,23 @@ struct ConstraintAnalysis } void visitLocalGet(LocalGet* curr) { - addAction(); - // To be relevant for optimization, there must be a local.get (otherwise, // nothing can be optimized as this is not used), and the type must be // relevant. if (isRelevantType(curr->type)) { + addAction(); relevantLocals[curr->index] = true; } } void visitLocalSet(LocalSet* curr) { - addAction(); + if (isRelevantType(getFunction()->getLocalType(curr->index))) { + addAction(); - // A tee is also a get, so it can mark a local as relevant, like LocalGet. - if (isRelevantType(curr->type)) { - relevantLocals[curr->index] = true; + // A tee is also a get, so it can mark a local as relevant, like LocalGet. + if (curr->isTee()) { + relevantLocals[curr->index] = true; + } } } diff --git a/test/lit/passes/constraint-analysis-float.wast b/test/lit/passes/constraint-analysis-float.wast index 9bb30927d6e..2298cef7d31 100644 --- a/test/lit/passes/constraint-analysis-float.wast +++ b/test/lit/passes/constraint-analysis-float.wast @@ -119,8 +119,8 @@ ;; CHECK-NEXT: (f64.const nan:0x8000000000000) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (f64.const nan:0x8000000000000) - ;; CHECK-NEXT: (f64.const nan:0x8000000000000) + ;; CHECK-NEXT: (local.get $nan) + ;; CHECK-NEXT: (local.get $nan) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; FASTM: (func $float-ne-nan (type $1) (result i32) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 30feff0c07f..6d0cbe998fe 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -4042,14 +4042,14 @@ ;; CHECK: (func $iloop (type $9) (param $0 f32) ;; CHECK-NEXT: (local $1 f32) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (loop ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4067,14 +4067,14 @@ ;; OPTIN: (func $iloop (type $9) (param $0 f32) ;; OPTIN-NEXT: (local $1 f32) ;; OPTIN-NEXT: (local.set $0 - ;; OPTIN-NEXT: (f32.const 0) + ;; OPTIN-NEXT: (local.get $1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (loop ;; OPTIN-NEXT: (local.set $1 - ;; OPTIN-NEXT: (f32.const 0) + ;; OPTIN-NEXT: (local.get $0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) From ebd23e66850b102ee9e8e62bfd2c48e490fec2c5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 13:13:10 -0700 Subject: [PATCH 15/36] work --- src/ir/constraint.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ir/constraint.cpp b/src/ir/constraint.cpp index e6871a1b95c..0c9cc14fefe 100644 --- a/src/ir/constraint.cpp +++ b/src/ir/constraint.cpp @@ -201,11 +201,6 @@ Result provesConstantPair(Abstract::Op aOp, bool recursing = false) { using namespace Abstract; - // SIMD types cannot be operated on (wasm does not have v128.eq etc.). - if (aConstant.type == Type::v128) { - return Unknown; - } - // a == A =?=> a op B. Simply apply A to the operation against B. if (aOp == Eq) { switch (bOp) { From 6e56a0eff9e7997371cc649fac1e39625efaa16f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 13:15:11 -0700 Subject: [PATCH 16/36] work --- src/passes/ConstraintAnalysis.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 688d794c0b0..076878e1963 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -714,3 +714,6 @@ struct ConstraintAnalysis Pass* createConstraintAnalysisPass() { return new ConstraintAnalysis(); } } // namespace wasm + +// TODO: test option to not do the local.get opts in optimizeExpr() here +// TODO why is fast-math brokenn From 783f44abd77c8cf963be8526a6a45fc090ad7bce Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 16:15:43 -0700 Subject: [PATCH 17/36] work --- src/passes/ConstraintAnalysis.cpp | 87 +- .../lit/passes/constraint-analysis-float.wast | 20 +- .../lit/passes/constraint-analysis-loops.wast | 10 +- test/lit/passes/constraint-analysis.wast | 989 ++++-------------- 4 files changed, 271 insertions(+), 835 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 076878e1963..816ab5bda34 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -339,6 +339,30 @@ struct ConstraintAnalysis // If we make things unreachable, we must refinalize. bool refinalize = false; + // If we find local.gets that we can optimize, we queue those changes here + // (each item being currp, the pointer to the LocalGet, and then the value + // to replace it with). This order is useful for the following reason: + // consider a simple expression, like this, + // + // (i32.eqz + // (local.get $x) + // ) + // + // If we can infer that x is 42, and we do that first, then we end up with + // eqz of 42. That is something Precompute can handle, but not us - this + // pass only looks at constraints on locals. We do not lose any optimization + // power by leaving this to Precompute, but it is less efficient and may + // require more cycles; it is also less convenient for testing, as we must + // avoid inferring local.gets in order to fully test constraint + // optimization. + // + // Instead, we queue local.get changes here. If, say, we optimize that eqz, + // then the local.get change ends up unnoticable (it changes the Unary + // which was removed from the tree anyhow, which is not harmful aside from a + // tiny bit of wasted work, but that waste is less than waiting for + // Precompute). + std::vector> getOptimizations; + for (auto& block : basicBlocks) { // Follow the general shape of flow(): we need to see what the state is // at each intermediate point inside the block. (Flowing between blocks is @@ -350,8 +374,10 @@ struct ConstraintAnalysis #endif if (!constraints.unreachable) { applyToConstraints(*currp, constraints); - if (optimizeExpression(currp, constraints)) { - refinalize = true; + if (auto* rep = optimizeLocalGet(currp, constraints)) { + getOptimizations.emplace_back(currp, rep); + } else { + optimizeConstraint(currp, constraints); } } else { // This is unreachable code: just mark it so. @@ -365,42 +391,53 @@ struct ConstraintAnalysis } } + // Apply local.get optimizations after all that. + for (auto& [currp, rep] : getOptimizations) { + auto oldType = (*currp)->type; + if (!Type::isSubType(rep->type, oldType)) { + // The value we know must exist here is impossible, which means it was + // cast in a way that traps at runtime. This code is unreachable. + rep = Builder(*getModule()).makeUnreachable(); + refinalize = true; + } else if (rep->type != oldType) { + // We are refining. + refinalize = true; + } + *currp = rep; + } + if (refinalize) { ReFinalize().walkFunctionInModule(getFunction(), getModule()); EHUtils::handleBlockNestedPops(getFunction(), *getModule()); } } - // Given an expression and the constraints on it, optimize it. Returns whether - // we changed types (which requires refinalization). - bool optimizeExpression(Expression** currp, + // Given an expression and the constraints on it, see if it is a local.get + // that we can optimize, and return the value to optimize to, if so. + Expression* optimizeLocalGet(Expression** currp, const BasicBlockConstraintMap& constraints) { - auto* curr = *currp; - - if (auto* get = curr->dynCast()) { - // A bare local.get can be optimized, if we know that local is a constant. + // A bare local.get can be optimized, if we know that local is a constant. + if (auto* get = (*currp)->dynCast()) { if (auto lit = constraints.get(get->index).getLiteral()) { - auto oldType = curr->type; - Builder builder(*getModule()); - auto* rep = builder.makeConstantExpression(*lit); - if (!Type::isSubType(rep->type, oldType)) { - // The value we know must exist here is impossible, which means it was - // cast in a way that traps at runtime. This code is unreachable. - rep = builder.makeUnreachable(); - } - auto changed = rep->type != oldType; - *currp = rep; - return changed; + return Builder(*getModule()).makeConstantExpression(*lit); } - return false; } + return nullptr; + } + + // Given an expression and the constraints on it, parse it into a constraint + // if we can, and optimize it. + void optimizeConstraint(Expression** currp, + const BasicBlockConstraintMap& constraints) { + auto* curr = *currp; + // Note that we don't need to try to parse a series of constraints with // ParsedAndedConstraints: if there is a tree of ANDed things, we will // simply optimize it as we walk it, each time handling one. auto parsed = LocalConstraint::parse(curr); if (!parsed) { - return false; + return; } if (!checkRelevancy(*parsed)) { #ifndef NDEBUG @@ -409,14 +446,14 @@ struct ConstraintAnalysis // below on checkRelevancy. assert(originalActions.contains(curr)); #endif - return false; + return; } auto result = constraints.proves(*parsed); if (result == Unknown) { // If we parsed something using two locals, like x != y, we can also look // for the flipped condition among y's constraints TODO - return false; + return; } // We know the result! @@ -425,7 +462,7 @@ struct ConstraintAnalysis LiteralUtils::makeFromInt32(result == True ? 1 : 0, curr->type, wasm); *currp = getDroppedChildrenAndAppend( curr, wasm, getPassOptions(), value, DropMode::IgnoreParentEffects); - return false; + return; } // Given a predecessor and one of its successors, find new constraints that diff --git a/test/lit/passes/constraint-analysis-float.wast b/test/lit/passes/constraint-analysis-float.wast index 2298cef7d31..348ec8d5941 100644 --- a/test/lit/passes/constraint-analysis-float.wast +++ b/test/lit/passes/constraint-analysis-float.wast @@ -22,10 +22,7 @@ ;; FASTM: (func $float-zero (type $0) ;; FASTM-NEXT: (local $f f64) ;; FASTM-NEXT: (if - ;; FASTM-NEXT: (f64.eq - ;; FASTM-NEXT: (f64.const 0) - ;; FASTM-NEXT: (f64.const 0) - ;; FASTM-NEXT: ) + ;; FASTM-NEXT: (i32.const 1) ;; FASTM-NEXT: (then ;; FASTM-NEXT: (nop) ;; FASTM-NEXT: ) @@ -70,19 +67,13 @@ ;; FASTM: (func $float-negative-zero (type $0) ;; FASTM-NEXT: (local $f f64) ;; FASTM-NEXT: (if - ;; FASTM-NEXT: (f64.eq - ;; FASTM-NEXT: (f64.const 0) - ;; FASTM-NEXT: (f64.const -0) - ;; FASTM-NEXT: ) + ;; FASTM-NEXT: (i32.const 1) ;; FASTM-NEXT: (then ;; FASTM-NEXT: (nop) ;; FASTM-NEXT: ) ;; FASTM-NEXT: ) ;; FASTM-NEXT: (if - ;; FASTM-NEXT: (f64.eq - ;; FASTM-NEXT: (f64.const 0) - ;; FASTM-NEXT: (f64.const 0) - ;; FASTM-NEXT: ) + ;; FASTM-NEXT: (i32.const 1) ;; FASTM-NEXT: (then ;; FASTM-NEXT: (nop) ;; FASTM-NEXT: ) @@ -128,10 +119,7 @@ ;; FASTM-NEXT: (local.set $nan ;; FASTM-NEXT: (f64.const nan:0x8000000000000) ;; FASTM-NEXT: ) - ;; FASTM-NEXT: (f64.ne - ;; FASTM-NEXT: (f64.const nan:0x8000000000000) - ;; FASTM-NEXT: (f64.const nan:0x8000000000000) - ;; FASTM-NEXT: ) + ;; FASTM-NEXT: (i32.const 0) ;; FASTM-NEXT: ) (func $float-ne-nan (result i32) (local $nan f64) diff --git a/test/lit/passes/constraint-analysis-loops.wast b/test/lit/passes/constraint-analysis-loops.wast index 3cdb9ff6cdb..392652821e3 100644 --- a/test/lit/passes/constraint-analysis-loops.wast +++ b/test/lit/passes/constraint-analysis-loops.wast @@ -1526,10 +1526,7 @@ ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1554,10 +1551,7 @@ ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 6d0cbe998fe..e08c15123ea 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -23,28 +23,16 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $simple (type $1) @@ -53,19 +41,13 @@ ;; OPTIN-NEXT: (i32.const 10) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ne - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -137,10 +119,7 @@ ;; OPTIN-NEXT: (i32.const 30) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (i32.div_u @@ -196,37 +175,22 @@ ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (i32.const 15) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: (i32.const 15) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-local (type $1) @@ -239,37 +203,22 @@ ;; OPTIN-NEXT: (i32.const 20) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (i32.const 15) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 15) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 15) - ;; OPTIN-NEXT: (i32.const 15) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $multi-local @@ -329,26 +278,17 @@ ;; CHECK-NEXT: (local.get $param) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-block (type $0) (param $param i32) @@ -360,24 +300,15 @@ ;; OPTIN-NEXT: (if (result i32) ;; OPTIN-NEXT: (local.get $param) ;; OPTIN-NEXT: (then - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (else - ;; OPTIN-NEXT: (i32.ne - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $multi-block (param $param i32) @@ -594,16 +525,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-block-split-yes (type $0) (param $param i32) @@ -620,10 +545,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -665,16 +587,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $loop ;; CHECK-NEXT: (local.get $param) @@ -688,10 +604,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (loop $loop ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -812,15 +725,10 @@ ;; CHECK-NEXT: (local $eq eqref) ;; CHECK-NEXT: (local $nn-eq (ref eq)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.eq @@ -829,15 +737,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $default-var (type $0) (param $param i32) @@ -845,14 +748,10 @@ ;; OPTIN-NEXT: (local $eq eqref) ;; OPTIN-NEXT: (local $nn-eq (ref eq)) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.eqz @@ -860,14 +759,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (ref.is_null - ;; OPTIN-NEXT: (ref.null none) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (ref.is_null - ;; OPTIN-NEXT: (ref.null none) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $default-var (param $param i32) @@ -922,15 +817,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1020,16 +910,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -1146,28 +1030,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1188,28 +1060,16 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1268,10 +1128,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block @@ -1288,16 +1145,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1310,10 +1161,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (block @@ -1330,16 +1178,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1401,16 +1243,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -1423,16 +1259,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1445,22 +1275,13 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -1523,10 +1344,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) @@ -1544,10 +1362,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 30) @@ -1634,10 +1449,7 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) @@ -1690,10 +1502,7 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block @@ -1712,10 +1521,7 @@ ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (if - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: (i32.const 1) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (block @@ -1857,10 +1663,7 @@ ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $conditional-br_if_2 (type $0) (param $param i32) @@ -1883,10 +1686,7 @@ ;; OPTIN-NEXT: (return) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $conditional-br_if_2 (param $param i32) @@ -1976,9 +1776,7 @@ ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $br_on_null (type $6) (param $param anyref) @@ -1999,9 +1797,7 @@ ;; OPTIN-NEXT: (return) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (ref.is_null - ;; OPTIN-NEXT: (ref.null none) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $br_on_null (param $param anyref) @@ -2045,9 +1841,7 @@ ;; CHECK-NEXT: (local.get $param) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.is_null - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (return) ;; CHECK-NEXT: ) @@ -2068,9 +1862,7 @@ ;; OPTIN-NEXT: (local.get $param) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (ref.is_null - ;; OPTIN-NEXT: (ref.null none) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (return) ;; OPTIN-NEXT: ) @@ -3470,16 +3262,10 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $multi-local-copy (type $1) @@ -3492,16 +3278,10 @@ ;; OPTIN-NEXT: (i32.const 10) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $multi-local-copy @@ -3546,16 +3326,10 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -3672,16 +3446,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3697,16 +3465,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -3752,16 +3514,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3777,16 +3533,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -4127,13 +3877,7 @@ ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local $e eqref) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: (ref.null none) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $nested-binaries (type $1) @@ -4141,9 +3885,7 @@ ;; OPTIN-NEXT: (local $e eqref) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (ref.is_null - ;; OPTIN-NEXT: (ref.null none) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -4173,10 +3915,7 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $relevant-copy (type $1) @@ -4186,9 +3925,7 @@ ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $relevant-copy @@ -4213,28 +3950,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-lt_s (type $1) @@ -4243,22 +3968,13 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -4302,28 +4018,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-le_s (type $1) @@ -4332,28 +4036,16 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.le_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.le_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.le_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $constant-inequalities-le_s @@ -4393,28 +4085,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-gt_s (type $1) @@ -4423,28 +4103,16 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $constant-inequalities-gt_s @@ -4484,28 +4152,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_s - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-ge_s (type $1) @@ -4514,22 +4170,13 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -4572,28 +4219,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-lt_u (type $1) @@ -4602,22 +4237,13 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.lt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -4660,28 +4286,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.le_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-le_u (type $1) @@ -4690,22 +4304,13 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.le_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.le_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.le_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 1) @@ -4748,28 +4353,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-gt_u (type $1) @@ -4778,22 +4371,13 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.gt_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -4836,28 +4420,16 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 41) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 43) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $constant-inequalities-ge_u (type $1) @@ -4866,22 +4438,13 @@ ;; OPTIN-NEXT: (i32.const 42) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 41) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.ge_u - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 43) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -4922,10 +4485,7 @@ ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: (unreachable) @@ -4935,9 +4495,7 @@ ;; OPTIN-NEXT: (local $x i32) ;; OPTIN-NEXT: (loop $loop ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (unreachable) ;; OPTIN-NEXT: (unreachable) @@ -5022,16 +4580,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $tee (type $1) @@ -5043,16 +4595,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $tee @@ -5087,10 +4633,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $fallthrough (type $1) @@ -5102,10 +4645,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $fallthrough @@ -5143,10 +4683,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $fallthrough-get (type $1) @@ -5167,10 +4704,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $fallthrough-get @@ -5225,10 +4759,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; OPTIN: (func $fallthrough-tee (type $0) (param $param i32) @@ -5249,10 +4780,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) (func $fallthrough-tee (param $param i32) @@ -5290,10 +4818,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5305,9 +4830,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -5338,10 +4861,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i64.eq - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: (i64.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5353,9 +4873,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i64.eqz - ;; OPTIN-NEXT: (i64.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -5585,22 +5103,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -5641,21 +5150,13 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (else @@ -6000,10 +5501,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else @@ -6030,10 +5528,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (else @@ -6117,22 +5612,13 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.const 0) @@ -6175,22 +5661,13 @@ ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.const 0) @@ -6470,9 +5947,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6487,9 +5962,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6608,10 +6081,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: (i32.const 42) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6628,10 +6098,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: (i32.const 42) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -6843,9 +6310,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6859,9 +6324,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eqz - ;; OPTIN-NEXT: (i32.const 0) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -7003,10 +6466,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7023,10 +6483,7 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 1) - ;; OPTIN-NEXT: (i32.const 1) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -7076,16 +6533,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.eq @@ -7117,16 +6568,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (i32.eq @@ -7207,22 +6652,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: (i32.const 20) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7248,22 +6684,13 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: (i32.const 20) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -7334,16 +6761,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: (i32.const 30) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7369,16 +6790,10 @@ ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (then ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: (i32.const 10) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (drop - ;; OPTIN-NEXT: (i32.eq - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: (i32.const 30) - ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (i32.const 1) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) @@ -7508,11 +6923,13 @@ (local.get $x) (then (drop + ;; This is non-zero, but we can't optimze. (local.get $x) ) ) (else (drop + ;; This is zero. (local.get $x) ) ) From 6db5f6a58b92a0ce301c5c55c7eeab3d3fcfd1db Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 18 Sep 2026 16:15:49 -0700 Subject: [PATCH 18/36] work --- src/passes/ConstraintAnalysis.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 816ab5bda34..46f49c001d0 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -415,7 +415,7 @@ struct ConstraintAnalysis // Given an expression and the constraints on it, see if it is a local.get // that we can optimize, and return the value to optimize to, if so. Expression* optimizeLocalGet(Expression** currp, - const BasicBlockConstraintMap& constraints) { + const BasicBlockConstraintMap& constraints) { // A bare local.get can be optimized, if we know that local is a constant. if (auto* get = (*currp)->dynCast()) { if (auto lit = constraints.get(get->index).getLiteral()) { From c8a3ffba9d4f6a08bd63f91afb28312824dca938 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 10:21:33 -0700 Subject: [PATCH 19/36] work --- src/passes/ConstraintAnalysis.cpp | 6 +++ test/lit/passes/constraint-analysis.wast | 47 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 46f49c001d0..0046c99466a 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -419,6 +419,12 @@ struct ConstraintAnalysis // A bare local.get can be optimized, if we know that local is a constant. if (auto* get = (*currp)->dynCast()) { if (auto lit = constraints.get(get->index).getLiteral()) { + // Among references, only propagate nulls. Other things, like strings, + // may increase size, so we leave them for passes like Precompute and + // GUFA. + if (lit->type.isRef() && !lit->isNull()) { + return nullptr; + } return Builder(*getModule()).makeConstantExpression(*lit); } } diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index e08c15123ea..c918ee35c33 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -7091,4 +7091,51 @@ ) ) ) + + ;; CHECK: (func $local.get.internalized-string (type $1) + ;; CHECK-NEXT: (local $x anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.null none) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (any.convert_extern + ;; CHECK-NEXT: (string.const "foo") + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $local.get.internalized-string (type $1) + ;; OPTIN-NEXT: (local $x anyref) + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (ref.null none) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (local.set $x + ;; OPTIN-NEXT: (any.convert_extern + ;; OPTIN-NEXT: (string.const "foo") + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + (func $local.get.internalized-string + (local $x anyref) + ;; A null can be propagated. + (drop + (local.get $x) + ) + ;; A non-null value, like an internalized string, is not optimized (we could + ;; emit an any.convert_extern of a strong.const, but it increases size, so + ;; we leave this for passes like Precompute and GUFA). + (local.set $x + (any.convert_extern + (string.const "foo") + ) + ) + (drop + (local.get $x) + ) + ) ) From 8e3495c6207c0919621521a85cc8acb485d950c6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 13:59:39 -0700 Subject: [PATCH 20/36] work --- src/passes/ConstraintAnalysis.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 0046c99466a..a47430a00e0 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -161,7 +161,11 @@ struct ConstraintAnalysis void doWalkFunction(Function* func) { fastMath = getPassOptions().fastMath; + // Mark the relevant locals. relevantLocals.assign(func->getNumLocals(), false); + for (Index i = 0; i < func->getNumLocals(); ++i) { + relevantLocals[i] = isRelevantType(func->getLocalType(i)); + } Super::doWalkFunction(func); } @@ -183,23 +187,14 @@ struct ConstraintAnalysis } void visitLocalGet(LocalGet* curr) { - // To be relevant for optimization, there must be a local.get (otherwise, - // nothing can be optimized as this is not used), and the type must be - // relevant. if (isRelevantType(curr->type)) { addAction(); - relevantLocals[curr->index] = true; } } void visitLocalSet(LocalSet* curr) { if (isRelevantType(getFunction()->getLocalType(curr->index))) { addAction(); - - // A tee is also a get, so it can mark a local as relevant, like LocalGet. - if (curr->isTee()) { - relevantLocals[curr->index] = true; - } } } From 5795eec7ece642eddd68c9dabdb771bf11ad8cc8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 14:04:28 -0700 Subject: [PATCH 21/36] work --- src/passes/ConstraintAnalysis.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index a47430a00e0..2d95f2aaabd 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -334,10 +334,8 @@ struct ConstraintAnalysis // If we make things unreachable, we must refinalize. bool refinalize = false; - // If we find local.gets that we can optimize, we queue those changes here - // (each item being currp, the pointer to the LocalGet, and then the value - // to replace it with). This order is useful for the following reason: - // consider a simple expression, like this, + // If we find local.gets that we can optimize, we queue those changes here. + // This order is useful for the following reason: // // (i32.eqz // (local.get $x) @@ -348,14 +346,17 @@ struct ConstraintAnalysis // pass only looks at constraints on locals. We do not lose any optimization // power by leaving this to Precompute, but it is less efficient and may // require more cycles; it is also less convenient for testing, as we must - // avoid inferring local.gets in order to fully test constraint + // avoid inferrable local.gets in order to fully test constraint // optimization. // - // Instead, we queue local.get changes here. If, say, we optimize that eqz, - // then the local.get change ends up unnoticable (it changes the Unary - // which was removed from the tree anyhow, which is not harmful aside from a - // tiny bit of wasted work, but that waste is less than waiting for + // Instead, we queue local.get changes to happen later, after the eqz in the + // example above. That is, the eqz gets a chance to get optimized, and if it + // does, the queued local.get change ends up unnoticable (it changes a thing + // not in the IR; a slight waste of work, but less wasteful than waiting for // Precompute). + // + // This queue of changes contains tuples of currp (the pointer to the + // local.get) and the value to replace it with. std::vector> getOptimizations; for (auto& block : basicBlocks) { From 03126addcb673cf12a980e5a1d0a1677c789c364 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 14:08:00 -0700 Subject: [PATCH 22/36] work --- src/passes/ConstraintAnalysis.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 2d95f2aaabd..9cba67f9e62 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -464,7 +464,6 @@ struct ConstraintAnalysis LiteralUtils::makeFromInt32(result == True ? 1 : 0, curr->type, wasm); *currp = getDroppedChildrenAndAppend( curr, wasm, getPassOptions(), value, DropMode::IgnoreParentEffects); - return; } // Given a predecessor and one of its successors, find new constraints that From 0782b34dc9dbe7f774a48bd7bf1e3af105ad9d67 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 14:08:32 -0700 Subject: [PATCH 23/36] work --- src/passes/ConstraintAnalysis.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 9cba67f9e62..782f591778b 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -752,6 +752,3 @@ struct ConstraintAnalysis Pass* createConstraintAnalysisPass() { return new ConstraintAnalysis(); } } // namespace wasm - -// TODO: test option to not do the local.get opts in optimizeExpr() here -// TODO why is fast-math brokenn From e79ade78af33d4e7b4054d51a038186647a7dbce Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 14:27:22 -0700 Subject: [PATCH 24/36] work --- test/lit/passes/constraint-analysis-propagation.wast | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/lit/passes/constraint-analysis-propagation.wast b/test/lit/passes/constraint-analysis-propagation.wast index 53f0530291a..6164a564567 100644 --- a/test/lit/passes/constraint-analysis-propagation.wast +++ b/test/lit/passes/constraint-analysis-propagation.wast @@ -106,7 +106,8 @@ (local.set $2 (local.get $1)) ;; $2 == $1 (br_if 0 (local.get $0)) ;; this once again applies $0 != 0, and - ;; now we notice the contradiction + ;; now we notice the contradiction, and + ;; this turns unreachable (local.set $0 (local.get $2)) ;; we add an unreachable after this ) From 9fe588ddff9634e105b188a37ad1a370eeaab013 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 14:32:26 -0700 Subject: [PATCH 25/36] work --- test/lit/passes/constraint-analysis.wast | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index c918ee35c33..2c4fbcac6cd 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -1430,7 +1430,7 @@ ;; As above, but now with a single if. The contradiction tested is ;; between the default value and the if condition. (if - (local.get $x) + (local.get $x) ;; this is 0, hence the if is not taken (then (drop ;; This is unreachable. @@ -3388,7 +3388,7 @@ (i32.const 42) ) ) - ;; Copy x into y, and see that it is now equal to 42. + ;; Copy x (which is 42) into y, and see that it is now equal to 42. (local.set $y (local.get $x) ) @@ -3481,7 +3481,7 @@ ) (if (i32.eq - (local.get $x) + (local.get $x) ;; this is 42 (local.get $y) ) (then From 68e9e5c6e8d8cb2266621287160f4b4da5b5b36e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 15:16:28 -0700 Subject: [PATCH 26/36] work --- test/lit/passes/constraint-analysis.wast | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 2c4fbcac6cd..8b6a8a4a794 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -3893,10 +3893,9 @@ (func $nested-binaries (local $x i32) (local $e eqref) - ;; Nested binaries. The outer one is initially not relevant - we cannot - ;; parse the right hand side - but after optimization it simplifies. We - ;; should not assert here, and only optimize the inner one, leaving the - ;; outer for later. + ;; Nested binaries of different types. We can apply the local.gets and then + ;; optimize the ref.eq to 1 and the lt_u to 1 as well. (This does not fully + ;; work out in OPTIN due to reordering, but Precompute would handle it.) (drop (i32.lt_u (local.get $x) From 96f839cfa850e1b076cff5171c1a549bcd4945fa Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 15:23:49 -0700 Subject: [PATCH 27/36] work --- test/lit/passes/constraint-analysis.wast | 49 +++++++++++++----------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 8b6a8a4a794..6335aadea33 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -13,8 +13,8 @@ ;; OPTIN: (type $array (array (mut i32))) (type $array (array (mut i32))) - ;; CHECK: (import "a" "b" (func $import (type $4) (result i32))) - ;; OPTIN: (import "a" "b" (func $import (type $4) (result i32))) + ;; CHECK: (import "a" "b" (func $import (type $5) (result i32))) + ;; OPTIN: (import "a" "b" (func $import (type $5) (result i32))) (import "a" "b" (func $import (result i32))) ;; CHECK: (func $simple (type $1) @@ -3930,8 +3930,7 @@ (func $relevant-copy (local $x i32) (local $y i32) - ;; x is not relevant, but it is copied to y, which is, so we must track x as - ;; relevant too. + ;; x has no sets or uses but for a copy to $y, but we still optimize here. (local.set $y (local.get $x) ) @@ -4480,28 +4479,34 @@ ) ) - ;; CHECK: (func $flipped-contradiction (type $4) (result i32) - ;; CHECK-NEXT: (local $x i32) + ;; CHECK: (func $flipped-contradiction (type $10) (param $x i32) (result i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.lt_u + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br_if $loop + ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $flipped-contradiction (type $4) (result i32) - ;; OPTIN-NEXT: (local $x i32) + ;; OPTIN: (func $flipped-contradiction (type $10) (param $x i32) (result i32) ;; OPTIN-NEXT: (loop $loop ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: (i32.eqz + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (br_if $loop + ;; OPTIN-NEXT: (local.get $x) ;; OPTIN-NEXT: ) - ;; OPTIN-NEXT: (unreachable) ;; OPTIN-NEXT: (unreachable) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) - (func $flipped-contradiction (result i32) - (local $x i32) + (func $flipped-contradiction (param $x i32) (result i32) (loop $loop (result i32) ;; If we do not branch, we add the constraint x >= 1. (br_if $loop @@ -4522,7 +4527,7 @@ ) ) - ;; CHECK: (func $flipped-contradiction-no (type $4) (result i32) + ;; CHECK: (func $flipped-contradiction-no (type $5) (result i32) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (loop $loop (result i32) ;; CHECK-NEXT: (br_if $loop @@ -4536,7 +4541,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $flipped-contradiction-no (type $4) (result i32) + ;; OPTIN: (func $flipped-contradiction-no (type $5) (result i32) ;; OPTIN-NEXT: (local $x i32) ;; OPTIN-NEXT: (loop $loop (result i32) ;; OPTIN-NEXT: (br_if $loop @@ -4853,7 +4858,7 @@ ) ) - ;; CHECK: (func $eqz-condition-64 (type $10) (param $x i64) + ;; CHECK: (func $eqz-condition-64 (type $11) (param $x i64) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i64.eqz ;; CHECK-NEXT: (local.get $x) @@ -4865,7 +4870,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $eqz-condition-64 (type $10) (param $x i64) + ;; OPTIN: (func $eqz-condition-64 (type $11) (param $x i64) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i64.eqz ;; OPTIN-NEXT: (local.get $x) @@ -5581,7 +5586,7 @@ ) ) - ;; CHECK: (func $several (type $11) (param $a i32) (param $b i32) (param $c i32) (param $d i32) (param $e i32) + ;; CHECK: (func $several (type $12) (param $a i32) (param $b i32) (param $c i32) (param $d i32) (param $e i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (i32.and @@ -5631,7 +5636,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $several (type $11) (param $a i32) (param $b i32) (param $c i32) (param $d i32) (param $e i32) + ;; OPTIN: (func $several (type $12) (param $a i32) (param $b i32) (param $c i32) (param $d i32) (param $e i32) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.and ;; OPTIN-NEXT: (i32.and @@ -6962,7 +6967,7 @@ ) ) - ;; CHECK: (func $local.get.impossible.cast (type $12) (result (ref func)) + ;; CHECK: (func $local.get.impossible.cast (type $13) (result (ref func)) ;; CHECK-NEXT: (local $x (ref func)) ;; CHECK-NEXT: (local.set $x ;; CHECK-NEXT: (ref.cast (ref nofunc) @@ -6971,7 +6976,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) - ;; OPTIN: (func $local.get.impossible.cast (type $12) (result (ref func)) + ;; OPTIN: (func $local.get.impossible.cast (type $13) (result (ref func)) ;; OPTIN-NEXT: (local $x (ref func)) ;; OPTIN-NEXT: (local.set $x ;; OPTIN-NEXT: (unreachable) From fca9397b57d43f3d1dba101d49f932bdc881dd7e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 15:51:27 -0700 Subject: [PATCH 28/36] work --- test/lit/passes/constraint-analysis.wast | 49 +++++++++++++----------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 6335aadea33..5855ed6a8e0 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -13,8 +13,8 @@ ;; OPTIN: (type $array (array (mut i32))) (type $array (array (mut i32))) - ;; CHECK: (import "a" "b" (func $import (type $5) (result i32))) - ;; OPTIN: (import "a" "b" (func $import (type $5) (result i32))) + ;; CHECK: (import "a" "b" (func $import (type $7) (result i32))) + ;; OPTIN: (import "a" "b" (func $import (type $7) (result i32))) (import "a" "b" (func $import (result i32))) ;; CHECK: (func $simple (type $1) @@ -1758,7 +1758,7 @@ ) ) - ;; CHECK: (func $br_on_null (type $6) (param $param anyref) + ;; CHECK: (func $br_on_null (type $5) (param $param anyref) ;; CHECK-NEXT: (block $block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.is_null @@ -1779,7 +1779,7 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $br_on_null (type $6) (param $param anyref) + ;; OPTIN: (func $br_on_null (type $5) (param $param anyref) ;; OPTIN-NEXT: (block $block ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (ref.is_null @@ -1829,7 +1829,7 @@ ) ) - ;; CHECK: (func $br_on_non_null (type $6) (param $param anyref) + ;; CHECK: (func $br_on_non_null (type $5) (param $param anyref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block $block (result (ref any)) ;; CHECK-NEXT: (drop @@ -1850,7 +1850,7 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $br_on_non_null (type $6) (param $param anyref) + ;; OPTIN: (func $br_on_non_null (type $5) (param $param anyref) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (block $block (result (ref any)) ;; OPTIN-NEXT: (drop @@ -2876,7 +2876,7 @@ ) ) - ;; CHECK: (func $local-changes-if (type $7) (param $x i32) (param $y i32) (param $z i32) (param $w i32) + ;; CHECK: (func $local-changes-if (type $8) (param $x i32) (param $y i32) (param $z i32) (param $w i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eq ;; CHECK-NEXT: (local.get $x) @@ -2933,7 +2933,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $local-changes-if (type $7) (param $x i32) (param $y i32) (param $z i32) (param $w i32) + ;; OPTIN: (func $local-changes-if (type $8) (param $x i32) (param $y i32) (param $z i32) (param $w i32) ;; OPTIN-NEXT: (if ;; OPTIN-NEXT: (i32.eq ;; OPTIN-NEXT: (local.get $x) @@ -3569,7 +3569,7 @@ ) ) - ;; CHECK: (func $simple-array-sum (type $8) (param $param (ref $array)) (result i32) + ;; CHECK: (func $simple-array-sum (type $9) (param $param (ref $array)) (result i32) ;; CHECK-NEXT: (local $index i32) ;; CHECK-NEXT: (local $sum i32) ;; CHECK-NEXT: (local $len i32) @@ -3614,7 +3614,7 @@ ;; CHECK-NEXT: (br $loop) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $simple-array-sum (type $8) (param $param (ref $array)) (result i32) + ;; OPTIN: (func $simple-array-sum (type $9) (param $param (ref $array)) (result i32) ;; OPTIN-NEXT: (local $index i32) ;; OPTIN-NEXT: (local $sum i32) ;; OPTIN-NEXT: (local $len i32) @@ -3789,7 +3789,7 @@ ) ) - ;; CHECK: (func $iloop (type $9) (param $0 f32) + ;; CHECK: (func $iloop (type $10) (param $0 f32) ;; CHECK-NEXT: (local $1 f32) ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (local.get $1) @@ -3814,7 +3814,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $iloop (type $9) (param $0 f32) + ;; OPTIN: (func $iloop (type $10) (param $0 f32) ;; OPTIN-NEXT: (local $1 f32) ;; OPTIN-NEXT: (local.set $0 ;; OPTIN-NEXT: (local.get $1) @@ -4479,7 +4479,7 @@ ) ) - ;; CHECK: (func $flipped-contradiction (type $10) (param $x i32) (result i32) + ;; CHECK: (func $flipped-contradiction (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (loop $loop ;; CHECK-NEXT: (br_if $loop ;; CHECK-NEXT: (i32.lt_u @@ -4493,7 +4493,7 @@ ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $flipped-contradiction (type $10) (param $x i32) (result i32) + ;; OPTIN: (func $flipped-contradiction (type $6) (param $x i32) (result i32) ;; OPTIN-NEXT: (loop $loop ;; OPTIN-NEXT: (br_if $loop ;; OPTIN-NEXT: (i32.eqz @@ -4527,11 +4527,13 @@ ) ) - ;; CHECK: (func $flipped-contradiction-no (type $5) (result i32) - ;; CHECK-NEXT: (local $x i32) + ;; CHECK: (func $flipped-contradiction-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (loop $loop (result i32) ;; CHECK-NEXT: (br_if $loop - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $loop ;; CHECK-NEXT: (local.get $x) @@ -4541,24 +4543,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $flipped-contradiction-no (type $5) (result i32) - ;; OPTIN-NEXT: (local $x i32) + ;; OPTIN: (func $flipped-contradiction-no (type $6) (param $x i32) (result i32) ;; OPTIN-NEXT: (loop $loop (result i32) ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (i32.gt_u + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (br_if $loop - ;; OPTIN-NEXT: (i32.const 0) + ;; OPTIN-NEXT: (local.get $x) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: (i32.eqz ;; OPTIN-NEXT: (i32.const 0) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) ;; OPTIN-NEXT: ) - (func $flipped-contradiction-no (result i32) + (func $flipped-contradiction-no (param $x i32) (result i32) ;; As above, but with lt replaced by gt. Now the constraints are x <= 1 and ;; x == 0, which do not contradict, and nothing becomes unreachable. - (local $x i32) (loop $loop (result i32) (br_if $loop (i32.gt_u From 65216d787a246df713da973d9c4127701613e98f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 21 Sep 2026 15:57:49 -0700 Subject: [PATCH 29/36] work --- test/lit/passes/constraint-analysis.wast | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 5855ed6a8e0..331b6166802 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -6990,7 +6990,8 @@ (local $x (ref func)) ;; The cast here traps at runtime. We do not have a valid value to put in ;; place of the local.get (it is not refined enough), but we know it is - ;; unreachable. + ;; unreachable. (In OPTIN, we figure out the set's value is unreachable even + ;; earlier.) (local.set $x (ref.cast (ref func) (ref.null func) @@ -7014,6 +7015,7 @@ (func $local.get.no.v128 (local $x v128) ;; We know the value here, but do not copy v128 constants, which are large. + ;; TODO: should we optimize this? (drop (local.get $x) ) @@ -7085,7 +7087,8 @@ (func $local.get.float (local $x f64) ;; The condition here ends up comparing $x to itself. That is normally 1, - ;; but not with a nan. We do not optimize floats for this reason. + ;; but not with a nan. We do not optimize floats for this reason (without + ;; --fast-math, see constraint-analysis-float.wast). (if (f64.eq (local.tee $x @@ -7136,6 +7139,7 @@ ;; A non-null value, like an internalized string, is not optimized (we could ;; emit an any.convert_extern of a strong.const, but it increases size, so ;; we leave this for passes like Precompute and GUFA). + ;; TODO: should we optimize this? (local.set $x (any.convert_extern (string.const "foo") From d3ce1632888e6b5aea868c7695f0acf15b4a886a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 22 Sep 2026 14:14:58 -0700 Subject: [PATCH 30/36] update existing tests --- test/lit/ctor-eval/multivalue-local.wast | 5 +---- test/lit/help/wasm-metadce.test | 2 +- test/lit/help/wasm-opt.test | 2 +- test/lit/help/wasm2js.test | 2 +- test/lit/passes/O.wast | 2 +- test/lit/passes/global-effects-O.wast | 6 +++--- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/test/lit/ctor-eval/multivalue-local.wast b/test/lit/ctor-eval/multivalue-local.wast index 5ae46cf2b4c..2fa0554967b 100644 --- a/test/lit/ctor-eval/multivalue-local.wast +++ b/test/lit/ctor-eval/multivalue-local.wast @@ -49,8 +49,5 @@ ;; CHECK-NEXT: (i32.const 42) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $import) -;; CHECK-NEXT: (i32.add -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: (local.get $0) -;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.const 84) ;; CHECK-NEXT: ) diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index bd12e989573..0be805fa01f 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -394,7 +394,7 @@ ;; CHECK-NEXT: --propagate-globals-globally propagate global values to other ;; CHECK-NEXT: globals (useful for tests) ;; CHECK-EMPTY: -;; CHECK-NEXT: --remove-empty-function-exports removes exports of empty +;; CHECK-NEXT: --remove-empty-function-exports removes exports of empty ;; CHECK-NEXT: functions ;; CHECK-EMPTY: ;; CHECK-NEXT: --remove-exports removes exports using a wildcard diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 568b3fef689..116c3260dcb 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -430,7 +430,7 @@ ;; CHECK-NEXT: --propagate-globals-globally propagate global values to other ;; CHECK-NEXT: globals (useful for tests) ;; CHECK-EMPTY: -;; CHECK-NEXT: --remove-empty-function-exports removes exports of empty +;; CHECK-NEXT: --remove-empty-function-exports removes exports of empty ;; CHECK-NEXT: functions ;; CHECK-EMPTY: ;; CHECK-NEXT: --remove-exports removes exports using a wildcard diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index d1f4db8f9e3..14388cd93cb 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -358,7 +358,7 @@ ;; CHECK-NEXT: --propagate-globals-globally propagate global values to other ;; CHECK-NEXT: globals (useful for tests) ;; CHECK-EMPTY: -;; CHECK-NEXT: --remove-empty-function-exports removes exports of empty +;; CHECK-NEXT: --remove-empty-function-exports removes exports of empty ;; CHECK-NEXT: functions ;; CHECK-EMPTY: ;; CHECK-NEXT: --remove-exports removes exports using a wildcard diff --git a/test/lit/passes/O.wast b/test/lit/passes/O.wast index baba79ee0c5..c8a07779ba8 100644 --- a/test/lit/passes/O.wast +++ b/test/lit/passes/O.wast @@ -137,7 +137,7 @@ ;; CHECK-NEXT: (call $ret) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/passes/global-effects-O.wast b/test/lit/passes/global-effects-O.wast index ef2cf62e06c..ce0507d1509 100644 --- a/test/lit/passes/global-effects-O.wast +++ b/test/lit/passes/global-effects-O.wast @@ -362,7 +362,7 @@ ;; CHECK_3-NEXT: ) ;; CHECK_3-NEXT: ) ;; CHECK_3-NEXT: ) - ;; CHECK_3-NEXT: (local.get $0) + ;; CHECK_3-NEXT: (i32.const 0) ;; CHECK_3-NEXT: ) ;; CHECK_s: (func $infinite-work (type $1) (param $0 i32) (result i32) ;; CHECK_s-NEXT: (loop $loop @@ -375,7 +375,7 @@ ;; CHECK_s-NEXT: ) ;; CHECK_s-NEXT: ) ;; CHECK_s-NEXT: ) - ;; CHECK_s-NEXT: (local.get $0) + ;; CHECK_s-NEXT: (i32.const 0) ;; CHECK_s-NEXT: ) ;; CHECK_O: (func $infinite-work (type $1) (param $0 i32) (result i32) ;; CHECK_O-NEXT: (loop $loop @@ -388,7 +388,7 @@ ;; CHECK_O-NEXT: ) ;; CHECK_O-NEXT: ) ;; CHECK_O-NEXT: ) - ;; CHECK_O-NEXT: (local.get $0) + ;; CHECK_O-NEXT: (i32.const 0) ;; CHECK_O-NEXT: ) (func $infinite-work (param $x i32) (result i32) ;; Some work with no side effects aside from that it appears to potentially From ceb6e9aa7b8744927b0d1adc6251c8d99519ce19 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 22 Sep 2026 15:08:04 -0700 Subject: [PATCH 31/36] another update --- test/ctor-eval/partial-locals.wast.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ctor-eval/partial-locals.wast.out b/test/ctor-eval/partial-locals.wast.out index a51d389b00f..fa7cefc4288 100644 --- a/test/ctor-eval/partial-locals.wast.out +++ b/test/ctor-eval/partial-locals.wast.out @@ -16,7 +16,7 @@ (i32.const 115) ) (global.set $sp - (local.get $0) + (i32.const 100) ) ) ) From d59046774da94ef1b2ebc6cf51f00ae625549b86 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 22 Sep 2026 15:36:55 -0700 Subject: [PATCH 32/36] another update --- test/wasm2js/br_table_hoisting.2asm.js.opt | 37 ++-------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/test/wasm2js/br_table_hoisting.2asm.js.opt b/test/wasm2js/br_table_hoisting.2asm.js.opt index c4d825421f0..192a6801b2e 100644 --- a/test/wasm2js/br_table_hoisting.2asm.js.opt +++ b/test/wasm2js/br_table_hoisting.2asm.js.opt @@ -117,40 +117,9 @@ function asmFunc(imports) { function foo4($0) { $0 = $0 | 0; - a : { - b : { - c : { - if ($0) { - break c - } - d : { - switch ($0 | 0) { - default: - if ($0) { - break c - } - zed(-1); - zed(-2); - break; - case 0: - break a; - case 1: - break b; - case 2: - break c; - case 3: - break d; - }; - } - zed(-3); - zed(-4); - } - zed(-5); - zed(-6); - break a; - } - zed(-7); - zed(-8); + if ($0) { + zed(-5); + zed(-6); } zed(-9); zed(-10); From 650e5d8351cce6e52c7988169a1663c8b6fd3ded Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 23 Sep 2026 11:26:08 -0700 Subject: [PATCH 33/36] fix.merge --- test/lit/passes/constraint-analysis.wast | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 9fdd85067f5..6b96ca8443d 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -1758,7 +1758,7 @@ ) ) - ;; CHECK: (func $br_on_null (type $5) (param $param anyref) + ;; CHECK: (func $br_on_null (type $4) (param $param anyref) ;; CHECK-NEXT: (block $block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.is_null @@ -1779,7 +1779,7 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $br_on_null (type $5) (param $param anyref) + ;; OPTIN: (func $br_on_null (type $4) (param $param anyref) ;; OPTIN-NEXT: (block $block ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (ref.is_null @@ -1829,7 +1829,7 @@ ) ) - ;; CHECK: (func $br_on_non_null (type $5) (param $param anyref) + ;; CHECK: (func $br_on_non_null (type $4) (param $param anyref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (block $block (result (ref any)) ;; CHECK-NEXT: (drop @@ -1850,7 +1850,7 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $br_on_non_null (type $5) (param $param anyref) + ;; OPTIN: (func $br_on_non_null (type $4) (param $param anyref) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (block $block (result (ref any)) ;; OPTIN-NEXT: (drop @@ -6905,7 +6905,7 @@ ) ) - ;; CHECK: (func $eqz-ref-is-null (type $5) (param $x anyref) + ;; CHECK: (func $eqz-ref-is-null (type $4) (param $x anyref) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (ref.is_null @@ -6924,7 +6924,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; OPTIN: (func $eqz-ref-is-null (type $5) (param $x anyref) + ;; OPTIN: (func $eqz-ref-is-null (type $4) (param $x anyref) ;; OPTIN-NEXT: (drop ;; OPTIN-NEXT: (ref.is_null ;; OPTIN-NEXT: (local.get $x) @@ -6956,7 +6956,6 @@ ) ) ) -) ;; CHECK: (func $local.get (type $0) (param $x i32) ;; CHECK-NEXT: (if From d29b82c62ec1b41392428e7a93aecef056d411f9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 23 Sep 2026 11:38:46 -0700 Subject: [PATCH 34/36] feedback: refactor builder stuff into OptimizeLocalGet --- src/passes/ConstraintAnalysis.cpp | 33 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index 782f591778b..d0417d7ca78 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -370,7 +370,7 @@ struct ConstraintAnalysis #endif if (!constraints.unreachable) { applyToConstraints(*currp, constraints); - if (auto* rep = optimizeLocalGet(currp, constraints)) { + if (auto* rep = optimizeLocalGet(currp, constraints, refinalize)) { getOptimizations.emplace_back(currp, rep); } else { optimizeConstraint(currp, constraints); @@ -389,16 +389,6 @@ struct ConstraintAnalysis // Apply local.get optimizations after all that. for (auto& [currp, rep] : getOptimizations) { - auto oldType = (*currp)->type; - if (!Type::isSubType(rep->type, oldType)) { - // The value we know must exist here is impossible, which means it was - // cast in a way that traps at runtime. This code is unreachable. - rep = Builder(*getModule()).makeUnreachable(); - refinalize = true; - } else if (rep->type != oldType) { - // We are refining. - refinalize = true; - } *currp = rep; } @@ -411,7 +401,8 @@ struct ConstraintAnalysis // Given an expression and the constraints on it, see if it is a local.get // that we can optimize, and return the value to optimize to, if so. Expression* optimizeLocalGet(Expression** currp, - const BasicBlockConstraintMap& constraints) { + const BasicBlockConstraintMap& constraints, + bool& refinalize) { // A bare local.get can be optimized, if we know that local is a constant. if (auto* get = (*currp)->dynCast()) { if (auto lit = constraints.get(get->index).getLiteral()) { @@ -421,7 +412,23 @@ struct ConstraintAnalysis if (lit->type.isRef() && !lit->isNull()) { return nullptr; } - return Builder(*getModule()).makeConstantExpression(*lit); + + Builder builder(*getModule()); + auto* rep = builder.makeConstantExpression(*lit); + + // See if the type changes. + auto oldType = get->type; + if (!Type::isSubType(rep->type, oldType)) { + // The value we know must exist here is impossible, which means it was + // cast in a way that traps at runtime. This code is unreachable. + rep = builder.makeUnreachable(); + refinalize = true; + } else if (rep->type != oldType) { + // We are refining. + refinalize = true; + } + + return rep; } } From 737b2d01ab7dd844d85b82c3b00b556c9598b33c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 23 Sep 2026 13:00:39 -0700 Subject: [PATCH 35/36] refactor refinalize --- src/passes/ConstraintAnalysis.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index d0417d7ca78..ea58ccc5d29 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -329,10 +329,11 @@ struct ConstraintAnalysis } } + // If we change types, we must refinalize. + bool refinalize = false; + // After inferring all we can, apply it to optimize the code. void optimize() { - // If we make things unreachable, we must refinalize. - bool refinalize = false; // If we find local.gets that we can optimize, we queue those changes here. // This order is useful for the following reason: @@ -370,7 +371,7 @@ struct ConstraintAnalysis #endif if (!constraints.unreachable) { applyToConstraints(*currp, constraints); - if (auto* rep = optimizeLocalGet(currp, constraints, refinalize)) { + if (auto* rep = optimizeLocalGet(currp, constraints)) { getOptimizations.emplace_back(currp, rep); } else { optimizeConstraint(currp, constraints); @@ -401,8 +402,7 @@ struct ConstraintAnalysis // Given an expression and the constraints on it, see if it is a local.get // that we can optimize, and return the value to optimize to, if so. Expression* optimizeLocalGet(Expression** currp, - const BasicBlockConstraintMap& constraints, - bool& refinalize) { + const BasicBlockConstraintMap& constraints) { // A bare local.get can be optimized, if we know that local is a constant. if (auto* get = (*currp)->dynCast()) { if (auto lit = constraints.get(get->index).getLiteral()) { From c4eb348bbf29216c1a04b23d63ae090cad30738f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 23 Sep 2026 16:17:50 -0700 Subject: [PATCH 36/36] [NFC] remove some dead code: now that we do not have a complex relevant-locals-detection scheme - all we do is operate on all locals, except ones of the wrong types - we don't need to carefully check if we detected the right locals as relevant. --- src/passes/ConstraintAnalysis.cpp | 45 ++----------------------------- 1 file changed, 2 insertions(+), 43 deletions(-) diff --git a/src/passes/ConstraintAnalysis.cpp b/src/passes/ConstraintAnalysis.cpp index ea58ccc5d29..81daa1ba494 100644 --- a/src/passes/ConstraintAnalysis.cpp +++ b/src/passes/ConstraintAnalysis.cpp @@ -170,19 +170,11 @@ struct ConstraintAnalysis Super::doWalkFunction(func); } -#ifndef NDEBUG - // We use these in asserts, see below. - std::unordered_set originalActions; -#endif - // Store the actions we care about. void addAction() { if (currBasicBlock) { auto* currp = getCurrentPointer(); currBasicBlock->contents.actions.push_back(currp); -#ifndef NDEBUG - originalActions.insert(*currp); -#endif } } @@ -448,13 +440,7 @@ struct ConstraintAnalysis if (!parsed) { return; } - if (!checkRelevancy(*parsed)) { -#ifndef NDEBUG - // If this is not relevant, then it must be one of the original actions we - // care about, i.e., not the result of optimizations. See the comment - // below on checkRelevancy. - assert(originalActions.contains(curr)); -#endif + if (!relevantLocals[parsed->local]) { return; } @@ -639,39 +625,12 @@ struct ConstraintAnalysis } } - // When we are about to use or apply a constraint to a local, it must be on a - // relevant one - otherwise we misidentified which are relevant, which could - // lead to missed opportunities or misoptimizations. This returns true if we - // are operating on proper, relevant data. Normally this is all that can - // happen, but intermediate optimizations can make things become relevant, - // consider this: - // - // x == (y < 10) - // - // The outer == is initially not relevant: we are comparing x to something we - // can't parse into a constraint's term. However, if we get lucky and optimize - // y < 10 into a constant, then it does become parseable, but because we did - // not consider x as relevant (and so we do not have all the relevant - // information about it), we must return false here and not operate on it - // (later optimization cycles can get to it). - bool checkRelevancy(const LocalConstraint& parsed) { - if (!relevantLocals[parsed.local]) { - return false; - } - if (auto* other = std::get_if(&parsed.constraint.term)) { - if (!relevantLocals[*other]) { - return false; - } - } - return true; - } - // Filters out constraints on irrelevant locals. void filterRelevant(ParsedAndedConstraints& parsed) { parsed.erase(std::remove_if(parsed.begin(), parsed.end(), [&](const LocalConstraint& pair) { - return !checkRelevancy(pair); + return !relevantLocals[pair.local]; }), parsed.end()); }