Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
adec816
fuzzz
kripken Jul 10, 2026
14e19d9
fuzzz
kripken Jul 10, 2026
46003bd
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Jul 10, 2026
7ea0ffd
undo
kripken Jul 10, 2026
ddd4edb
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Jul 14, 2026
e0276db
update
kripken Jul 14, 2026
c5deeeb
moar
kripken Jul 15, 2026
c3434b5
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Jul 30, 2026
ed44408
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Jul 31, 2026
e83c054
work
kripken Jul 31, 2026
192d924
work
kripken Jul 31, 2026
3096b52
less
kripken Aug 7, 2026
2ef5df7
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Aug 12, 2026
df548b9
fix
kripken Aug 12, 2026
ff3b15a
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Aug 14, 2026
cfc644f
finish
kripken Aug 14, 2026
9cdfcbe
work
kripken Aug 14, 2026
e880306
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Aug 17, 2026
433559a
move
kripken Aug 17, 2026
e083272
update
kripken Aug 17, 2026
1af77da
PR number
kripken Aug 17, 2026
3677bd8
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Aug 19, 2026
06f2c48
Merge remote-tracking branch 'myself/fuzz.constraint' into fuzz.const…
kripken Aug 19, 2026
42121a2
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Aug 20, 2026
1ef4c61
Merge remote-tracking branch 'origin/main' into fuzz.constraint
kripken Aug 20, 2026
9509fce
fix
kripken Aug 20, 2026
5c7acce
Merge remote-tracking branch 'origin/main' into fuzz.constraint.pre
kripken Aug 20, 2026
27737ea
undo
kripken Aug 20, 2026
64215b3
work
kripken Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- Add a new `--constraint-analysis` pass which propagates logical facts along
branches. (#9010)
- Replace the `BINARYEN_ROOT` environment variable (used by developers who are
doing out-of-tree builds of binaryen) with `BINARYEN_BIN` (#9023)

Expand Down
1 change: 1 addition & 0 deletions scripts/fuzz_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2691,6 +2691,7 @@ def write_commands(commands, filename):
("--code-pushing",),
("--code-folding",),
("--const-hoisting",),
("--constraint-analysis",),
("--dae",),
("--dae-optimizing",),
("--dae2",),
Expand Down
15 changes: 7 additions & 8 deletions src/passes/ConstraintAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,14 +517,12 @@ struct ConstraintAnalysis
// incremented and loop again, leading to [0, 2] and so forth, only stopping
// when it reaches the loop bound, which may be very high. We don't want to
// spend significant time on such constant operations, as other passes will
// propagate them anyhow, so we verify that we don't apply such x = y + 1
// operations too many times.
#ifndef NDEBUG
static const Index MaxBinaryActions = 5;
// propagate them anyhow, so we stop before applying such x = y + 1
// operations a ridiculous number of times, by widening to a worst case.
static const Index MaxBinaryActions = 20;

// How many times we processed each Binary action.
std::unordered_map<Binary*, Index> binaryActionCounts;
#endif

// Given an expression, apply it to the constraints. For example, a local.set
// sets the value for that local.
Expand All @@ -536,12 +534,13 @@ struct ConstraintAnalysis
return;
}

#ifndef NDEBUG
// See above on binary action counting limits.
if (auto* binary = set->value->dynCast<Binary>()) {
assert(binaryActionCounts[binary]++ <= MaxBinaryActions);
if (binaryActionCounts[binary]++ >= MaxBinaryActions) {
constraints.setProvesNothing(set->index);
return;
}
}
#endif

// Look at the fallthrough. It is valid to do so, because our constraints
// only track two things, constants and locals. For a constant, it does
Expand Down
2 changes: 1 addition & 1 deletion src/passes/pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ void PassRunner::addDefaultFunctionOptimizationPasses() {
"remove-unused-brs"); // coalesce-locals opens opportunities
addIfNoDWARFIssues(
"remove-unused-names"); // remove-unused-brs opens opportunities
addIfNoDWARFIssues("merge-blocks"); // clean up remove-unused-brs new blocks
addIfNoDWARFIssues("merge-blocks"); // clean up new blocks from last passes
// late propagation
if (options.optimizeLevel >= 3 || options.shrinkLevel >= 2) {
addIfNoDWARFIssues("precompute-propagate");
Expand Down
47 changes: 46 additions & 1 deletion test/lit/passes/constraint-analysis-loops.wast
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,51 @@
)
)

;; CHECK: (func $infinite-loop-with-branch (type $0)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (loop $loop
;; CHECK-NEXT: (if
;; CHECK-NEXT: (i32.gt_s
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (then
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $x
;; CHECK-NEXT: (i32.add
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $loop)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $infinite-loop-with-branch
(local $x i32)
;; An infinite loop that *looks* like it might not be infinite. We have a
;; branch with a loop-like condition, but it is just a nop.
(loop $loop
(if
(i32.gt_s
(local.get $x)
(i32.const 0)
)
(then
(nop)
)
)
(local.set $x
(i32.add
(local.get $x)
(i32.const 1)
)
)
(br $loop)
)
)

;; CHECK: (func $bound (type $0)
;; CHECK-NEXT: (local $x i32)
;; CHECK-NEXT: (loop $loop
Expand Down Expand Up @@ -665,7 +710,7 @@
(br $out)
)
)
;; x > 0 && x <= 100 here (but we need loops mode to get both).
;; x > 0 && x <= 100 here.
(drop
(i32.gt_u
(local.get $x)
Expand Down
Loading