Skip to content

Commit aaf1dac

Browse files
authored
Fix opt/shrink levels when running the optimizer multiple times, Part 2 (#5787)
This is a followup to #5333 . That fixed the selection of which passes to run, but forgot to also fix the global state of the current optimize/shrink levels. This PR fixes that. As a result, running -O3 -Oz will now work as expected: the first -O3 will run the right passes (as #5333 fixed) and while running them, the global optimize/shrinkLevels will be -O3 (and not -Oz), which this PR fixes. A specific result of this is that -O3 -Oz used to inline less, since the invocation of inlining during -O3 thought we were optimizing for size. The new test verifies that we do fully inline in the first -O3 now.
1 parent fd9d04c commit aaf1dac

File tree

6 files changed

+92
-49
lines changed

6 files changed

+92
-49
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ full changeset diff at the end of each section.
1515
Current Trunk
1616
-------------
1717

18+
- Fix a bug where e.g. -O3 -Oz ran the -O3 with the opt levels of -Oz, which
19+
could inhibit inlining, for example. While this is a bugfix, it affects how
20+
commandline options are interpreted, so if you depended on the old behavior
21+
this may be a breaking change. That is, the old behavior made -O3 -Oz run the
22+
first -O3 with -Oz's opt levels, and the new behavior is to run -O3 with the
23+
proper (-O3) opt levels. This is a followup to #5333 from a previous release.
24+
(#5787)
25+
1826
v113
1927
----
2028

src/pass.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,6 @@ struct PassRunner {
388388
// Whether this pass runner has run. A pass runner should only be run once.
389389
bool ran = false;
390390

391-
// Passes in |options.passesToSkip| that we have seen and skipped.
392-
std::unordered_set<std::string> skippedPasses;
393-
394391
void runPass(Pass* pass);
395392
void runPassOnFunction(Pass* pass, Function* func);
396393

src/passes/pass.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,6 @@ void PassRunner::run() {
698698
assert(!ran);
699699
ran = true;
700700

701-
// As we run passes, we'll notice which we skip.
702-
skippedPasses.clear();
703-
704701
static const int passDebug = getPassDebug();
705702
// Emit logging information when asked for. At passDebug level 1+ we log
706703
// the main passes, while in 2 we also log nested ones. Note that for
@@ -821,20 +818,6 @@ void PassRunner::run() {
821818
}
822819
flush();
823820
}
824-
825-
if (!isNested) {
826-
// All the passes the user requested to skip should have been seen, and
827-
// skipped. If not, the user may have had a typo in the name of a pass to
828-
// skip, and we will warn. (We don't do this in a nested runner because
829-
// those are used for various internal tasks inside passes, which would lead
830-
// to many spurious warnings.)
831-
for (auto pass : options.passesToSkip) {
832-
if (!skippedPasses.count(pass)) {
833-
std::cerr << "warning: --" << pass << " was requested to be skipped, "
834-
<< "but it was not found in the passes that were run.\n";
835-
}
836-
}
837-
}
838821
}
839822

840823
void PassRunner::runOnFunction(Function* func) {
@@ -956,7 +939,6 @@ void PassRunner::runPass(Pass* pass) {
956939
assert(!pass->isFunctionParallel());
957940

958941
if (options.passesToSkip.count(pass->name)) {
959-
skippedPasses.insert(pass->name);
960942
return;
961943
}
962944

@@ -980,7 +962,6 @@ void PassRunner::runPassOnFunction(Pass* pass, Function* func) {
980962
assert(pass->isFunctionParallel());
981963

982964
if (options.passesToSkip.count(pass->name)) {
983-
skippedPasses.insert(pass->name);
984965
return;
985966
}
986967

src/tools/optimization-options.h

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -328,32 +328,52 @@ struct OptimizationOptions : public ToolOptions {
328328
bool runningPasses() { return passes.size() > 0; }
329329

330330
void runPasses(Module& wasm) {
331-
PassRunner passRunner(&wasm, passOptions);
332-
if (debug) {
333-
passRunner.setDebug(true);
334-
}
335-
for (auto& pass : passes) {
336-
// We apply the pass's intended opt and shrink levels, if any.
337-
auto oldOptimizeLevel = passRunner.options.optimizeLevel;
338-
auto oldShrinkLevel = passRunner.options.shrinkLevel;
339-
if (pass.optimizeLevel) {
340-
passRunner.options.optimizeLevel = *pass.optimizeLevel;
331+
std::unique_ptr<PassRunner> passRunner;
332+
333+
// Flush anything in the current pass runner, and then reset it to a fresh
334+
// state so it is ready for new things.
335+
auto flushAndReset = [&]() {
336+
if (passRunner) {
337+
passRunner->run();
341338
}
342-
if (pass.shrinkLevel) {
343-
passRunner.options.shrinkLevel = *pass.shrinkLevel;
339+
passRunner = std::make_unique<PassRunner>(&wasm, passOptions);
340+
if (debug) {
341+
passRunner->setDebug(true);
344342
}
343+
};
345344

345+
flushAndReset();
346+
347+
for (auto& pass : passes) {
346348
if (pass.name == DEFAULT_OPT_PASSES) {
347-
passRunner.addDefaultOptimizationPasses();
349+
// This is something like -O3 or -Oz. We must run this now, in order to
350+
// set the proper opt and shrink levels. To do that, first reset the
351+
// runner so that anything already queued is run (since we can only run
352+
// after those things).
353+
flushAndReset();
354+
355+
// -O3/-Oz etc. always set their own optimize/shrinkLevels.
356+
assert(pass.optimizeLevel);
357+
assert(pass.shrinkLevel);
358+
passRunner->options.optimizeLevel = *pass.optimizeLevel;
359+
passRunner->options.shrinkLevel = *pass.shrinkLevel;
360+
361+
// Run our optimizations now, and reset the runner so that the default
362+
// pass options are used later (and not the temporary optimize/
363+
// shrinkLevels we just set).
364+
passRunner->addDefaultOptimizationPasses();
365+
flushAndReset();
348366
} else {
349-
passRunner.add(pass.name);
350-
}
367+
// This is a normal pass. Add it to the queue for execution.
368+
passRunner->add(pass.name);
351369

352-
// Revert back to the default levels, if we changed them.
353-
passRunner.options.optimizeLevel = oldOptimizeLevel;
354-
passRunner.options.shrinkLevel = oldShrinkLevel;
370+
// Normal passes do not set their own optimize/shrinkLevels.
371+
assert(!pass.optimizeLevel);
372+
assert(!pass.shrinkLevel);
373+
}
355374
}
356-
passRunner.run();
375+
376+
flushAndReset();
357377
}
358378
};
359379

test/lit/passes/O3_Oz.wast

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt -O3 -Oz -S -o - | filecheck %s
4+
5+
(module
6+
(func $inline.me (param $x i32) (result i32)
7+
(i32.add
8+
(local.get $x)
9+
(i32.const 2)
10+
)
11+
)
12+
13+
(func "export" (param $x i32) (result i32)
14+
;; $inline.me is called twice, so we do not always inline it like called-
15+
;; once functions are. -Oz is too cautious to inline such things that may
16+
;; end up increasing total code size, but we are running -O3 -Oz here and so
17+
;; the first -O3 will inline there. That is, this test verifies that the
18+
;; later -Oz does not affect the earlier -O3 (which it could, if -Oz set
19+
;; global state that -O3 then reads to see the optimization and shrink
20+
;; levels).
21+
(i32.add
22+
(call $inline.me
23+
(local.get $x)
24+
)
25+
(call $inline.me
26+
(local.get $x)
27+
)
28+
)
29+
)
30+
)
31+
;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32)))
32+
33+
;; CHECK: (export "export" (func $1))
34+
35+
;; CHECK: (func $1 (; has Stack IR ;) (param $0 i32) (result i32)
36+
;; CHECK-NEXT: (i32.add
37+
;; CHECK-NEXT: (local.tee $0
38+
;; CHECK-NEXT: (i32.add
39+
;; CHECK-NEXT: (local.get $0)
40+
;; CHECK-NEXT: (i32.const 2)
41+
;; CHECK-NEXT: )
42+
;; CHECK-NEXT: )
43+
;; CHECK-NEXT: (local.get $0)
44+
;; CHECK-NEXT: )
45+
;; CHECK-NEXT: )

test/lit/passes/skip-missing.wast

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)