summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 7f0b28574..9024d0cb6 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -3597,6 +3597,40 @@ private:
}
}
}
+ {
+ // x != NaN ==> 1
+ // x <=> NaN ==> 0
+ // x op NaN' ==> NaN', iff `op` != `copysign` and `x` != C
+ Const* c;
+ Binary* bin;
+ Expression* x;
+ if (matches(curr, binary(&bin, pure(&x), fval(&c))) &&
+ std::isnan(c->value.getFloat()) &&
+ bin->op != getBinary(x->type, CopySign)) {
+ if (bin->isRelational()) {
+ // reuse "c" (nan) constant
+ c->type = Type::i32;
+ if (bin->op == getBinary(x->type, Ne)) {
+ // x != NaN ==> 1
+ c->value = Literal::makeOne(Type::i32);
+ } else {
+ // x == NaN,
+ // x > NaN,
+ // x <= NaN
+ // x .. NaN ==> 0
+ c->value = Literal::makeZero(Type::i32);
+ }
+ return c;
+ }
+ // propagate NaN of RHS but canonicalize it
+ if (c->type == Type::f32) {
+ c->value = standardizeNaN(c->value.getf32());
+ } else {
+ c->value = standardizeNaN(c->value.getf64());
+ }
+ return c;
+ }
+ }
return nullptr;
}