summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-10-21 22:43:30 +0300
committerGitHub <noreply@github.com>2020-10-21 12:43:30 -0700
commita2fa37eb94fdd6896f4d90f22e34fbd5f028d742 (patch)
tree1c5a934bebac2668f38dd1c138b04834487d015c /src
parentdc5638879350e7186ea79aa5199606ad570fa0c3 (diff)
downloadbinaryen-a2fa37eb94fdd6896f4d90f22e34fbd5f028d742.tar.gz
binaryen-a2fa37eb94fdd6896f4d90f22e34fbd5f028d742.tar.bz2
binaryen-a2fa37eb94fdd6896f4d90f22e34fbd5f028d742.zip
Add float simplifications for absolute binary expressions (#3013)
Diffstat (limited to 'src')
-rw-r--r--src/ir/abstract.h5
-rw-r--r--src/passes/OptimizeInstructions.cpp49
2 files changed, 54 insertions, 0 deletions
diff --git a/src/ir/abstract.h b/src/ir/abstract.h
index 2bb764aeb..d1a7ec47d 100644
--- a/src/ir/abstract.h
+++ b/src/ir/abstract.h
@@ -27,6 +27,7 @@ namespace Abstract {
enum Op {
// Unary
+ Abs,
Neg,
// Binary
Add,
@@ -91,6 +92,8 @@ inline UnaryOp getUnary(Type type, Op op) {
}
case Type::f32: {
switch (op) {
+ case Abs:
+ return AbsFloat32;
case Neg:
return NegFloat32;
default:
@@ -100,6 +103,8 @@ inline UnaryOp getUnary(Type type, Op op) {
}
case Type::f64: {
switch (op) {
+ case Abs:
+ return AbsFloat64;
case Neg:
return NegFloat64;
default:
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 232faab7a..ad7cc8f8a 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -484,6 +484,25 @@ struct OptimizeInstructions
if (auto* ret = optimizeAddedConstants(binary)) {
return ret;
}
+ } else if (binary->op == MulFloat32 || binary->op == MulFloat64 ||
+ binary->op == DivFloat32 || binary->op == DivFloat64) {
+ if (binary->left->type == binary->right->type) {
+ if (auto* leftUnary = binary->left->dynCast<Unary>()) {
+ if (leftUnary->op ==
+ Abstract::getUnary(binary->type, Abstract::Abs)) {
+ if (auto* rightUnary = binary->right->dynCast<Unary>()) {
+ if (leftUnary->op == rightUnary->op) { // both are abs ops
+ // abs(x) * abs(y) ==> abs(x * y)
+ // abs(x) / abs(y) ==> abs(x / y)
+ binary->left = leftUnary->value;
+ binary->right = rightUnary->value;
+ leftUnary->value = binary;
+ return leftUnary;
+ }
+ }
+ }
+ }
+ }
}
// a bunch of operations on a constant right side can be simplified
if (auto* right = binary->right->dynCast<Const>()) {
@@ -684,6 +703,36 @@ struct OptimizeInstructions
unary->value = makeZeroExt(ext, bits);
return unary;
}
+ } else if (unary->op == AbsFloat32 || unary->op == AbsFloat64) {
+ // abs(-x) ==> abs(x)
+ if (auto* unaryInner = unary->value->dynCast<Unary>()) {
+ if (unaryInner->op ==
+ Abstract::getUnary(unaryInner->type, Abstract::Neg)) {
+ unary->value = unaryInner->value;
+ return unary;
+ }
+ }
+ // abs(x * x) ==> x * x
+ // abs(x / x) ==> x / x
+ if (auto* binary = unary->value->dynCast<Binary>()) {
+ if ((binary->op == Abstract::getBinary(binary->type, Abstract::Mul) ||
+ binary->op ==
+ Abstract::getBinary(binary->type, Abstract::DivS)) &&
+ ExpressionAnalyzer::equal(binary->left, binary->right)) {
+ return binary;
+ }
+ // abs(0 - x) ==> abs(x),
+ // only for fast math
+ if (getPassOptions().fastMath &&
+ binary->op == Abstract::getBinary(binary->type, Abstract::Sub)) {
+ if (auto* c = binary->left->dynCast<Const>()) {
+ if (c->value.isZero()) {
+ unary->value = binary->right;
+ return unary;
+ }
+ }
+ }
+ }
}
if (auto* ret = deduplicateUnary(unary)) {