diff options
author | Alon Zakai <azakai@google.com> | 2019-05-17 19:12:01 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-17 19:12:01 -0700 |
commit | 677808afb18a059d3dadcf2be7bd8daade5b77f9 (patch) | |
tree | a047c7c6070c47924587ad7c23aa6d53da23168d | |
parent | d6a6188493031c5f6bbe2ca49860c9d9df962752 (diff) | |
download | binaryen-677808afb18a059d3dadcf2be7bd8daade5b77f9.tar.gz binaryen-677808afb18a059d3dadcf2be7bd8daade5b77f9.tar.bz2 binaryen-677808afb18a059d3dadcf2be7bd8daade5b77f9.zip |
Fix AvoidReinterprets on reinterpreted loads of fewer than the full size (#2123)
* fix
* fix style
-rw-r--r-- | src/passes/AvoidReinterprets.cpp | 16 | ||||
-rw-r--r-- | test/passes/avoid-reinterprets.txt | 15 | ||||
-rw-r--r-- | test/passes/avoid-reinterprets.wast | 14 |
3 files changed, 42 insertions, 3 deletions
diff --git a/src/passes/AvoidReinterprets.cpp b/src/passes/AvoidReinterprets.cpp index 823de53ba..d9b93b188 100644 --- a/src/passes/AvoidReinterprets.cpp +++ b/src/passes/AvoidReinterprets.cpp @@ -27,6 +27,14 @@ namespace wasm { +static bool canReplaceWithReinterpret(Load* load) { + // We can replace a full-size load with a valid pointer with + // a reinterpret of the same address. A partial load would see + // more bytes and possibly invalid data, and an unreachable + // pointer is just not interesting to handle. + return load->type != unreachable && load->bytes == getTypeSize(load->type); +} + static Load* getSingleLoad(LocalGraph* localGraph, GetLocal* get) { std::set<GetLocal*> seen; seen.insert(get); @@ -104,7 +112,7 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> { for (auto& pair : infos) { auto* load = pair.first; auto& info = pair.second; - if (info.reinterpreted && load->type != unreachable) { + if (info.reinterpreted && canReplaceWithReinterpret(load)) { // We should use another load here, to avoid reinterprets. info.ptrLocal = Builder::addVar(func, i32); info.reinterpretedLocal = @@ -131,8 +139,10 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> { if (isReinterpret(curr)) { auto* value = Properties::getFallthrough(curr->value); if (auto* load = value->dynCast<Load>()) { - // A reinterpret of a load - flip it right here. - replaceCurrent(makeReinterpretedLoad(load, load->ptr)); + // A reinterpret of a load - flip it right here if we can. + if (canReplaceWithReinterpret(load)) { + replaceCurrent(makeReinterpretedLoad(load, load->ptr)); + } } else if (auto* get = value->dynCast<GetLocal>()) { if (auto* load = getSingleLoad(localGraph, get)) { auto iter = infos.find(load); diff --git a/test/passes/avoid-reinterprets.txt b/test/passes/avoid-reinterprets.txt index f78c6443b..294e1506f 100644 --- a/test/passes/avoid-reinterprets.txt +++ b/test/passes/avoid-reinterprets.txt @@ -1,5 +1,6 @@ (module (type $0 (func)) + (type $1 (func (result f32))) (memory $0 1) (func $simple (; 0 ;) (type $0) (drop @@ -148,4 +149,18 @@ (local.get $3) ) ) + (func $partial1 (; 6 ;) (type $1) (result f32) + (f32.reinterpret_i32 + (i32.load16_u + (i32.const 3) + ) + ) + ) + (func $partial2 (; 7 ;) (type $1) (result f32) + (f32.reinterpret_i32 + (i32.load8_u + (i32.const 3) + ) + ) + ) ) diff --git a/test/passes/avoid-reinterprets.wast b/test/passes/avoid-reinterprets.wast index 1499f8356..296b16df3 100644 --- a/test/passes/avoid-reinterprets.wast +++ b/test/passes/avoid-reinterprets.wast @@ -35,4 +35,18 @@ (local.set $y (local.get $x)) (drop (f32.reinterpret_i32 (local.get $y))) ) + (func $partial1 (result f32) + (f32.reinterpret_i32 + (i32.load16_u + (i32.const 3) + ) + ) + ) + (func $partial2 (result f32) + (f32.reinterpret_i32 + (i32.load8_u + (i32.const 3) + ) + ) + ) ) |