summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/DeNaN.cpp27
-rw-r--r--test/passes/denan.txt55
-rw-r--r--test/passes/denan.wast12
3 files changed, 86 insertions, 8 deletions
diff --git a/src/passes/DeNaN.cpp b/src/passes/DeNaN.cpp
index 8d0462718..8dadb90de 100644
--- a/src/passes/DeNaN.cpp
+++ b/src/passes/DeNaN.cpp
@@ -22,6 +22,7 @@
// differ on wasm's nondeterminism around NaNs.
//
+#include "ir/names.h"
#include "ir/properties.h"
#include "pass.h"
#include "wasm-builder.h"
@@ -31,6 +32,9 @@ namespace wasm {
struct DeNaN : public WalkerPass<
ControlFlowWalker<DeNaN, UnifiedExpressionVisitor<DeNaN>>> {
+
+ Name deNan32, deNan64;
+
void visitExpression(Expression* expr) {
// If the expression returns a floating-point value, ensure it is not a
// NaN. If we can do this at compile time, do it now, which is useful for
@@ -53,13 +57,13 @@ struct DeNaN : public WalkerPass<
if (c && c->value.isNaN()) {
replacement = builder.makeConst(float(0));
} else {
- replacement = builder.makeCall("deNan32", {expr}, Type::f32);
+ replacement = builder.makeCall(deNan32, {expr}, Type::f32);
}
} else if (expr->type == Type::f64) {
if (c && c->value.isNaN()) {
replacement = builder.makeConst(double(0));
} else {
- replacement = builder.makeCall("deNan64", {expr}, Type::f64);
+ replacement = builder.makeCall(deNan64, {expr}, Type::f64);
}
}
if (replacement) {
@@ -86,12 +90,12 @@ struct DeNaN : public WalkerPass<
fixes.push_back(builder.makeLocalSet(
i,
builder.makeCall(
- "deNan32", {builder.makeLocalGet(i, Type::f32)}, Type::f32)));
+ deNan32, {builder.makeLocalGet(i, Type::f32)}, Type::f32)));
} else if (func->getLocalType(i) == Type::f64) {
fixes.push_back(builder.makeLocalSet(
i,
builder.makeCall(
- "deNan64", {builder.makeLocalGet(i, Type::f64)}, Type::f64)));
+ deNan64, {builder.makeLocalGet(i, Type::f64)}, Type::f64)));
}
}
if (!fixes.empty()) {
@@ -105,8 +109,15 @@ struct DeNaN : public WalkerPass<
}
}
- void visitModule(Module* module) {
- // Add helper functions.
+ void doWalkModule(Module* module) {
+ // Pick names for the helper functions.
+ deNan32 = Names::getValidFunctionName(*module, "deNan32");
+ deNan64 = Names::getValidFunctionName(*module, "deNan64");
+
+ ControlFlowWalker<DeNaN, UnifiedExpressionVisitor<DeNaN>>::doWalkModule(
+ module);
+
+ // Add helper functions after the walk, so they are not instrumented.
Builder builder(*module);
auto add = [&](Name name, Type type, Literal literal, BinaryOp op) {
auto* func = new Function;
@@ -130,8 +141,8 @@ struct DeNaN : public WalkerPass<
builder.makeConst(literal));
module->addFunction(func);
};
- add("deNan32", Type::f32, Literal(float(0)), EqFloat32);
- add("deNan64", Type::f64, Literal(double(0)), EqFloat64);
+ add(deNan32, Type::f32, Literal(float(0)), EqFloat32);
+ add(deNan64, Type::f64, Literal(double(0)), EqFloat64);
}
};
diff --git a/test/passes/denan.txt b/test/passes/denan.txt
index 10794b03b..de592c7fd 100644
--- a/test/passes/denan.txt
+++ b/test/passes/denan.txt
@@ -155,3 +155,58 @@
)
)
)
+(module
+ (type $none_=>_none (func))
+ (type $f32_=>_f32 (func (param f32) (result f32)))
+ (type $f64_=>_f64 (func (param f64) (result f64)))
+ (func $deNan32
+ (nop)
+ )
+ (func $deNan64
+ (nop)
+ )
+ (func $foo32 (param $x f32) (result f32)
+ (local.set $x
+ (call $deNan32_0
+ (local.get $x)
+ )
+ )
+ (call $deNan32_0
+ (call $foo32
+ (local.get $x)
+ )
+ )
+ )
+ (func $foo64 (param $x f64) (result f64)
+ (local.set $x
+ (call $deNan64_0
+ (local.get $x)
+ )
+ )
+ (call $deNan64_0
+ (call $foo64
+ (local.get $x)
+ )
+ )
+ )
+ (func $deNan32_0 (param $0 f32) (result f32)
+ (if (result f32)
+ (f32.eq
+ (local.get $0)
+ (local.get $0)
+ )
+ (local.get $0)
+ (f32.const 0)
+ )
+ )
+ (func $deNan64_0 (param $0 f64) (result f64)
+ (if (result f64)
+ (f64.eq
+ (local.get $0)
+ (local.get $0)
+ )
+ (local.get $0)
+ (f64.const 0)
+ )
+ )
+)
diff --git a/test/passes/denan.wast b/test/passes/denan.wast
index 7ab0964b2..78405d3a4 100644
--- a/test/passes/denan.wast
+++ b/test/passes/denan.wast
@@ -35,3 +35,15 @@
(local.get $x)
(i32.const 1)))
)
+;; existing names should not be a problem
+(module
+ (func $deNan32)
+ (func $deNan64)
+ (func $foo32 (param $x f32) (result f32)
+ (call $foo32 (local.get $x))
+ )
+ (func $foo64 (param $x f64) (result f64)
+ (call $foo64 (local.get $x))
+ )
+
+)