diff options
author | Derek Schuff <dschuff@chromium.org> | 2017-07-21 08:46:23 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-21 08:46:23 -0700 |
commit | ab8dbae1d1a27e4de24fd9ee09d45785a414922d (patch) | |
tree | ac337117d973464a16d597fc7a5c29550a93a489 /src/ast/effects.h | |
parent | da680fdbcb7eaad1c692369c7c826fc02b00c877 (diff) | |
download | binaryen-ab8dbae1d1a27e4de24fd9ee09d45785a414922d.tar.gz binaryen-ab8dbae1d1a27e4de24fd9ee09d45785a414922d.tar.bz2 binaryen-ab8dbae1d1a27e4de24fd9ee09d45785a414922d.zip |
Optimizer support for atomic instructions (#1094)
* Teach EffectAnalyzer not to reorder atomics wrt other memory operations.
* Teach EffectAnalyzer not to reorder host operations with memory operations
* Teach various passes about the operands of AtomicRMW and AtomicCmpxchg
* Factor out some functions in DeadCodeElimination and MergeBlocks
Diffstat (limited to 'src/ast/effects.h')
-rw-r--r-- | src/ast/effects.h | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/ast/effects.h b/src/ast/effects.h index 6e4bb617e..5392c0e50 100644 --- a/src/ast/effects.h +++ b/src/ast/effects.h @@ -53,12 +53,14 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { // (so a trap may occur later or earlier, if it is // going to occur anyhow), but we can't remove them, // they count as side effects + bool isAtomic = false; // An atomic load/store/RMW/Cmpxchg or an operator that + // has a defined ordering wrt atomics (e.g. grow_memory) bool accessesLocal() { return localsRead.size() + localsWritten.size() > 0; } bool accessesGlobal() { return globalsRead.size() + globalsWritten.size() > 0; } bool accessesMemory() { return calls || readsMemory || writesMemory; } - bool hasSideEffects() { return calls || localsWritten.size() > 0 || writesMemory || branches || globalsWritten.size() > 0 || implicitTrap; } - bool hasAnything() { return branches || calls || accessesLocal() || readsMemory || writesMemory || accessesGlobal() || implicitTrap; } + bool hasSideEffects() { return calls || localsWritten.size() > 0 || writesMemory || branches || globalsWritten.size() > 0 || implicitTrap || isAtomic; } + bool hasAnything() { return branches || calls || accessesLocal() || readsMemory || writesMemory || accessesGlobal() || implicitTrap || isAtomic; } // checks if these effects would invalidate another set (e.g., if we write, we invalidate someone that reads, they can't be moved past us) bool invalidates(EffectAnalyzer& other) { @@ -67,6 +69,12 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { || (accessesMemory() && (other.writesMemory || other.calls))) { return true; } + // All atomics are sequentially consistent for now, and ordered wrt other + // memory references. + if ((isAtomic && other.accessesMemory()) || + (other.isAtomic && accessesMemory())) { + return true; + } for (auto local : localsWritten) { if (other.localsWritten.count(local) || other.localsRead.count(local)) { return true; @@ -176,10 +184,24 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { } void visitLoad(Load *curr) { readsMemory = true; + isAtomic |= curr->isAtomic; if (!ignoreImplicitTraps) implicitTrap = true; } void visitStore(Store *curr) { writesMemory = true; + isAtomic |= curr->isAtomic; + if (!ignoreImplicitTraps) implicitTrap = true; + } + void visitAtomicRMW(AtomicRMW* curr) { + readsMemory = true; + writesMemory = true; + isAtomic = true; + if (!ignoreImplicitTraps) implicitTrap = true; + } + void visitAtomicCmpxchg(AtomicCmpxchg* curr) { + readsMemory = true; + writesMemory = true; + isAtomic = true; if (!ignoreImplicitTraps) implicitTrap = true; } void visitUnary(Unary *curr) { @@ -219,11 +241,16 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer> { } } void visitReturn(Return *curr) { branches = true; } - void visitHost(Host *curr) { calls = true; } + void visitHost(Host *curr) { + calls = true; + // grow_memory modifies the set of valid addresses, and thus can be modeled as modifying memory + writesMemory = true; + // Atomics are also sequentially consistent with grow_memory. + isAtomic = true; + } void visitUnreachable(Unreachable *curr) { branches = true; } }; } // namespace wasm #endif // wasm_ast_effects_h - |