summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/AvoidReinterprets.cpp16
-rw-r--r--test/passes/avoid-reinterprets.txt15
-rw-r--r--test/passes/avoid-reinterprets.wast14
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)
+ )
+ )
+ )
)