diff options
author | Max Graey <maxgraey@gmail.com> | 2020-10-21 22:43:30 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-21 12:43:30 -0700 |
commit | a2fa37eb94fdd6896f4d90f22e34fbd5f028d742 (patch) | |
tree | 1c5a934bebac2668f38dd1c138b04834487d015c /src | |
parent | dc5638879350e7186ea79aa5199606ad570fa0c3 (diff) | |
download | binaryen-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.h | 5 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 49 |
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)) { |