summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-07-10 12:15:22 -0700
committerGitHub <noreply@github.com>2024-07-10 12:15:22 -0700
commit37a86d558994415e722e7f62f5784b1a8b8b4832 (patch)
tree282342051d33146bbda303ef97587b652b148d6a
parent76f661203f98820ebc6840ecf627a5eafc038403 (diff)
downloadbinaryen-37a86d558994415e722e7f62f5784b1a8b8b4832.tar.gz
binaryen-37a86d558994415e722e7f62f5784b1a8b8b4832.tar.bz2
binaryen-37a86d558994415e722e7f62f5784b1a8b8b4832.zip
[StackIR] Allow StackIR to be disabled from the commandline (#6725)
Normally we use it when optimizing (above a certain level). This lets the user prevent it from being used even then. Also add optimization options to wasm-metadce so that this is possible there as well and not just in wasm-opt (this also opens the door to running more passes in metadce, which may be useful later).
-rwxr-xr-xscripts/fuzz_opt.py1
-rw-r--r--src/tools/optimization-options.h17
-rw-r--r--src/tools/wasm-metadce.cpp4
-rw-r--r--test/lit/help/wasm-metadce.test721
-rw-r--r--test/lit/help/wasm-opt.test3
-rw-r--r--test/lit/help/wasm2js.test3
-rw-r--r--test/lit/passes/stack-ir-defaults.wast66
7 files changed, 737 insertions, 78 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py
index 4e1305042..2707df4c0 100755
--- a/scripts/fuzz_opt.py
+++ b/scripts/fuzz_opt.py
@@ -1565,6 +1565,7 @@ opt_choices = [
('--merge-locals',),
('--monomorphize',),
('--monomorphize-always',),
+ ('--no-stack-ir',),
('--once-reduction',),
("--optimize-casts",),
("--optimize-instructions",),
diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h
index 8772edd29..af468769d 100644
--- a/src/tools/optimization-options.h
+++ b/src/tools/optimization-options.h
@@ -26,12 +26,17 @@
namespace wasm {
struct OptimizationOptions : public ToolOptions {
+ // By default we allow StackIR and enable it by default in higher optimization
+ // levels, but users can disallow it as well.
+ bool allowStackIR = true;
+
void parse(int argc, const char* argv[]) {
ToolOptions::parse(argc, argv);
// After parsing the arguments, update defaults based on the optimize/shrink
// levels.
- if (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1) {
+ if (allowStackIR &&
+ (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1)) {
passOptions.generateStackIR = true;
passOptions.optimizeStackIR = true;
}
@@ -191,6 +196,16 @@ struct OptimizationOptions : public ToolOptions {
[&](Options* o, const std::string& arguments) {
passOptions.debugInfo = true;
})
+ .add("--no-stack-ir",
+ "",
+ "do not use StackIR (even when it is the default)",
+ ToolOptionsCategory,
+ Options::Arguments::Zero,
+ [&](Options* o, const std::string& arguments) {
+ allowStackIR = false;
+ passOptions.generateStackIR = false;
+ passOptions.optimizeStackIR = false;
+ })
.add("--always-inline-max-function-size",
"-aimfs",
"Max size of functions that are always inlined (default " +
diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp
index 301470206..9cc06375e 100644
--- a/src/tools/wasm-metadce.cpp
+++ b/src/tools/wasm-metadce.cpp
@@ -29,11 +29,11 @@
#include "asmjs/shared-constants.h"
#include "ir/element-utils.h"
#include "ir/module-utils.h"
+#include "optimization-options.h"
#include "pass.h"
#include "support/colors.h"
#include "support/file.h"
#include "support/json.h"
-#include "tool-options.h"
#include "wasm-builder.h"
#include "wasm-io.h"
#include "wasm-validator.h"
@@ -371,7 +371,7 @@ int main(int argc, const char* argv[]) {
const std::string WasmMetaDCEOption = "wasm-opt options";
- ToolOptions options(
+ OptimizationOptions options(
"wasm-metadce",
"This tool performs dead code elimination (DCE) on a larger space "
"that the wasm module is just a part of. For example, if you have "
diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test
index 453328df1..5b621caf5 100644
--- a/test/lit/help/wasm-metadce.test
+++ b/test/lit/help/wasm-metadce.test
@@ -51,146 +51,717 @@
;; CHECK-NEXT: wasm-opt options:
;; CHECK-NEXT: -----------------
;; CHECK-NEXT:
-;; CHECK-NEXT: --output,-o Output file (stdout if not specified)
+;; CHECK-NEXT: --output,-o Output file (stdout if not
+;; CHECK-NEXT: specified)
;; CHECK-NEXT:
-;; CHECK-NEXT: --input-source-map,-ism Consume source map from the specified
-;; CHECK-NEXT: file
+;; CHECK-NEXT: --input-source-map,-ism Consume source map from the
+;; CHECK-NEXT: specified file
;; CHECK-NEXT:
-;; CHECK-NEXT: --output-source-map,-osm Emit source map to the specified file
+;; CHECK-NEXT: --output-source-map,-osm Emit source map to the specified
+;; CHECK-NEXT: file
;; CHECK-NEXT:
-;; CHECK-NEXT: --output-source-map-url,-osu Emit specified string as source map URL
+;; CHECK-NEXT: --output-source-map-url,-osu Emit specified string as source
+;; CHECK-NEXT: map URL
;; CHECK-NEXT:
-;; CHECK-NEXT: --emit-text,-S Emit text instead of binary for the
-;; CHECK-NEXT: output file
+;; CHECK-NEXT: --emit-text,-S Emit text instead of binary for
+;; CHECK-NEXT: the output file
;; CHECK-NEXT:
-;; CHECK-NEXT: --debuginfo,-g Emit names section and debug info
+;; CHECK-NEXT: --debuginfo,-g Emit names section and debug
+;; CHECK-NEXT: info
;; CHECK-NEXT:
-;; CHECK-NEXT: --graph-file,-f Filename of the graph description file
+;; CHECK-NEXT: --graph-file,-f Filename of the graph
+;; CHECK-NEXT: description file
;; CHECK-NEXT:
-;; CHECK-NEXT: --dump,-d Dump the combined graph file (useful for
-;; CHECK-NEXT: debugging)
+;; CHECK-NEXT: --dump,-d Dump the combined graph file
+;; CHECK-NEXT: (useful for debugging)
+;; CHECK-NEXT:
+;; CHECK-NEXT:
+;; CHECK-NEXT: Optimization passes:
+;; CHECK-NEXT: --------------------
+;; CHECK-NEXT:
+;; CHECK-NEXT: --abstract-type-refining refine and merge abstract
+;; CHECK-NEXT: (never-created) types
+;; CHECK-NEXT:
+;; CHECK-NEXT: --alignment-lowering lower unaligned loads and stores
+;; CHECK-NEXT: to smaller aligned ones
+;; CHECK-NEXT:
+;; CHECK-NEXT: --asyncify async/await style transform,
+;; CHECK-NEXT: allowing pausing and resuming
+;; CHECK-NEXT:
+;; CHECK-NEXT: --avoid-reinterprets Tries to avoid reinterpret
+;; CHECK-NEXT: operations via more loads
+;; CHECK-NEXT:
+;; CHECK-NEXT: --cfp propagate constant struct field
+;; CHECK-NEXT: values
+;; CHECK-NEXT:
+;; CHECK-NEXT: --cfp-reftest propagate constant struct field
+;; CHECK-NEXT: values, using ref.test
+;; CHECK-NEXT:
+;; CHECK-NEXT: --coalesce-locals reduce # of locals by coalescing
+;; CHECK-NEXT:
+;; CHECK-NEXT: --coalesce-locals-learning reduce # of locals by coalescing
+;; CHECK-NEXT: and learning
+;; CHECK-NEXT:
+;; CHECK-NEXT: --code-folding fold code, merging duplicates
+;; CHECK-NEXT:
+;; CHECK-NEXT: --code-pushing push code forward, potentially
+;; CHECK-NEXT: making it not always execute
+;; CHECK-NEXT:
+;; CHECK-NEXT: --const-hoisting hoist repeated constants to a
+;; CHECK-NEXT: local
+;; CHECK-NEXT:
+;; CHECK-NEXT: --dae removes arguments to calls in an
+;; CHECK-NEXT: lto-like manner
+;; CHECK-NEXT:
+;; CHECK-NEXT: --dae-optimizing removes arguments to calls in an
+;; CHECK-NEXT: lto-like manner, and optimizes
+;; CHECK-NEXT: where we removed
+;; CHECK-NEXT:
+;; CHECK-NEXT: --dce removes unreachable code
+;; CHECK-NEXT:
+;; CHECK-NEXT: --dealign forces all loads and stores to
+;; CHECK-NEXT: have alignment 1
+;; CHECK-NEXT:
+;; CHECK-NEXT: --denan instrument the wasm to convert
+;; CHECK-NEXT: NaNs into 0 at runtime
+;; CHECK-NEXT:
+;; CHECK-NEXT: --dfo optimizes using the DataFlow SSA
+;; CHECK-NEXT: IR
+;; CHECK-NEXT:
+;; CHECK-NEXT: --directize turns indirect calls into direct
+;; CHECK-NEXT: ones
+;; CHECK-NEXT:
+;; CHECK-NEXT: --discard-global-effects discards global effect info
+;; CHECK-NEXT:
+;; CHECK-NEXT: --duplicate-function-elimination removes duplicate functions
+;; CHECK-NEXT:
+;; CHECK-NEXT: --duplicate-import-elimination removes duplicate imports
+;; CHECK-NEXT:
+;; CHECK-NEXT: --dwarfdump dump DWARF debug info sections
+;; CHECK-NEXT: from the read binary
+;; CHECK-NEXT:
+;; CHECK-NEXT: --emit-target-features emit the target features section
+;; CHECK-NEXT: in the output
+;; CHECK-NEXT:
+;; CHECK-NEXT: --extract-function leaves just one function (useful
+;; CHECK-NEXT: for debugging)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --extract-function-index leaves just one function
+;; CHECK-NEXT: selected by index
+;; CHECK-NEXT:
+;; CHECK-NEXT: --flatten flattens out code, removing
+;; CHECK-NEXT: nesting
+;; CHECK-NEXT:
+;; CHECK-NEXT: --fpcast-emu emulates function pointer casts,
+;; CHECK-NEXT: allowing incorrect indirect
+;; CHECK-NEXT: calls to (sometimes) work
+;; CHECK-NEXT:
+;; CHECK-NEXT: --func-metrics reports function metrics
+;; CHECK-NEXT:
+;; CHECK-NEXT: --generate-dyncalls generate dynCall fuctions used
+;; CHECK-NEXT: by emscripten ABI
+;; CHECK-NEXT:
+;; CHECK-NEXT: --generate-global-effects generate global effect info
+;; CHECK-NEXT: (helps later passes)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --generate-i64-dyncalls generate dynCall functions used
+;; CHECK-NEXT: by emscripten ABI, but only for
+;; CHECK-NEXT: functions with i64 in their
+;; CHECK-NEXT: signature (which cannot be
+;; CHECK-NEXT: invoked via the wasm table
+;; CHECK-NEXT: without JavaScript BigInt
+;; CHECK-NEXT: support).
+;; CHECK-NEXT:
+;; CHECK-NEXT: --global-refining refine the types of globals
+;; CHECK-NEXT:
+;; CHECK-NEXT: --gsi globally optimize struct values
+;; CHECK-NEXT:
+;; CHECK-NEXT: --gto globally optimize GC types
+;; CHECK-NEXT:
+;; CHECK-NEXT: --gufa Grand Unified Flow Analysis:
+;; CHECK-NEXT: optimize the entire program
+;; CHECK-NEXT: using information about what
+;; CHECK-NEXT: content can actually appear in
+;; CHECK-NEXT: each location
+;; CHECK-NEXT:
+;; CHECK-NEXT: --gufa-cast-all GUFA plus add casts for all
+;; CHECK-NEXT: inferences
+;; CHECK-NEXT:
+;; CHECK-NEXT: --gufa-optimizing GUFA plus local optimizations in
+;; CHECK-NEXT: functions we modified
+;; CHECK-NEXT:
+;; CHECK-NEXT: --heap2local replace GC allocations with
+;; CHECK-NEXT: locals
+;; CHECK-NEXT:
+;; CHECK-NEXT: --i64-to-i32-lowering lower all uses of i64s to use
+;; CHECK-NEXT: i32s instead
+;; CHECK-NEXT:
+;; CHECK-NEXT: --inline-main inline __original_main into main
+;; CHECK-NEXT:
+;; CHECK-NEXT: --inlining inline functions (you probably
+;; CHECK-NEXT: want inlining-optimizing)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --inlining-optimizing inline functions and optimizes
+;; CHECK-NEXT: where we inlined
+;; CHECK-NEXT:
+;; CHECK-NEXT: --instrument-locals instrument the build with code
+;; CHECK-NEXT: to intercept all loads and
+;; CHECK-NEXT: stores
+;; CHECK-NEXT:
+;; CHECK-NEXT: --instrument-memory instrument the build with code
+;; CHECK-NEXT: to intercept all loads and
+;; CHECK-NEXT: stores
+;; CHECK-NEXT:
+;; CHECK-NEXT: --intrinsic-lowering lower away binaryen intrinsics
+;; CHECK-NEXT:
+;; CHECK-NEXT: --jspi wrap imports and exports for
+;; CHECK-NEXT: JavaScript promise integration
+;; CHECK-NEXT:
+;; CHECK-NEXT: --legalize-and-prune-js-interface legalizes the import/export
+;; CHECK-NEXT: boundary and prunes when needed
+;; CHECK-NEXT:
+;; CHECK-NEXT: --legalize-js-interface legalizes i64 types on the
+;; CHECK-NEXT: import/export boundary
+;; CHECK-NEXT:
+;; CHECK-NEXT: --licm loop invariant code motion
+;; CHECK-NEXT:
+;; CHECK-NEXT: --limit-segments attempt to merge segments to fit
+;; CHECK-NEXT: within web limits
+;; CHECK-NEXT:
+;; CHECK-NEXT: --local-cse common subexpression elimination
+;; CHECK-NEXT: inside basic blocks
+;; CHECK-NEXT:
+;; CHECK-NEXT: --local-subtyping apply more specific subtypes to
+;; CHECK-NEXT: locals where possible
+;; CHECK-NEXT:
+;; CHECK-NEXT: --log-execution instrument the build with
+;; CHECK-NEXT: logging of where execution goes
+;; CHECK-NEXT:
+;; CHECK-NEXT: --memory-packing packs memory into separate
+;; CHECK-NEXT: segments, skipping zeros
+;; CHECK-NEXT:
+;; CHECK-NEXT: --memory64-lowering lower loads and stores to a
+;; CHECK-NEXT: 64-bit memory to instead use a
+;; CHECK-NEXT: 32-bit one
+;; CHECK-NEXT:
+;; CHECK-NEXT: --merge-blocks merges blocks to their parents
+;; CHECK-NEXT:
+;; CHECK-NEXT: --merge-locals merges locals when beneficial
+;; CHECK-NEXT:
+;; CHECK-NEXT: --merge-similar-functions merges similar functions when
+;; CHECK-NEXT: benefical
+;; CHECK-NEXT:
+;; CHECK-NEXT: --metrics reports metrics
+;; CHECK-NEXT:
+;; CHECK-NEXT: --minify-imports minifies import names (only
+;; CHECK-NEXT: those, and not export names),
+;; CHECK-NEXT: and emits a mapping to the
+;; CHECK-NEXT: minified ones
+;; CHECK-NEXT:
+;; CHECK-NEXT: --minify-imports-and-exports minifies both import and export
+;; CHECK-NEXT: names, and emits a mapping to
+;; CHECK-NEXT: the minified ones
+;; CHECK-NEXT:
+;; CHECK-NEXT: --minify-imports-and-exports-and-modules minifies both import and export
+;; CHECK-NEXT: names, and emits a mapping to
+;; CHECK-NEXT: the minified ones, and minifies
+;; CHECK-NEXT: the modules as well
+;; CHECK-NEXT:
+;; CHECK-NEXT: --mod-asyncify-always-and-only-unwind apply the assumption that
+;; CHECK-NEXT: asyncify imports always unwind,
+;; CHECK-NEXT: and we never rewind
+;; CHECK-NEXT:
+;; CHECK-NEXT: --mod-asyncify-never-unwind apply the assumption that
+;; CHECK-NEXT: asyncify never unwinds
+;; CHECK-NEXT:
+;; CHECK-NEXT: --monomorphize creates specialized versions of
+;; CHECK-NEXT: functions
+;; CHECK-NEXT:
+;; CHECK-NEXT: --monomorphize-always creates specialized versions of
+;; CHECK-NEXT: functions (even if unhelpful)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --multi-memory-lowering combines multiple memories into
+;; CHECK-NEXT: a single memory
+;; CHECK-NEXT:
+;; CHECK-NEXT: --multi-memory-lowering-with-bounds-checks combines multiple memories into
+;; CHECK-NEXT: a single memory, trapping if the
+;; CHECK-NEXT: read or write is larger than the
+;; CHECK-NEXT: length of the memory's data
+;; CHECK-NEXT:
+;; CHECK-NEXT: --name-types (re)name all heap types
+;; CHECK-NEXT:
+;; CHECK-NEXT: --nm name list
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-full-inline mark functions as no-inline (for
+;; CHECK-NEXT: full inlining only)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-inline mark functions as no-inline
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-partial-inline mark functions as no-inline (for
+;; CHECK-NEXT: partial inlining only)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --once-reduction reduces calls to code that only
+;; CHECK-NEXT: runs once
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-added-constants optimizes added constants into
+;; CHECK-NEXT: load/store offsets
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-added-constants-propagate optimizes added constants into
+;; CHECK-NEXT: load/store offsets, propagating
+;; CHECK-NEXT: them across locals too
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-casts eliminate and reuse casts
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-for-js early optimize of the
+;; CHECK-NEXT: instruction combinations for js
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-instructions optimizes instruction
+;; CHECK-NEXT: combinations
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-j2cl optimizes J2CL specific
+;; CHECK-NEXT: constructs.
+;; CHECK-NEXT:
+;; CHECK-NEXT: --outlining outline instructions
+;; CHECK-NEXT:
+;; CHECK-NEXT: --pick-load-signs pick load signs based on their
+;; CHECK-NEXT: uses
+;; CHECK-NEXT:
+;; CHECK-NEXT: --poppify Tranform Binaryen IR into Poppy
+;; CHECK-NEXT: IR
+;; CHECK-NEXT:
+;; CHECK-NEXT: --post-emscripten miscellaneous optimizations for
+;; CHECK-NEXT: Emscripten-generated code
+;; CHECK-NEXT:
+;; CHECK-NEXT: --precompute computes compile-time
+;; CHECK-NEXT: evaluatable expressions
+;; CHECK-NEXT:
+;; CHECK-NEXT: --precompute-propagate computes compile-time
+;; CHECK-NEXT: evaluatable expressions and
+;; CHECK-NEXT: propagates them through locals
+;; CHECK-NEXT:
+;; CHECK-NEXT: --print print in s-expression format
+;; CHECK-NEXT:
+;; CHECK-NEXT: --print-call-graph print call graph
+;; CHECK-NEXT:
+;; CHECK-NEXT: --print-features print options for enabled
+;; CHECK-NEXT: features
+;; CHECK-NEXT:
+;; CHECK-NEXT: --print-full print in full s-expression
+;; CHECK-NEXT: format
+;; CHECK-NEXT:
+;; CHECK-NEXT: --print-function-map print a map of function indexes
+;; CHECK-NEXT: to names
+;; CHECK-NEXT:
+;; CHECK-NEXT: --print-minified print in minified s-expression
+;; CHECK-NEXT: format
+;; CHECK-NEXT:
+;; CHECK-NEXT: --propagate-debug-locs propagate debug location from
+;; CHECK-NEXT: parents or previous siblings to
+;; CHECK-NEXT: child nodes
+;; CHECK-NEXT:
+;; CHECK-NEXT: --propagate-globals-globally propagate global values to other
+;; CHECK-NEXT: globals (useful for tests)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-imports removes imports and replaces
+;; CHECK-NEXT: them with nops
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-memory removes memory segments
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-non-js-ops removes operations incompatible
+;; CHECK-NEXT: with js
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-unused-brs removes breaks from locations
+;; CHECK-NEXT: that are not needed
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-unused-module-elements removes unused module elements
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-unused-names removes names from locations
+;; CHECK-NEXT: that are never branched to
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-unused-nonfunction-module-elements removes unused module elements
+;; CHECK-NEXT: that are not functions
+;; CHECK-NEXT:
+;; CHECK-NEXT: --remove-unused-types remove unused private GC types
+;; CHECK-NEXT:
+;; CHECK-NEXT: --reorder-functions sorts functions by access
+;; CHECK-NEXT: frequency
+;; CHECK-NEXT:
+;; CHECK-NEXT: --reorder-functions-by-name sorts functions by name (useful
+;; CHECK-NEXT: for debugging)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --reorder-globals sorts globals by access
+;; CHECK-NEXT: frequency
+;; CHECK-NEXT:
+;; CHECK-NEXT: --reorder-locals sorts locals by access frequency
+;; CHECK-NEXT:
+;; CHECK-NEXT: --rereloop re-optimize control flow using
+;; CHECK-NEXT: the relooper algorithm
+;; CHECK-NEXT:
+;; CHECK-NEXT: --roundtrip write the module to binary, then
+;; CHECK-NEXT: read it
+;; CHECK-NEXT:
+;; CHECK-NEXT: --rse remove redundant local.sets
+;; CHECK-NEXT:
+;; CHECK-NEXT: --safe-heap instrument loads and stores to
+;; CHECK-NEXT: check for invalid behavior
+;; CHECK-NEXT:
+;; CHECK-NEXT: --separate-data-segments write data segments to a file
+;; CHECK-NEXT: and strip them from the module
+;; CHECK-NEXT:
+;; CHECK-NEXT: --set-globals sets specified globals to
+;; CHECK-NEXT: specified values
+;; CHECK-NEXT:
+;; CHECK-NEXT: --signature-pruning remove params from function
+;; CHECK-NEXT: signature types where possible
+;; CHECK-NEXT:
+;; CHECK-NEXT: --signature-refining apply more specific subtypes to
+;; CHECK-NEXT: signature types where possible
+;; CHECK-NEXT:
+;; CHECK-NEXT: --signext-lowering lower sign-ext operations to
+;; CHECK-NEXT: wasm mvp and disable the sign
+;; CHECK-NEXT: extension feature
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-globals miscellaneous globals-related
+;; CHECK-NEXT: optimizations
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-globals-optimizing miscellaneous globals-related
+;; CHECK-NEXT: optimizations, and optimizes
+;; CHECK-NEXT: where we replaced global.gets
+;; CHECK-NEXT: with constants
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-locals miscellaneous locals-related
+;; CHECK-NEXT: optimizations
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-locals-nonesting miscellaneous locals-related
+;; CHECK-NEXT: optimizations (no nesting at
+;; CHECK-NEXT: all; preserves flatness)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-locals-nostructure miscellaneous locals-related
+;; CHECK-NEXT: optimizations (no structure)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-locals-notee miscellaneous locals-related
+;; CHECK-NEXT: optimizations (no tees)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --simplify-locals-notee-nostructure miscellaneous locals-related
+;; CHECK-NEXT: optimizations (no tees or
+;; CHECK-NEXT: structure)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --souperify emit Souper IR in text form
+;; CHECK-NEXT:
+;; CHECK-NEXT: --souperify-single-use emit Souper IR in text form
+;; CHECK-NEXT: (single-use nodes only)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --spill-pointers spill pointers to the C stack
+;; CHECK-NEXT: (useful for Boehm-style GC)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --ssa ssa-ify variables so that they
+;; CHECK-NEXT: have a single assignment
+;; CHECK-NEXT:
+;; CHECK-NEXT: --ssa-nomerge ssa-ify variables so that they
+;; CHECK-NEXT: have a single assignment,
+;; CHECK-NEXT: ignoring merges
+;; CHECK-NEXT:
+;; CHECK-NEXT: --stack-check enforce limits on llvm's
+;; CHECK-NEXT: __stack_pointer global
+;; CHECK-NEXT:
+;; CHECK-NEXT: --string-gathering gathers wasm strings to globals
+;; CHECK-NEXT:
+;; CHECK-NEXT: --string-lowering lowers wasm strings and
+;; CHECK-NEXT: operations to imports
+;; CHECK-NEXT:
+;; CHECK-NEXT: --string-lowering-magic-imports same as string-lowering, but
+;; CHECK-NEXT: encodes well-formed strings as
+;; CHECK-NEXT: magic imports
+;; CHECK-NEXT:
+;; CHECK-NEXT: --strip deprecated; same as strip-debug
+;; CHECK-NEXT:
+;; CHECK-NEXT: --strip-debug strip debug info (including the
+;; CHECK-NEXT: names section)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --strip-dwarf strip dwarf debug info
+;; CHECK-NEXT:
+;; CHECK-NEXT: --strip-eh strip EH instructions
+;; CHECK-NEXT:
+;; CHECK-NEXT: --strip-producers strip the wasm producers section
+;; CHECK-NEXT:
+;; CHECK-NEXT: --strip-target-features strip the wasm target features
+;; CHECK-NEXT: section
+;; CHECK-NEXT:
+;; CHECK-NEXT: --stub-unsupported-js stub out unsupported JS
+;; CHECK-NEXT: operations
+;; CHECK-NEXT:
+;; CHECK-NEXT: --symbolmap (alias for print-function-map)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --table64-lowering lower 64-bit tables 32-bit ones
+;; CHECK-NEXT:
+;; CHECK-NEXT: --trace-calls instrument the build with code
+;; CHECK-NEXT: to intercept specific function
+;; CHECK-NEXT: calls
+;; CHECK-NEXT:
+;; CHECK-NEXT: --translate-to-exnref translate old Phase 3 EH
+;; CHECK-NEXT: instructions to new ones with
+;; CHECK-NEXT: exnref
+;; CHECK-NEXT:
+;; CHECK-NEXT: --translate-to-new-eh deprecated; same as
+;; CHECK-NEXT: translate-to-exnref
+;; CHECK-NEXT:
+;; CHECK-NEXT: --trap-mode-clamp replace trapping operations with
+;; CHECK-NEXT: clamping semantics
+;; CHECK-NEXT:
+;; CHECK-NEXT: --trap-mode-js replace trapping operations with
+;; CHECK-NEXT: js semantics
+;; CHECK-NEXT:
+;; CHECK-NEXT: --tuple-optimization optimize trivial tuples away
+;; CHECK-NEXT:
+;; CHECK-NEXT: --type-finalizing mark all leaf types as final
+;; CHECK-NEXT:
+;; CHECK-NEXT: --type-merging merge types to their supertypes
+;; CHECK-NEXT: where possible
+;; CHECK-NEXT:
+;; CHECK-NEXT: --type-refining apply more specific subtypes to
+;; CHECK-NEXT: type fields where possible
+;; CHECK-NEXT:
+;; CHECK-NEXT: --type-ssa create new nominal types to help
+;; CHECK-NEXT: other optimizations
+;; CHECK-NEXT:
+;; CHECK-NEXT: --type-unfinalizing mark all types as non-final
+;; CHECK-NEXT: (open)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --unsubtyping removes unnecessary subtyping
+;; CHECK-NEXT: relationships
+;; CHECK-NEXT:
+;; CHECK-NEXT: --untee removes local.tees, replacing
+;; CHECK-NEXT: them with sets and gets
+;; CHECK-NEXT:
+;; CHECK-NEXT: --vacuum removes obviously unneeded code
+;; CHECK-NEXT:
+;; CHECK-NEXT:
+;; CHECK-NEXT: Optimization options:
+;; CHECK-NEXT: ---------------------
+;; CHECK-NEXT:
+;; CHECK-NEXT: -O execute default optimization
+;; CHECK-NEXT: passes (equivalent to -Os)
+;; CHECK-NEXT:
+;; CHECK-NEXT: -O0 execute no optimization passes
+;; CHECK-NEXT:
+;; CHECK-NEXT: -O1 execute -O1 optimization passes
+;; CHECK-NEXT: (quick&useful opts, useful for
+;; CHECK-NEXT: iteration builds)
+;; CHECK-NEXT:
+;; CHECK-NEXT: -O2 execute -O2 optimization passes
+;; CHECK-NEXT: (most opts, generally gets most
+;; CHECK-NEXT: perf)
+;; CHECK-NEXT:
+;; CHECK-NEXT: -O3 execute -O3 optimization passes
+;; CHECK-NEXT: (spends potentially a lot of
+;; CHECK-NEXT: time optimizing)
+;; CHECK-NEXT:
+;; CHECK-NEXT: -O4 execute -O4 optimization passes
+;; CHECK-NEXT: (also flatten the IR, which can
+;; CHECK-NEXT: take a lot more time and memory,
+;; CHECK-NEXT: but is useful on more nested /
+;; CHECK-NEXT: complex / less-optimized input)
+;; CHECK-NEXT:
+;; CHECK-NEXT: -Os execute default optimization
+;; CHECK-NEXT: passes, focusing on code size
+;; CHECK-NEXT:
+;; CHECK-NEXT: -Oz execute default optimization
+;; CHECK-NEXT: passes, super-focusing on code
+;; CHECK-NEXT: size
+;; CHECK-NEXT:
+;; CHECK-NEXT: --optimize-level,-ol How much to focus on optimizing
+;; CHECK-NEXT: code
+;; CHECK-NEXT:
+;; CHECK-NEXT: --shrink-level,-s How much to focus on shrinking
+;; CHECK-NEXT: code size
+;; CHECK-NEXT:
+;; CHECK-NEXT: --debuginfo,-g Emit names section in wasm
+;; CHECK-NEXT: binary (or full debuginfo in
+;; CHECK-NEXT: wast)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --always-inline-max-function-size,-aimfs Max size of functions that are
+;; CHECK-NEXT: always inlined (default 2, which
+;; CHECK-NEXT: is safe for use with -Os builds)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --flexible-inline-max-function-size,-fimfs Max size of functions that are
+;; CHECK-NEXT: inlined when lightweight (no
+;; CHECK-NEXT: loops or function calls) when
+;; CHECK-NEXT: optimizing aggressively for
+;; CHECK-NEXT: speed (-O3). Default: 20
+;; CHECK-NEXT:
+;; CHECK-NEXT: --one-caller-inline-max-function-size,-ocimfs Max size of functions that are
+;; CHECK-NEXT: inlined when there is only one
+;; CHECK-NEXT: caller (default -1, which means
+;; CHECK-NEXT: all such functions are inlined)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --inline-functions-with-loops,-ifwl Allow inlining functions with
+;; CHECK-NEXT: loops
+;; CHECK-NEXT:
+;; CHECK-NEXT: --partial-inlining-ifs,-pii Number of ifs allowed in partial
+;; CHECK-NEXT: inlining (zero means partial
+;; CHECK-NEXT: inlining is disabled) (default:
+;; CHECK-NEXT: 0)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --ignore-implicit-traps,-iit Optimize under the helpful
+;; CHECK-NEXT: assumption that no surprising
+;; CHECK-NEXT: traps occur (from load, div/mod,
+;; CHECK-NEXT: etc.)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --traps-never-happen,-tnh Optimize under the helpful
+;; CHECK-NEXT: assumption that no trap is
+;; CHECK-NEXT: reached at runtime (from load,
+;; CHECK-NEXT: div/mod, etc.)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --low-memory-unused,-lmu Optimize under the helpful
+;; CHECK-NEXT: assumption that the low 1K of
+;; CHECK-NEXT: memory is not used by the
+;; CHECK-NEXT: application
+;; CHECK-NEXT:
+;; CHECK-NEXT: --fast-math,-ffm Optimize floats without handling
+;; CHECK-NEXT: corner cases of NaNs and
+;; CHECK-NEXT: rounding
+;; CHECK-NEXT:
+;; CHECK-NEXT: --zero-filled-memory,-uim Assume that an imported memory
+;; CHECK-NEXT: will be zero-initialized
+;; CHECK-NEXT:
+;; CHECK-NEXT: --skip-pass,-sp Skip a pass (do not run it)
;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: Tool options:
;; CHECK-NEXT: -------------
;; CHECK-NEXT:
-;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features
+;; CHECK-NEXT: --mvp-features,-mvp Disable all non-MVP features
+;; CHECK-NEXT:
+;; CHECK-NEXT: --all-features,-all Enable all features
;; CHECK-NEXT:
-;; CHECK-NEXT: --all-features,-all Enable all features
+;; CHECK-NEXT: --detect-features (deprecated - this flag does
+;; CHECK-NEXT: nothing)
;; CHECK-NEXT:
-;; CHECK-NEXT: --detect-features (deprecated - this flag does nothing)
+;; CHECK-NEXT: --quiet,-q Emit less verbose output and
+;; CHECK-NEXT: hide trivial warnings.
;; CHECK-NEXT:
-;; CHECK-NEXT: --quiet,-q Emit less verbose output and hide trivial
-;; CHECK-NEXT: warnings.
+;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for
+;; CHECK-NEXT: testing purposes.
;; CHECK-NEXT:
-;; CHECK-NEXT: --experimental-poppy Parse wast files as Poppy IR for testing
-;; CHECK-NEXT: purposes.
+;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-sign-ext Enable sign extension operations
+;; CHECK-NEXT: --disable-sign-ext Disable sign extension
+;; CHECK-NEXT: operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-sign-ext Disable sign extension operations
+;; CHECK-NEXT: --enable-threads Enable atomic operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-threads Enable atomic operations
+;; CHECK-NEXT: --disable-threads Disable atomic operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-threads Disable atomic operations
+;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-mutable-globals Enable mutable globals
+;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-mutable-globals Disable mutable globals
+;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int
+;; CHECK-NEXT: operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-nontrapping-float-to-int Enable nontrapping float-to-int
-;; CHECK-NEXT: operations
+;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int
+;; CHECK-NEXT: operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-nontrapping-float-to-int Disable nontrapping float-to-int
-;; CHECK-NEXT: operations
+;; CHECK-NEXT: --enable-simd Enable SIMD operations and types
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-simd Enable SIMD operations and types
+;; CHECK-NEXT: --disable-simd Disable SIMD operations and
+;; CHECK-NEXT: types
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-simd Disable SIMD operations and types
+;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-bulk-memory Enable bulk memory operations
+;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-bulk-memory Disable bulk memory operations
+;; CHECK-NEXT: --enable-exception-handling Enable exception handling
+;; CHECK-NEXT: operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-exception-handling Enable exception handling operations
+;; CHECK-NEXT: --disable-exception-handling Disable exception handling
+;; CHECK-NEXT: operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-exception-handling Disable exception handling operations
+;; CHECK-NEXT: --enable-tail-call Enable tail call operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-tail-call Enable tail call operations
+;; CHECK-NEXT: --disable-tail-call Disable tail call operations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-tail-call Disable tail call operations
+;; CHECK-NEXT: --enable-reference-types Enable reference types
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-reference-types Enable reference types
+;; CHECK-NEXT: --disable-reference-types Disable reference types
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-reference-types Disable reference types
+;; CHECK-NEXT: --enable-multivalue Enable multivalue functions
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-multivalue Enable multivalue functions
+;; CHECK-NEXT: --disable-multivalue Disable multivalue functions
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-multivalue Disable multivalue functions
+;; CHECK-NEXT: --enable-gc Enable garbage collection
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-gc Enable garbage collection
+;; CHECK-NEXT: --disable-gc Disable garbage collection
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-gc Disable garbage collection
+;; CHECK-NEXT: --enable-memory64 Enable memory64
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-memory64 Enable memory64
+;; CHECK-NEXT: --disable-memory64 Disable memory64
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-memory64 Disable memory64
+;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD
+;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD
+;; CHECK-NEXT: --enable-extended-const Enable extended const
+;; CHECK-NEXT: expressions
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-extended-const Enable extended const expressions
+;; CHECK-NEXT: --disable-extended-const Disable extended const
+;; CHECK-NEXT: expressions
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-extended-const Disable extended const expressions
+;; CHECK-NEXT: --enable-strings Enable strings
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-strings Enable strings
+;; CHECK-NEXT: --disable-strings Disable strings
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-strings Disable strings
+;; CHECK-NEXT: --enable-multimemory Enable multimemory
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-multimemory Enable multimemory
+;; CHECK-NEXT: --disable-multimemory Disable multimemory
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-multimemory Disable multimemory
+;; CHECK-NEXT: --enable-typed-continuations Enable typed continuations
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-typed-continuations Enable typed continuations
+;; CHECK-NEXT: --disable-typed-continuations Disable typed continuations
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-typed-continuations Disable typed continuations
+;; CHECK-NEXT: --enable-shared-everything Enable shared-everything threads
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-shared-everything Enable shared-everything threads
+;; CHECK-NEXT: --disable-shared-everything Disable shared-everything
+;; CHECK-NEXT: threads
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-shared-everything Disable shared-everything threads
+;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag
;; CHECK-NEXT:
-;; CHECK-NEXT: --enable-typed-function-references Deprecated compatibility flag
+;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag
;; CHECK-NEXT:
-;; CHECK-NEXT: --disable-typed-function-references Deprecated compatibility flag
+;; CHECK-NEXT: --no-validation,-n Disables validation, assumes
+;; CHECK-NEXT: inputs are correct
;; CHECK-NEXT:
-;; CHECK-NEXT: --no-validation,-n Disables validation, assumes inputs are
-;; CHECK-NEXT: correct
+;; CHECK-NEXT: --pass-arg,-pa An argument passed along to
+;; CHECK-NEXT: optimization passes being run.
+;; CHECK-NEXT: Must be in the form KEY@VALUE
;; CHECK-NEXT:
-;; CHECK-NEXT: --pass-arg,-pa An argument passed along to optimization
-;; CHECK-NEXT: passes being run. Must be in the form
-;; CHECK-NEXT: KEY@VALUE
+;; CHECK-NEXT: --closed-world,-cw Assume code outside of the
+;; CHECK-NEXT: module does not inspect or
+;; CHECK-NEXT: interact with GC and function
+;; CHECK-NEXT: references, even if they are
+;; CHECK-NEXT: passed out. The outside may hold
+;; CHECK-NEXT: on to them and pass them back
+;; CHECK-NEXT: in, but not inspect their
+;; CHECK-NEXT: contents or call them.
;; CHECK-NEXT:
-;; CHECK-NEXT: --closed-world,-cw Assume code outside of the module does
-;; CHECK-NEXT: not inspect or interact with GC and
-;; CHECK-NEXT: function references, even if they are
-;; CHECK-NEXT: passed out. The outside may hold on to
-;; CHECK-NEXT: them and pass them back in, but not
-;; CHECK-NEXT: inspect their contents or call them.
+;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing
;; CHECK-NEXT:
-;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing
+;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing
;; CHECK-NEXT:
-;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing
+;; CHECK-NEXT: --print-stack-ir print StackIR during writing
;; CHECK-NEXT:
-;; CHECK-NEXT: --print-stack-ir print StackIR during writing
+;; CHECK-NEXT: --no-stack-ir do not use StackIR (even when it
+;; CHECK-NEXT: is the default)
;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: General options:
;; CHECK-NEXT: ----------------
;; CHECK-NEXT:
-;; CHECK-NEXT: --version Output version information and exit
+;; CHECK-NEXT: --version Output version information and
+;; CHECK-NEXT: exit
;; CHECK-NEXT:
-;; CHECK-NEXT: --help,-h Show this help message and exit
+;; CHECK-NEXT: --help,-h Show this help message and exit
;; CHECK-NEXT:
-;; CHECK-NEXT: --debug,-d Print debug information to stderr
+;; CHECK-NEXT: --debug,-d Print debug information to
+;; CHECK-NEXT: stderr
;; CHECK-NEXT:
diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test
index 76566049e..9f7caf98b 100644
--- a/test/lit/help/wasm-opt.test
+++ b/test/lit/help/wasm-opt.test
@@ -759,6 +759,9 @@
;; CHECK-NEXT:
;; CHECK-NEXT: --print-stack-ir print StackIR during writing
;; CHECK-NEXT:
+;; CHECK-NEXT: --no-stack-ir do not use StackIR (even when it
+;; CHECK-NEXT: is the default)
+;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: General options:
;; CHECK-NEXT: ----------------
diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test
index 8e305cfb9..ca731d277 100644
--- a/test/lit/help/wasm2js.test
+++ b/test/lit/help/wasm2js.test
@@ -713,6 +713,9 @@
;; CHECK-NEXT:
;; CHECK-NEXT: --print-stack-ir print StackIR during writing
;; CHECK-NEXT:
+;; CHECK-NEXT: --no-stack-ir do not use StackIR (even when it
+;; CHECK-NEXT: is the default)
+;; CHECK-NEXT:
;; CHECK-NEXT:
;; CHECK-NEXT: General options:
;; CHECK-NEXT: ----------------
diff --git a/test/lit/passes/stack-ir-defaults.wast b/test/lit/passes/stack-ir-defaults.wast
new file mode 100644
index 000000000..1ea8bbf24
--- /dev/null
+++ b/test/lit/passes/stack-ir-defaults.wast
@@ -0,0 +1,66 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+
+;; Request StackIR explicitly. This optimizes.
+;; RUN: wasm-opt %s --generate-stack-ir --optimize-stack-ir -all --print-stack-ir | filecheck %s --check-prefix=REQUESTED
+
+;; As above, but disallow it later. This does not optimize.
+;; RUN: wasm-opt %s --generate-stack-ir --optimize-stack-ir -all --no-stack-ir --print-stack-ir | filecheck %s --check-prefix=DISALLOWD
+
+;; As above, but flip it, so we allow it after disallowing. This optimizes.
+;; RUN: wasm-opt %s --no-stack-ir --generate-stack-ir --optimize-stack-ir -all --print-stack-ir | filecheck %s --check-prefix=REALLOWED
+
+;; Running -O will use StackIR by default. This optimizes.
+;; RUN: wasm-opt %s -O -all --print-stack-ir | filecheck %s --check-prefix=O_DEFAULT
+
+;; As above, but disallow it. This does not optimize.
+;; RUN: wasm-opt %s -O --no-stack-ir -all --print-stack-ir | filecheck %s --check-prefix=O__DENIED
+
+;; As above, but flip it. This still does not optimize, as the global state of
+;; --no-stack-ir is not overridden (before we explicitly overrode it, while here
+;; we -O only requests StackIR if allowed).
+;; RUN: wasm-opt %s --no-stack-ir -O -all --print-stack-ir | filecheck %s --check-prefix=O_REALLOW
+
+(module
+ ;; REQUESTED: (import "a" "b" (func $import (type $0) (result i32)))
+ ;; DISALLOWD: (import "a" "b" (func $import (type $0) (result i32)))
+ ;; REALLOWED: (import "a" "b" (func $import (type $0) (result i32)))
+ ;; O_DEFAULT: (import "a" "b" (func $import (type $0) (result i32)))
+ ;; O__DENIED: (import "a" "b" (func $import (type $0) (result i32)))
+ ;; O_REALLOW: (import "a" "b" (func $import (type $0) (result i32)))
+ (import "a" "b" (func $import (result i32)))
+
+ ;; REQUESTED: (func $func (type $0) (result i32)
+ ;; REQUESTED-NEXT: call $import
+ ;; REQUESTED-NEXT: unreachable
+ ;; REQUESTED-NEXT: )
+ ;; DISALLOWD: (func $func (type $0) (result i32)
+ ;; DISALLOWD-NEXT: call $import
+ ;; DISALLOWD-NEXT: drop
+ ;; DISALLOWD-NEXT: unreachable
+ ;; DISALLOWD-NEXT: )
+ ;; REALLOWED: (func $func (type $0) (result i32)
+ ;; REALLOWED-NEXT: call $import
+ ;; REALLOWED-NEXT: unreachable
+ ;; REALLOWED-NEXT: )
+ ;; O_DEFAULT: (func $func (type $0) (result i32)
+ ;; O_DEFAULT-NEXT: call $import
+ ;; O_DEFAULT-NEXT: unreachable
+ ;; O_DEFAULT-NEXT: )
+ ;; O__DENIED: (func $func (type $0) (result i32)
+ ;; O__DENIED-NEXT: call $import
+ ;; O__DENIED-NEXT: drop
+ ;; O__DENIED-NEXT: unreachable
+ ;; O__DENIED-NEXT: )
+ ;; O_REALLOW: (func $func (type $0) (result i32)
+ ;; O_REALLOW-NEXT: call $import
+ ;; O_REALLOW-NEXT: drop
+ ;; O_REALLOW-NEXT: unreachable
+ ;; O_REALLOW-NEXT: )
+ (func $func (export "func") (result i32)
+ ;; This drop can be removed when we optimize using StackIR.
+ (drop
+ (call $import)
+ )
+ (unreachable)
+ )
+)