/**
 * Optimize AST.
 *
 * @param {Array|string} ast - AST or WAT source
 * @param {boolean|string|Object} [opts=true] - Optimization options
 * @returns {Array} Optimized AST
 *
 * @example
 * optimize(ast)                      // all optimizations
 * optimize(ast, 'treeshake')         // only treeshake
 * optimize(ast, { fold: true })      // explicit
 */
export default function optimize(ast: any[] | string, opts?: boolean | string | any): any[];
/**
 * Recursively count AST nodes — fast size heuristic without compiling.
 * @param {any} node
 * @returns {number}
 */
export function count(node: any): number;
/**
 * Compile AST and measure binary size in bytes.
 * @param {Array} ast
 * @returns {number}
 */
export function binarySize(ast: any[]): number;
/**
 * Remove unused functions, globals, types, tables.
 * Keeps exports and their transitive dependencies.
 * @param {Array} ast
 * @returns {Array}
 */
export function treeshake(ast: any[]): any[];
/**
 * Fold constant expressions.
 * @param {Array} ast
 * @returns {Array}
 */
export function fold(ast: any[]): any[];
/**
 * Remove dead code after control flow terminators.
 * @param {Array} ast
 * @returns {Array}
 */
export function deadcode(ast: any[]): any[];
/**
 * Reuse locals of the same type to reduce total local count.
 * Basic version: deduplicate unused locals.
 * @param {Array} ast
 * @returns {Array}
 */
export function localReuse(ast: any[]): any[];
/**
 * Remove identity operations.
 * @param {Array} ast
 * @returns {Array}
 */
export function identity(ast: any[]): any[];
/**
 * Strength reduction: replace expensive ops with cheaper equivalents.
 * @param {Array} ast
 * @returns {Array}
 */
export function strength(ast: any[]): any[];
/**
 * Simplify branches with constant conditions.
 * @param {Array} ast
 * @returns {Array}
 */
export function branch(ast: any[]): any[];
export function propagate(ast: any): any;
/**
 * Inline tiny functions (single expression, no locals, no params or simple params).
 * @param {Array} ast
 * @returns {Array}
 */
export function inline(ast: any[]): any[];
/**
 * Inline functions that are called from exactly one place into their lone caller,
 * then delete them. Unlike {@link inline} (which duplicates tiny stateless bodies),
 * this never duplicates code and never inflates: each inlined function drops a
 * function-section entry, a type-section entry (if now unused), and a `call`
 * instruction, paying back only a `block`/`local.set` wrapper. This is what
 * `wasm-opt -Oz` does — collapsing helper chains down to a couple of functions —
 * and it's the bulk of the gap between hand-tuned WASM and naive codegen.
 *
 * A function `$f` qualifies when it is, all of:
 *  • named, with named params and locals (numeric indices can't be safely renamed);
 *  • referenced exactly once across the whole module, by a plain `call` (no
 *    `return_call`, `ref.func`, `elem`, `export`, or `start` reference, and not
 *    recursive);
 *  • single-result or void (a multi-value result can't be modeled as `(block (result …))`);
 *  • free of numeric (depth-relative) branch labels — those would shift under the
 *    extra block nesting — and of `return_call*` in its body.
 *
 * `(call $f a0 a1 …)` becomes
 *   (block $__inlN (result T)?
 *     (local.set $__inlN_p0 a0) (local.set $__inlN_p1 a1) …   ;; args evaluated once, in order
 *     …body, params/locals renamed to $__inlN_*, `return X` → `br $__inlN X`…)
 * and the renamed params+locals are appended to the caller's `local` decls; the
 * body's own block/loop/if labels are renamed too so they can't shadow the caller's.
 * Runs to a fixpoint so helper chains fully collapse.
 *
 * @param {Array} ast
 * @returns {Array}
 */
export function inlineOnce(ast: any[]): any[];
/**
 * Normalize options to a { passName: bool } map. An explicit object is kept
 * as-is (preserving `log`/`verbose`), with any unmentioned pass filled to its
 * default; `true` selects the defaults; a string selects only the named
 * passes (or all of them via `'all'`).
 *
 * @param {boolean|string|Object} opts
 * @returns {Object}
 */
export function normalize(opts: boolean | string | any): any;
/** Option name → default-on map — the public catalogue of passes. */
export const OPTS: any;
/**
 * Remove no-op code: nops, drop of pure expressions, empty branches,
 * and select with identical arms.
 * @param {Array} ast
 * @returns {Array}
 */
export function vacuum(ast: any[]): any[];
/**
 * Apply peephole optimizations.
 * @param {Array} ast
 * @returns {Array}
 */
export function peephole(ast: any[]): any[];
/**
 * Replace `global.get` of an immutable, const-initialised global with the
 * constant — but only when it doesn't grow the module. A `global.get` costs
 * ~2 B; an `i32.const 12345` costs 4 B; an `f64.const` costs 9 B. Naively
 * inlining a big constant read from many sites trades a few cheap reads + one
 * global decl for many fat immediates — pure bloat (and the node-count size
 * guard can't see it: same number of AST nodes). So we only propagate a global
 * when `refs·constSize ≤ refs·2 + declSize`; when every read is replaced and
 * the global isn't exported, its now-dead decl is dropped here too.
 * @param {Array} ast
 * @returns {Array}
 */
