summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp')
-rw-r--r--Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp b/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp
new file mode 100644
index 000000000..d8e43b4ee
--- /dev/null
+++ b/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "B3ReduceDoubleToFloat.h"
+
+#if ENABLE(B3_JIT)
+
+#include "B3BasicBlock.h"
+#include "B3PhaseScope.h"
+#include "B3ValueInlines.h"
+
+namespace JSC { namespace B3 {
+
+namespace {
+void attemptSimplification(Value* candidate)
+{
+ switch (candidate->opcode()) {
+ case Add:
+ case Sub:
+ case Mul:
+ case Div:
+ if (candidate->child(0)->opcode() == FloatToDouble && candidate->child(1)->opcode() == FloatToDouble) {
+ candidate->child(0) = candidate->child(0)->child(0);
+ candidate->child(1) = candidate->child(1)->child(0);
+ candidate->setType(Float);
+ }
+ break;
+ case Abs:
+ case Ceil:
+ case Floor:
+ case Sqrt:
+ if (candidate->child(0)->opcode() == FloatToDouble) {
+ candidate->child(0) = candidate->child(0)->child(0);
+ candidate->setType(Float);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+} // namespace
+
+// The goal of this phase is to transform Double operations
+// into float if the Double result is never used as Double.
+//
+// In C, that would be something like:
+// float add(float a, float b) {
+// return (double)a + (double)b;
+// }
+//
+// Such operation arise in JS because there are is no Float type
+// and float operations are generated by adding double-to-float rounding.
+//
+// The operations can be done entirely without Double conversion.
+// Using float in place remove the useless conversion, and the float
+// ops is sometime massively cheaper (SQRT for example).
+//
+// If the Double value is used as Double, we do not do the conversion.
+// It is cheaper to do a conversion than repeat any floating-point operation.
+void reduceDoubleToFloat(Procedure& procedure)
+{
+ // FIXME: We should tune this phase for performance and make it part of ReduceStrength.
+ // ReduceStrength can eliminate nodes that prevents us from simplifying operations.
+ PhaseScope phaseScope(procedure, "reduceDoubleToFloat");
+
+ HashSet<Value*> candidates;
+
+ // First, we find any value that is converted to float
+ // and only used as float.
+ // We also simplify comparisons since that's always safe and we
+ // don't want them to appear in the next loop.
+ for (BasicBlock* block : procedure) {
+ for (Value* value : *block) {
+ value->performSubstitution();
+
+ switch (value->opcode()) {
+ case DoubleToFloat:
+ candidates.add(value->child(0));
+ break;
+ case Equal:
+ case NotEqual:
+ case LessThan:
+ case GreaterThan:
+ case LessEqual:
+ case GreaterEqual:
+ case EqualOrUnordered:
+ if (value->child(0)->opcode() == FloatToDouble && value->child(1)->opcode() == FloatToDouble) {
+ value->child(0) = value->child(0)->child(0);
+ value->child(1) = value->child(1)->child(0);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ for (BasicBlock* block : procedure) {
+ for (Value* value : *block) {
+ if (value->opcode() == DoubleToFloat)
+ continue;
+
+ for (Value* child : value->children()) {
+ if (child->type() == Double)
+ candidates.remove(child);
+ }
+ }
+ }
+
+ if (candidates.isEmpty())
+ return;
+
+ // Second, we go over the candidates and attempt to simplify them.
+ // This leaves the graph in an invalid state where Float Values are
+ // used by DoubleToFloat Values. This is only temporary.
+ for (Value* candidate : candidates)
+ attemptSimplification(candidate);
+
+ // Finally, remove the DoubleToFloat made useless by the simplifications.
+ for (BasicBlock* block : procedure) {
+ for (Value* value : *block) {
+ if (value->opcode() == DoubleToFloat && value->child(0)->type() == Float)
+ value->replaceWithIdentity(value->child(0));
+ }
+ }
+
+ // We do not clean all the useless nodes and conversions. ReduceStrength does that better.
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+