From 0917a82d7b37158e4b30ba3d6aa4623b28041f9c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 14 Jul 2026 11:45:57 -0700 Subject: [PATCH 1/2] go --- src/ir/constraint.cpp | 10 +++++++++ test/lit/passes/constraint-analysis.wast | 27 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/ir/constraint.cpp b/src/ir/constraint.cpp index 6332f8a5224..3dd7fd0aa9a 100644 --- a/src/ir/constraint.cpp +++ b/src/ir/constraint.cpp @@ -330,6 +330,9 @@ void BasicBlockConstraintMap::approximateAndInternal(Index index, const Constraint& c, bool flip, bool isCopy) { + // We should not be applying constraints when already unreachable. + assert(!unreachable); + Constraint actual = c; if (flip) { LocalConstraint flipped{index, c}; @@ -377,6 +380,10 @@ void BasicBlockConstraintMap::approximateAndInternal(Index index, // flipped one too. if (!flip && std::holds_alternative(actual.term)) { approximateAndInternal(index, actual, true, isCopy); + if (unreachable) { + // We just found a contradiction. + return; + } } // If this constraint is simply "== x", then we are equal to that other local @@ -386,6 +393,9 @@ void BasicBlockConstraintMap::approximateAndInternal(Index index, if (actual.op == Abstract::Eq) { for (auto& otherC : get(*other)) { approximateAndInternal(index, otherC, false, true); + if (unreachable) { + return; + } } } } diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index 207a8e65993..f8c57883601 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -1317,6 +1317,33 @@ ) ) + (func $contadiction-during-flipping + (local $x i32) + (local $y i32) + (local.set $y + (i32.const 1) + ) + ;; $x == 0, $y == 1, so they are never equal, and the if body is + ;; unreachable. We find this out while applying the secondary facts of a + ;; constraint: we add $y == $x, and then apply $x's constraints to $y, + ;; ending up in $y with $y == 1 && $y == 0. + (if + (i32.eq + (local.get $y) + (local.get $x) + ) + (then + ;; This becomes unreachable. + (drop + (i32.eq + (local.get $y) + (local.get $x) + ) + ) + ) + ) + ) + ;; CHECK: (func $conditional-br_if (type $0) (param $param i32) ;; CHECK-NEXT: (block $block ;; CHECK-NEXT: (drop From 4972466099a55c50ebb1ee95160ebbc677459360 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 14 Jul 2026 11:46:16 -0700 Subject: [PATCH 2/2] test --- test/lit/passes/constraint-analysis.wast | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/lit/passes/constraint-analysis.wast b/test/lit/passes/constraint-analysis.wast index f8c57883601..f79b74494a8 100644 --- a/test/lit/passes/constraint-analysis.wast +++ b/test/lit/passes/constraint-analysis.wast @@ -1317,6 +1317,42 @@ ) ) + ;; CHECK: (func $contadiction-during-flipping (type $1) + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (local $y i32) + ;; CHECK-NEXT: (local.set $y + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; OPTIN: (func $contadiction-during-flipping (type $1) + ;; OPTIN-NEXT: (local $x i32) + ;; OPTIN-NEXT: (local $y i32) + ;; OPTIN-NEXT: (local.set $y + ;; OPTIN-NEXT: (i32.const 1) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (if + ;; OPTIN-NEXT: (i32.eq + ;; OPTIN-NEXT: (local.get $x) + ;; OPTIN-NEXT: (local.get $y) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: (then + ;; OPTIN-NEXT: (drop + ;; OPTIN-NEXT: (unreachable) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) + ;; OPTIN-NEXT: ) (func $contadiction-during-flipping (local $x i32) (local $y i32)