Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- The --mod-asyncify-never-unwind and --mod-asyncify-always-and-only-unwind
passed were deleted. They only existed to support the lazy code loading
support in emscripten that was removed. (#7893)

v124
----

Expand Down
160 changes: 0 additions & 160 deletions src/passes/Asyncify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1885,164 +1885,4 @@ struct Asyncify : public Pass {

Pass* createAsyncifyPass() { return new Asyncify(); }

// Helper passes that can be run after Asyncify.

template<bool neverRewind, bool neverUnwind, bool importsAlwaysUnwind>
struct ModAsyncify
: public WalkerPass<LinearExecutionWalker<
ModAsyncify<neverRewind, neverUnwind, importsAlwaysUnwind>>> {
bool isFunctionParallel() override { return true; }

std::unique_ptr<Pass> create() override {
return std::make_unique<
ModAsyncify<neverRewind, neverUnwind, importsAlwaysUnwind>>();
}

void doWalkFunction(Function* func) {
// Find the asyncify state name.
auto* unwind = this->getModule()->getExport(ASYNCIFY_STOP_UNWIND);
auto* unwindFunc = this->getModule()->getFunction(
((unwind->kind == ExternalKind::Function)) ? *unwind->getInternalName()
: Name());
FindAll<GlobalSet> sets(unwindFunc->body);
assert(sets.list.size() == 1);
asyncifyStateName = sets.list[0]->name;
// Walk and optimize.
this->walk(func->body);
}

// Note that we don't just implement GlobalGet as we may know the value is
// *not* 0, 1, or 2, but not know the actual value. So what we can say depends
// on the comparison being done on it, and so we implement Binary and
// Select.

void visitBinary(Binary* curr) {
// Check if this is a comparison of the asyncify state to a specific
// constant, which we may know is impossible.
bool flip = false;
if (curr->op == NeInt32) {
flip = true;
} else if (curr->op != EqInt32) {
return;
}
auto* c = curr->right->dynCast<Const>();
if (!c) {
return;
}
auto* get = curr->left->dynCast<GlobalGet>();
if (!get || get->name != asyncifyStateName) {
return;
}
// This is a comparison of the state to a constant, check if we know the
// value.
int32_t value;
auto checkedValue = c->value.geti32();
if ((checkedValue == int(State::Unwinding) && neverUnwind) ||
(checkedValue == int(State::Rewinding) && neverRewind)) {
// We know the state is checked against an impossible value.
value = 0;
} else if (checkedValue == int(State::Unwinding) && this->unwinding) {
// We know we are in fact unwinding right now.
value = 1;
unsetUnwinding();
} else {
return;
}
if (flip) {
value = 1 - value;
}
Builder builder(*this->getModule());
this->replaceCurrent(builder.makeConst(int32_t(value)));
}

void visitSelect(Select* curr) {
auto* get = curr->condition->dynCast<GlobalGet>();
if (!get || get->name != asyncifyStateName) {
return;
}
// This is a comparison of the normal state, which means we are checking
// "if running normally, run this code, but if rewinding, ignore it". If
// we know we'll never rewind, we can optimize this.
if (neverRewind) {
Builder builder(*this->getModule());
curr->condition = builder.makeConst(int32_t(0));
}
}

void visitUnary(Unary* curr) {
if (curr->op != EqZInt32) {
return;
}
auto* get = curr->value->dynCast<GlobalGet>();
if (!get || get->name != asyncifyStateName) {
return;
}
// This is a comparison of the state to zero, which means we are checking
// "if running normally, run this code, but if rewinding, ignore it". If
// we know we'll never rewind, we can optimize this.
if (neverRewind) {
Builder builder(*this->getModule());
// The whole expression will be 1 because it is (i32.eqz (i32.const 0))
this->replaceCurrent(builder.makeConst(int32_t(1)));
}
}

void visitCall(Call* curr) {
unsetUnwinding();
if (!importsAlwaysUnwind) {
return;
}
auto* target = this->getModule()->getFunction(curr->target);
if (!target->imported()) {
return;
}
// This is an import that definitely unwinds. Await the next check of
// the state in this linear execution trace, which we can turn into a
// constant.
this->unwinding = true;
}

void visitCallIndirect(CallIndirect* curr) { unsetUnwinding(); }

static void doNoteNonLinear(
ModAsyncify<neverRewind, neverUnwind, importsAlwaysUnwind>* self,
Expression**) {
// When control flow branches, stop tracking an unwinding.
self->unsetUnwinding();
}

void visitGlobalSet(GlobalSet* set) {
// TODO: this could be more precise
unsetUnwinding();
}

private:
Name asyncifyStateName;

// Whether we just did a call to an import that indicates we are unwinding.
bool unwinding = false;

void unsetUnwinding() { this->unwinding = false; }
};

//
// Assume imports that may unwind will always unwind, and that rewinding never
// happens.
//

Pass* createModAsyncifyAlwaysOnlyUnwindPass() {
return new ModAsyncify<true, false, true>();
}

//
// Assume that we never unwind, but may still rewind.
//
struct ModAsyncifyNeverUnwind : public Pass {
void run(Module* module) override {}
};

Pass* createModAsyncifyNeverUnwindPass() {
return new ModAsyncify<false, true, false>();
}

} // namespace wasm
7 changes: 0 additions & 7 deletions src/passes/pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,6 @@ void PassRegistry::registerPasses() {
registerPass("minimize-rec-groups",
"Split types into minimal recursion groups",
createMinimizeRecGroupsPass);
registerPass("mod-asyncify-always-and-only-unwind",
"apply the assumption that asyncify imports always unwind, "
"and we never rewind",
createModAsyncifyAlwaysOnlyUnwindPass);
registerPass("mod-asyncify-never-unwind",
"apply the assumption that asyncify never unwinds",
createModAsyncifyNeverUnwindPass);
registerPass("monomorphize",
"creates specialized versions of functions",
createMonomorphizePass);
Expand Down
2 changes: 0 additions & 2 deletions src/passes/passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ Pass* createOptimizeForJSPass();
Pass* createOutliningPass();
#endif
Pass* createPickLoadSignsPass();
Pass* createModAsyncifyAlwaysOnlyUnwindPass();
Pass* createModAsyncifyNeverUnwindPass();
Pass* createLLVMNonTrappingFPToIntLoweringPass();
Pass* createPoppifyPass();
Pass* createPostEmscriptenPass();
Expand Down
7 changes: 0 additions & 7 deletions test/lit/help/wasm-metadce.test
Original file line number Diff line number Diff line change
Expand Up @@ -292,13 +292,6 @@
;; CHECK-NEXT: --minimize-rec-groups Split types into minimal
;; CHECK-NEXT: recursion groups
;; 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:
Expand Down
7 changes: 0 additions & 7 deletions test/lit/help/wasm-opt.test
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,6 @@
;; CHECK-NEXT: --minimize-rec-groups Split types into minimal
;; CHECK-NEXT: recursion groups
;; 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:
Expand Down
7 changes: 0 additions & 7 deletions test/lit/help/wasm2js.test
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,6 @@
;; CHECK-NEXT: --minimize-rec-groups Split types into minimal
;; CHECK-NEXT: recursion groups
;; 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:
Expand Down
Loading
Loading