Skip to content

Commit 24c0da5

Browse files
authored
Merge pull request #705 from wado-lang/claude/update-compiler-optimizer-docs-WObXL
docs: add condition implication optimization pass
2 parents 733d792 + 58add1d commit 24c0da5

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

docs/compiler.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Source (.wado) → Lexer → Parser → Bind → Load → Analyze → Resolve
4646
| Bind | `bind.rs` | Local name binding, scope analysis, mutability check |
4747
| Loader | `loader.rs` | Module loading, dependency resolution |
4848
| Desugar | `desugar.rs` | AST transformations (compound assign, etc.) |
49-
| EffectCheck | `effect_check.rs` | Validates effect requirements for function calls |
49+
| EffectCheck | `effect_check.rs` | Validates effect requirements and stores declarations |
5050
| Unparser | `unparse.rs` | Converts AST/TIR back to source code |
5151
| Analyzer | `analyze.rs` | Semantic analysis, symbol table construction |
5252
| Symbol | `symbol.rs` | Symbol table data structures |
@@ -85,13 +85,17 @@ Source (.wado) → Lexer → Parser → Bind → Load → Analyze → Resolve
8585
| FieldScalarize | `optimize/field_scalarize.rs` | Hot field scalarization from GC structs |
8686
| BlockFusion | `optimize/labeled_block_fusion.rs` | Labeled block fusion |
8787
| StoreLoadFwd | `optimize/store_load_forward.rs` | Store-load forwarding for literal values |
88+
| CondImplication | `optimize/condition_implication.rs` | Condition implication from dominating guards |
8889
| TmplHoist | `optimize/tmpl_hoist.rs` | Template buffer hoisting out of loops |
8990
| ComponentPlan | `wir_build/component_plan.rs` | `ComponentPlan` types and `build_component_plan` |
9091
| Stdlib | `stdlib.rs` | Embedded core library sources |
9192
| CompilerHost | `compiler_host.rs` | I/O abstraction for the compiler |
9293
| Logger | `logger.rs` | Diagnostic logging with timestamps |
9394
| ComponentModel | `component_model.rs` | WASI import registry and CM ABI type support |
9495
| BuiltinRegistry | `builtin_registry.rs` | Builtin function registry from `core:builtin` |
96+
| Doc | `doc.rs` | Documentation generation from AST |
97+
| HashMap | `hashmap.rs` | Deterministic `IndexMap`/`IndexSet` type aliases |
98+
| TirVisitor | `tir_visitor.rs` | Generic visitor traits for TIR tree traversal |
9599
| WorldRegistry | `world_registry.rs` | World definitions registry for export signatures |
96100
| WIR | `wir.rs` | Wasm IR data structures |
97101
| WIR Unparse | `wir_unparse.rs` | WIR → pseudo-Wado source code for debugging |
@@ -220,8 +224,14 @@ Embedded `.wado` files in `wado-compiler/lib/`:
220224
| `core:prelude/primitive.wado` | `prelude/primitive.wado` | Primitive type trait implementations |
221225
| `core:prelude/format.wado` | `prelude/format.wado` | Format traits (Display, Formatter) |
222226
| `core:prelude/fpfmt.wado` | `prelude/fpfmt.wado` | Float-to-string formatting (pure Wado) |
227+
| `core:prelude/tuple.wado` | `prelude/tuple.wado` | Tuple trait implementations |
223228
| `core:cli` | `cli.wado` | CLI output (println, eprintln, etc.) |
224229
| `core:collections` | `collections.wado` | TreeMap and other collections |
230+
| `core:serde` | `serde.wado` | Serialization/deserialization traits |
231+
| `core:json` | `json.wado` | JSON serialization/deserialization |
232+
| `core:json_nsd` | `json_nsd.wado` | JSON non-self-describing deserializer |
233+
| `core:json_value` | `json_value.wado` | JSON value type representation |
234+
| `core:simd` | `simd.wado` | SIMD v128 operations |
225235
| `core:zlib` | `zlib.wado` | Compression (zlib/deflate) |
226236
| `core:base64` | `base64.wado` | Base64 encoding/decoding (RFC 4648) |
227237
| `core:internal` | `internal.wado` | Compiler-generated code support, panic/unreachable |

docs/optimizer.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ The optimizer runs after lowering and before Wasm emission:
3939
9. Constant Global Promotion (`const_global_promotion.rs`)
4040
10. Constant Branch Pruning (`const_branch_prune.rs`)
4141
11. Loop-Invariant Code Motion (`licm.rs`)
42-
12. Template String Buffer Hoisting (`tmpl_hoist.rs`)
42+
12. Condition Implication (`condition_implication.rs`)
43+
13. Template String Buffer Hoisting (`tmpl_hoist.rs`)
4344
3. **Hot Field Scalarization** (`field_scalarize.rs`): runs once after the loop converges
4445
4. **Final DCE**: clean up code made dead by optimizations (all levels)
4546
5. **Select Lowering** (`select_lowering.rs`): post-optimization rewrite (all levels)
@@ -116,6 +117,14 @@ Eliminates branches with compile-time-known boolean conditions. Also simplifies
116117