export function globals(ast: any[]): any[];
/** Match (type.load/store (i32.add ptr (type.const N))) and fold offset */
export function offset(ast: any): any;
/**
 * Remove br to a block's own label when it is the last instruction.
 * @param {Array} ast
 * @returns {Array}
 */
export function unbranch(ast: any[]): any[];
/**
 * Collapse the `while`-emit idiom into a single loop.
 *
 *   (block $A
 *     (loop $B
 *       (br_if $A (i32.eqz cond))   ;; exit when cond is false
 *       …body…
 *       (br $B)                      ;; continue
 *     ))
 *
 * becomes
 *
 *   (loop $B
 *     (if cond (then …body… (br $B))))
 *
 * Saves ~3 B per while-loop (drop the outer block framing + the `i32.eqz`,
 * trade `br_if`→`if`). Safe only when:
 *  - the block contains nothing but the loop (plus optional `type` slot),
 *  - block / loop are void (no result),
 *  - $A is never targeted from within body (only the head `br_if` uses it).
 *
 * @param {Array} ast
 * @returns {Array}
 */
export function loopify(ast: any[]): any[];
/**
 * Strip mutability from globals that are never written.
 * Enables globals constant-propagation for more globals.
 * @param {Array} ast
 * @returns {Array}
 */
export function stripmut(ast: any[]): any[];
/**
 * Simplify (if cond (then (br $label))) → (br_if $label cond)
 * and (if cond (then) (else (br $label))) → (br_if $label (i32.eqz cond))
 * Only when the br is the sole instruction in the arm.
 * @param {Array} ast
 * @returns {Array}
 */
export function brif(ast: any[]): any[];
/**
 * Fold identical trailing code out of if/else arms.
 * (if cond (then A X) (else B X)) → (if cond (then A) (else B)) X
 * @param {Array} ast
 * @returns {Array}
 */
export function foldarms(ast: any[]): any[];
/**
 * Eliminate duplicate functions by hashing bodies.
 * Keeps the first occurrence and redirects all references to it.
 * @param {Array} ast
 * @returns {Array}
 */
export function dedupe(ast: any[]): any[];
export function reorder(ast: any): any;
/**
 * Merge structurally identical (type ...) definitions.
 * Keeps the first occurrence and redirects all references.
 * @param {Array} ast
 * @returns {Array}
 */
export function dedupTypes(ast: any[]): any[];
/**
 * Pack data segments: trim trailing zeros and merge adjacent constant-offset segments.
 * @param {Array} ast
 * @returns {Array}
 */
export function packData(ast: any[]): any[];
/**
 * Minify import module and field names for smaller binaries.
 * Only safe when you control the host environment.
 * @param {Array} ast
 * @returns {Array}
 */
export function minifyImports(ast: any[]): any[];
/**
 * Unwrap redundant blocks whose label is never targeted. The block's stack
 * effect is determined entirely by its body, so removing the `block`/`end`
 * framing is sound as long as no `br` reaches into the block from inside.
 *
 * Three complementary patterns:
 *
 * 1. **Block at scope level** (sibling in `func`/`block`/`loop`/`then`/`else`):
 *    splice body into the parent scope. Works for untyped, `(result T)`-typed,
 *    or even `(param …)`-typed blocks — in all cases the body produces the
 *    same net stack effect as the framed block did, at the same position.
 * 2. **Result-typed block in expression position** (`(block (result T) expr)`
 *    as the value of some operand): collapse to `expr` if the body is a
 *    single value expression. Catches the wrappers jz codegen leaves around
 *    arena allocations once `propagate` has folded the intermediate
 *    set/get pairs to a single call.
 * 3. **Result-typed block as the sole operand of a void consumer** at scope:
 *    `(local.set $x (block (result T) stmt* expr))` → splice `stmt*` into
 *    the parent scope and rewrite the consumer to `(local.set $x expr)`.
 *    Same shape for `global.set` and `drop`. Cleans up the multi-stmt
 *    wrappers `inlineOnce` leaves when inlining helpers whose return value
 *    is fed into a single set/drop.
 *
 * Pattern 2 runs first (post-order) so patterns 1+3 see cleaned-up parents.
 * @param {Array} ast
 * @returns {Array}
 */
export function mergeBlocks(ast: any[]): any[];
/**
 * Share local slots between same-type locals with non-overlapping live ranges.
 * Live range = [first pos, last pos] of any local.get/set/tee, extended over
 * any loop containing a reference (so a value read across loop iterations stays
 * intact). Greedy slot assignment by start position. Params and unnamed/numeric
 * references are left alone; `localReuse` later removes the renamed-away decls.
 *
 * Soundness: WASM zero-initializes locals at function entry, so a local whose
 * first reference (in walk order) is a `local.get` *relies* on that implicit
 * zero — coalescing it into a slot whose previous user left a non-zero residue
 * would silently change behavior (e.g. a `for (let i=0; …)` loop counter
 * inheriting `N*4` from a sibling temp). Such "read-first" locals can still
 * serve as a slot's *primary* (the slot then keeps the function's zero start),
 * but can never be a donor merged into an existing slot.
 * @param {Array} ast
 * @returns {Array}
 */
export function coalesceLocals(ast: any[]): any[];
export { count as size };
//# sourceMappingURL=optimize.d.ts.map