117118
Hoists loop-invariant field accesses out of loops when the target variable does not change within the loop body.
118119

120+
### Condition Implication (`condition_implication.rs`)
121+
122+
Eliminates conditions implied false by dominating guards. When a loop guard proves `i < bound`, any inner condition `i >= bound` is known false and can be replaced with `false`. The existing `const_branch_prune` pass then removes the dead branch on the next iteration.
123+
124+
Also handles dominating if-conditions: when `if (var + offset) < bound { ... }`, bounds checks `(var + k) >= bound` for `k <= offset` inside the then-block are known false.
125+
126+
This subsumes the former WIR-level bounds check elimination pass, handling both strict `<` and inclusive `<=` guard patterns at the TIR level.
127+
119128
### Template String Buffer Hoisting (`tmpl_hoist.rs`)
120129

121130
Hoists the backing array allocation for template strings out of loops. Each iteration reuses the same backing array buffer. Escape analysis ensures the template result is not stored beyond the iteration.
@@ -145,6 +154,7 @@ WIR-level optimizations run after WIR build and before Wasm emission, operating
145154
### Phase 1: Type Representation
146155

147156
- **Nullable ref optimization** — rewrites type-level representations for nullable references
157+
- **Pre-SROA copy propagation** — inlines trivial copies like `alias = source` so that SROA can see direct variant access patterns (RefTest/RefCast on source)
148158
- **Multi-value return SROA** — rewrites functions returning small scalar structs (2–4 fields) to use Wasm multi-value returns, eliminating GC struct allocation at function boundaries
149159
- **Single-field parameter SROA** — rewrites `ref null S` parameters (where `S` is a single-field struct) to take the scalar field value directly. Primary trigger is `Box<T>` from template string interpolation.
150160

@@ -155,8 +165,7 @@ After parameter SROA, substitutes `StructGet(LocalGet(x), field)` with the inner
155165
### Phase 3: Data Flow
156166

157167
- **Collapse array append sequences** — merges consecutive `append` calls into `array.new_fixed`
158-
- **Forward struct field constants** — tracks known field values (constants and `LocalGet` references) through `StructGet` for bounds check elimination. Also resolves block-result `StructNew` patterns for single-exit blocks. Uses stores-aware alias analysis: locals passed to functions without `stores` declarations are not marked as aliased, enabling field forwarding even when references are passed to callees
159-
- **Eliminate loop-guarded bounds checks** — removes redundant `index >= bound` checks when the loop guard dominates them. Supports both `i < bound` (strict) and `i <= limit` (inclusive) guards. For inclusive guards, resolves definition chains to verify that the bounds check bound equals `limit + 1` (e.g., `arr.used == limit + 1` when `arr = Array::filled(limit + 1, ...)`)
168+
- **Forward struct field constants** — tracks known field values (constants and `LocalGet` references) through `StructGet` for constant index bounds check elimination. Also resolves block-result `StructNew` patterns for single-exit blocks. Uses stores-aware alias analysis: locals passed to functions without `stores` declarations are not marked as aliased, enabling field forwarding even when references are passed to callees
160169

161170
### Phase 4: Library-Specific Rewrites
162171

@@ -201,7 +210,7 @@ After parameter SROA, substitutes `StructGet(LocalGet(x), field)` with the inner
201210
- **Reassociation** — reorder associative operations to group constants
202211
- **SimplifyCFG** — general control flow graph simplification
203212
- **Tail Call Optimization** — emit `return_call` for tail-recursive calls
204-
- **Bounds Check Elimination (outside loops)** — redundant consecutive checks
213+
- **Bounds Check Elimination (outside loops)** — redundant consecutive checks (loop-guarded bounds checks are handled by `condition_implication`)
205214

206215
## Testing Strategy
207216

wado-compiler/src/optimize.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ struct OptConfig {
7373
/// |-------|-----|------------|------------------|
7474
/// | O0 | Yes | 0 | N/A |
7575
/// | O1 | Yes | 2 | 5 |
76-
/// | O2 | Yes | 10 | 10 |
77-
/// | O3 | Yes | 100 | 19 |
78-
/// | Os | Yes | 10 | 10 |
76+
/// | O2 | Yes | 10 | 12 |
77+
/// | O3 | Yes | 100 | 20 |
78+
/// | Os | Yes | 10 | 12 |
7979
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8080
pub enum OptLevel {
8181
/// No optimization passes. DCE only.
@@ -84,11 +84,11 @@ pub enum OptLevel {
8484
/// Iterations: 2, Inline threshold: 5.
8585
O1,
8686
/// Production optimizations. All passes including DCE.
87-
/// Iterations: 10, Inline threshold: 10.
87+
/// Iterations: 10, Inline threshold: 12.
8888
#[default]
8989
O2,
9090
/// Aggressive production optimizations. All passes including DCE.
91-
/// Iterations: 100, Inline threshold: 19 (20 degrades fts benchmark performance).
91+
/// Iterations: 100, Inline threshold: 20.
9292
O3,
9393
/// Size optimizations. Same as O2 plus name section stripping.
9494
/// Intended for frontend/browser deployment.

0 commit comments

Comments
 (0)