[turbofan] Add operators for float32 support.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Mon, 22 Sep 2014 11:42:10 +0000 (11:42 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Mon, 22 Sep 2014 11:42:10 +0000 (11:42 +0000)
This adds Float32Constant, ChangeFloat32ToFloat64 and
TruncateFloat64ToFloat32 operators.

TEST=compiler-unittests
BUG=v8:3589
LOG=n
R=titzer@chromium.org

Review URL: https://codereview.chromium.org/594493002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24112 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

17 files changed:
src/compiler/common-operator-unittest.cc
src/compiler/common-operator.cc
src/compiler/common-operator.h
src/compiler/graph-unittest.cc
src/compiler/graph-unittest.h
src/compiler/machine-operator-reducer-unittest.cc
src/compiler/machine-operator-reducer.cc
src/compiler/machine-operator-reducer.h
src/compiler/machine-operator-unittest.cc
src/compiler/machine-operator.cc
src/compiler/machine-operator.h
src/compiler/node-matchers.h
src/compiler/opcodes.h
src/compiler/typer.cc
src/conversions-inl.h
src/conversions.h
src/runtime.cc

index 128f8ddede541c214f4dfd3779f19c5abf445293..5001770ddf1347c772e9bc7d2b44424f69f24fd7 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "src/compiler/common-operator.h"
 
+#include <limits>
+
 #include "src/compiler/operator-properties-inl.h"
 #include "src/test/test-utils.h"
 
@@ -132,9 +134,26 @@ class CommonOperatorTest : public TestWithZone {
 
 const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
 
+const float kFloat32Values[] = {
+    std::numeric_limits<float>::min(), -1.0f, -0.0f, 0.0f, 1.0f,
+    std::numeric_limits<float>::max()};
+
 }  // namespace
 
 
+TEST_F(CommonOperatorTest, Float32Constant) {
+  TRACED_FOREACH(float, value, kFloat32Values) {
+    const Operator* op = common()->Float32Constant(value);
+    EXPECT_FLOAT_EQ(value, OpParameter<float>(op));
+    EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
+    EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
+  }
+}
+
+
 TEST_F(CommonOperatorTest, ValueEffect) {
   TRACED_FOREACH(int, arguments, kArguments) {
     const Operator* op = common()->ValueEffect(arguments);
index 903484306305abdb4fc010a67a413a48c003cc99..19792bd1da5d2db0d058143668ca4c108429d8c3 100644 (file)
@@ -137,6 +137,13 @@ const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
 }
 
 
+const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
+  return new (zone())
+      Operator1<float>(IrOpcode::kFloat32Constant, Operator::kPure, 0, 1,
+                       "Float32Constant", value);
+}
+
+
 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
   return new (zone())
       Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
index 52c0af29f913439cfcf4c460776232a1992d76b1..a3659adfc2a05cc56231037a54daab292d1288be 100644 (file)
@@ -84,6 +84,7 @@ class CommonOperatorBuilder FINAL {
 
   const Operator* Int32Constant(int32_t);
   const Operator* Int64Constant(int64_t);
+  const Operator* Float32Constant(volatile float);
   const Operator* Float64Constant(volatile double);
   const Operator* ExternalConstant(const ExternalReference&);
   const Operator* NumberConstant(volatile double);
index f7faa6de29da447790f61dda238ffb0b688a1e8d..58adb112c731600fd9b29aa93d2540a3ab8f4b0b 100644 (file)
@@ -44,7 +44,12 @@ Node* GraphTest::Parameter(int32_t index) {
 }
 
 
-Node* GraphTest::Float64Constant(double value) {
+Node* GraphTest::Float32Constant(volatile float value) {
+  return graph()->NewNode(common()->Float32Constant(value));
+}
+
+
+Node* GraphTest::Float64Constant(volatile double value) {
   return graph()->NewNode(common()->Float64Constant(value));
 }
 
@@ -59,7 +64,7 @@ Node* GraphTest::Int64Constant(int64_t value) {
 }
 
 
-Node* GraphTest::NumberConstant(double value) {
+Node* GraphTest::NumberConstant(volatile double value) {
   return graph()->NewNode(common()->NumberConstant(value));
 }
 
@@ -664,6 +669,12 @@ Matcher<Node*> IsInt64Constant(const Matcher<int64_t>& value_matcher) {
 }
 
 
+Matcher<Node*> IsFloat32Constant(const Matcher<float>& value_matcher) {
+  return MakeMatcher(
+      new IsConstantMatcher<float>(IrOpcode::kFloat32Constant, value_matcher));
+}
+
+
 Matcher<Node*> IsFloat64Constant(const Matcher<double>& value_matcher) {
   return MakeMatcher(
       new IsConstantMatcher<double>(IrOpcode::kFloat64Constant, value_matcher));
index 42e4dd9bdc5eb18f0ca397004dc70ccfe2165fbb..3cda9b7b190a32ce1767dfae596ac97f937d6fa8 100644 (file)
@@ -31,10 +31,11 @@ class GraphTest : public TestWithContext, public TestWithZone {
 
  protected:
   Node* Parameter(int32_t index);
-  Node* Float64Constant(double value);
+  Node* Float32Constant(volatile float value);
+  Node* Float64Constant(volatile double value);
   Node* Int32Constant(int32_t value);
   Node* Int64Constant(int64_t value);
-  Node* NumberConstant(double value);
+  Node* NumberConstant(volatile double value);
   Node* HeapConstant(const Unique<HeapObject>& value);
   Node* FalseConstant();
   Node* TrueConstant();
@@ -65,6 +66,7 @@ Matcher<Node*> IsExternalConstant(
     const Matcher<ExternalReference>& value_matcher);
 Matcher<Node*> IsHeapConstant(
     const Matcher<Unique<HeapObject> >& value_matcher);
+Matcher<Node*> IsFloat32Constant(const Matcher<float>& value_matcher);
 Matcher<Node*> IsFloat64Constant(const Matcher<double>& value_matcher);
 Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher);
 Matcher<Node*> IsInt64Constant(const Matcher<int64_t>& value_matcher);
index 6b27b12670432e4f9a75ae358166d7a3637d4ab7..cad5112978a732d14ea15473040d1b3f06dbb518 100644 (file)
@@ -46,6 +46,29 @@ class MachineOperatorReducerTestWithParam
 
 namespace {
 
+static const float kFloat32Values[] = {
+    -V8_INFINITY,  -2.70497e+38f, -1.4698e+37f,  -1.22813e+35f, -1.20555e+35f,
+    -1.34584e+34f, -1.0079e+32f,  -6.49364e+26f, -3.06077e+25f, -1.46821e+25f,
+    -1.17658e+23f, -1.9617e+22f,  -2.7357e+20f,  -1.48708e+13f, -1.89633e+12f,
+    -4.66622e+11f, -2.22581e+11f, -1.45381e+10f, -1.3956e+09f,  -1.32951e+09f,
+    -1.30721e+09f, -1.19756e+09f, -9.26822e+08f, -6.35647e+08f, -4.00037e+08f,
+    -1.81227e+08f, -5.09256e+07f, -964300.0f,    -192446.0f,    -28455.0f,
+    -27194.0f,     -26401.0f,     -20575.0f,     -17069.0f,     -9167.0f,
+    -960.178f,     -113.0f,       -62.0f,        -15.0f,        -7.0f,
+    -0.0256635f,   -4.60374e-07f, -3.63759e-10f, -4.30175e-14f, -5.27385e-15f,
+    -1.48084e-15f, -1.05755e-19f, -3.2995e-21f,  -1.67354e-23f, -1.11885e-23f,
+    -1.78506e-30f, -5.07594e-31f, -3.65799e-31f, -1.43718e-34f, -1.27126e-38f,
+    -0.0f,         0.0f,          1.17549e-38f,  1.56657e-37f,  4.08512e-29f,
+    3.31357e-28f,  6.25073e-22f,  4.1723e-13f,   1.44343e-09f,  5.27004e-08f,
+    9.48298e-08f,  5.57888e-07f,  4.89988e-05f,  0.244326f,     12.4895f,
+    19.0f,         47.0f,         106.0f,        538.324f,      564.536f,
+    819.124f,      7048.0f,       12611.0f,      19878.0f,      20309.0f,
+    797056.0f,     1.77219e+09f,  1.51116e+11f,  4.18193e+13f,  3.59167e+16f,
+    3.38211e+19f,  2.67488e+20f,  1.78831e+21f,  9.20914e+21f,  8.35654e+23f,
+    1.4495e+24f,   5.94015e+25f,  4.43608e+30f,  2.44502e+33f,  2.61152e+33f,
+    1.38178e+37f,  1.71306e+37f,  3.31899e+38f,  3.40282e+38f,  V8_INFINITY};
+
+
 static const double kFloat64Values[] = {
     -V8_INFINITY,  -4.23878e+275, -5.82632e+265, -6.60355e+220, -6.26172e+212,
     -2.56222e+211, -4.82408e+201, -1.84106e+157, -1.63662e+127, -1.55772e+100,
@@ -205,6 +228,20 @@ INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest,
                         ::testing::ValuesIn(kUnaryOperators));
 
 
+// -----------------------------------------------------------------------------
+// ChangeFloat64ToFloat32
+
+
+TEST_F(MachineOperatorReducerTest, ChangeFloat64ToFloat32WithConstant) {
+  TRACED_FOREACH(float, x, kFloat32Values) {
+    Reduction reduction = Reduce(graph()->NewNode(
+        machine()->ChangeFloat32ToFloat64(), Float32Constant(x)));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_THAT(reduction.replacement(), IsFloat64Constant(x));
+  }
+}
+
+
 // -----------------------------------------------------------------------------
 // ChangeFloat64ToInt32
 
@@ -314,6 +351,31 @@ TEST_F(MachineOperatorReducerTest, ChangeUint32ToUint64WithConstant) {
 }
 
 
+// -----------------------------------------------------------------------------
+// TruncateFloat64ToFloat32
+
+
+TEST_F(MachineOperatorReducerTest,
+       TruncateFloat64ToFloat32WithChangeFloat32ToFloat64) {
+  Node* value = Parameter(0);
+  Reduction reduction = Reduce(graph()->NewNode(
+      machine()->TruncateFloat64ToFloat32(),
+      graph()->NewNode(machine()->ChangeFloat32ToFloat64(), value)));
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_EQ(value, reduction.replacement());
+}
+
+
+TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) {
+  TRACED_FOREACH(double, x, kFloat64Values) {
+    Reduction reduction = Reduce(graph()->NewNode(
+        machine()->TruncateFloat64ToFloat32(), Float64Constant(x)));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_THAT(reduction.replacement(), IsFloat32Constant(DoubleToFloat32(x)));
+  }
+}
+
+
 // -----------------------------------------------------------------------------
 // TruncateFloat64ToInt32
 
index 936deca8b636deb3e1121cfb9cb360c6a23fc842..53ee81075e960875e0a9d94de8dc0247744e732d 100644 (file)
@@ -21,6 +21,11 @@ MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph)
 MachineOperatorReducer::~MachineOperatorReducer() {}
 
 
+Node* MachineOperatorReducer::Float32Constant(volatile float value) {
+  return graph()->NewNode(common()->Float32Constant(value));
+}
+
+
 Node* MachineOperatorReducer::Float64Constant(volatile double value) {
   return jsgraph()->Float64Constant(value);
 }
@@ -383,6 +388,11 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
       }
       break;
     }
+    case IrOpcode::kChangeFloat32ToFloat64: {
+      Float32Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat64(m.Value());
+      break;
+    }
     case IrOpcode::kChangeFloat64ToInt32: {
       Float64Matcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceInt32(FastD2I(m.Value()));
@@ -427,6 +437,12 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
       if (m.IsChangeInt32ToInt64()) return Replace(m.node()->InputAt(0));
       break;
     }
+    case IrOpcode::kTruncateFloat64ToFloat32: {
+      Float64Matcher m(node->InputAt(0));
+      if (m.HasValue()) return ReplaceFloat32(DoubleToFloat32(m.Value()));
+      if (m.IsChangeFloat32ToFloat64()) return Replace(m.node()->InputAt(0));
+      break;
+    }
     // TODO(turbofan): strength-reduce and fold floating point operations.
     default:
       break;
index 57fcdee8e06a19177a55fd03af6e4833959efc7b..c79ceae204b791af36f9bbfd6a6735f8f2b68744 100644 (file)
@@ -27,11 +27,15 @@ class MachineOperatorReducer FINAL : public Reducer {
   virtual Reduction Reduce(Node* node) OVERRIDE;
 
  private:
+  Node* Float32Constant(volatile float value);
   Node* Float64Constant(volatile double value);
   Node* Int32Constant(int32_t value);
   Node* Int64Constant(int64_t value);
 
   Reduction ReplaceBool(bool value) { return ReplaceInt32(value ? 1 : 0); }
+  Reduction ReplaceFloat32(volatile float value) {
+    return Replace(Float32Constant(value));
+  }
   Reduction ReplaceFloat64(volatile double value) {
     return Replace(Float64Constant(value));
   }
index 5b34000b58610165467e62c204fb3a6224f84565..6aaf06f7510d4c8ef280596deb4c79b47409ef64 100644 (file)
@@ -187,32 +187,33 @@ const PureOperator kPureOperators[] = {
     &MachineOperatorBuilder::Name, IrOpcode::k##Name, input_count, \
         output_count                                               \
   }
-    PURE(Word32And, 2, 1),             PURE(Word32Or, 2, 1),
-    PURE(Word32Xor, 2, 1),             PURE(Word32Shl, 2, 1),
-    PURE(Word32Shr, 2, 1),             PURE(Word32Sar, 2, 1),
-    PURE(Word32Ror, 2, 1),             PURE(Word32Equal, 2, 1),
-    PURE(Word64And, 2, 1),             PURE(Word64Or, 2, 1),
-    PURE(Word64Xor, 2, 1),             PURE(Word64Shl, 2, 1),
-    PURE(Word64Shr, 2, 1),             PURE(Word64Sar, 2, 1),
-    PURE(Word64Ror, 2, 1),             PURE(Word64Equal, 2, 1),
-    PURE(Int32Add, 2, 1),              PURE(Int32AddWithOverflow, 2, 2),
-    PURE(Int32Sub, 2, 1),              PURE(Int32SubWithOverflow, 2, 2),
-    PURE(Int32Mul, 2, 1),              PURE(Int32Div, 2, 1),
-    PURE(Int32UDiv, 2, 1),             PURE(Int32Mod, 2, 1),
-    PURE(Int32UMod, 2, 1),             PURE(Int32LessThan, 2, 1),
-    PURE(Int32LessThanOrEqual, 2, 1),  PURE(Uint32LessThan, 2, 1),
-    PURE(Uint32LessThanOrEqual, 2, 1), PURE(Int64Add, 2, 1),
-    PURE(Int64Sub, 2, 1),              PURE(Int64Mul, 2, 1),
-    PURE(Int64Div, 2, 1),              PURE(Int64UDiv, 2, 1),
-    PURE(Int64Mod, 2, 1),              PURE(Int64UMod, 2, 1),
-    PURE(Int64LessThan, 2, 1),         PURE(Int64LessThanOrEqual, 2, 1),
-    PURE(ChangeFloat64ToInt32, 1, 1),  PURE(ChangeFloat64ToUint32, 1, 1),
-    PURE(ChangeInt32ToInt64, 1, 1),    PURE(ChangeUint32ToFloat64, 1, 1),
-    PURE(ChangeUint32ToUint64, 1, 1),  PURE(TruncateFloat64ToInt32, 1, 1),
-    PURE(TruncateInt64ToInt32, 1, 1),  PURE(Float64Add, 2, 1),
-    PURE(Float64Sub, 2, 1),            PURE(Float64Mul, 2, 1),
-    PURE(Float64Div, 2, 1),            PURE(Float64Mod, 2, 1),
-    PURE(Float64Equal, 2, 1),          PURE(Float64LessThan, 2, 1),
+    PURE(Word32And, 2, 1),                PURE(Word32Or, 2, 1),
+    PURE(Word32Xor, 2, 1),                PURE(Word32Shl, 2, 1),
+    PURE(Word32Shr, 2, 1),                PURE(Word32Sar, 2, 1),
+    PURE(Word32Ror, 2, 1),                PURE(Word32Equal, 2, 1),
+    PURE(Word64And, 2, 1),                PURE(Word64Or, 2, 1),
+    PURE(Word64Xor, 2, 1),                PURE(Word64Shl, 2, 1),
+    PURE(Word64Shr, 2, 1),                PURE(Word64Sar, 2, 1),
+    PURE(Word64Ror, 2, 1),                PURE(Word64Equal, 2, 1),
+    PURE(Int32Add, 2, 1),                 PURE(Int32AddWithOverflow, 2, 2),
+    PURE(Int32Sub, 2, 1),                 PURE(Int32SubWithOverflow, 2, 2),
+    PURE(Int32Mul, 2, 1),                 PURE(Int32Div, 2, 1),
+    PURE(Int32UDiv, 2, 1),                PURE(Int32Mod, 2, 1),
+    PURE(Int32UMod, 2, 1),                PURE(Int32LessThan, 2, 1),
+    PURE(Int32LessThanOrEqual, 2, 1),     PURE(Uint32LessThan, 2, 1),
+    PURE(Uint32LessThanOrEqual, 2, 1),    PURE(Int64Add, 2, 1),
+    PURE(Int64Sub, 2, 1),                 PURE(Int64Mul, 2, 1),
+    PURE(Int64Div, 2, 1),                 PURE(Int64UDiv, 2, 1),
+    PURE(Int64Mod, 2, 1),                 PURE(Int64UMod, 2, 1),
+    PURE(Int64LessThan, 2, 1),            PURE(Int64LessThanOrEqual, 2, 1),
+    PURE(ChangeFloat32ToFloat64, 1, 1),   PURE(ChangeFloat64ToInt32, 1, 1),
+    PURE(ChangeFloat64ToUint32, 1, 1),    PURE(ChangeInt32ToInt64, 1, 1),
+    PURE(ChangeUint32ToFloat64, 1, 1),    PURE(ChangeUint32ToUint64, 1, 1),
+    PURE(TruncateFloat64ToFloat32, 1, 1), PURE(TruncateFloat64ToInt32, 1, 1),
+    PURE(TruncateInt64ToInt32, 1, 1),     PURE(Float64Add, 2, 1),
+    PURE(Float64Sub, 2, 1),               PURE(Float64Mul, 2, 1),
+    PURE(Float64Div, 2, 1),               PURE(Float64Mod, 2, 1),
+    PURE(Float64Equal, 2, 1),             PURE(Float64LessThan, 2, 1),
     PURE(Float64LessThanOrEqual, 2, 1)
 #undef PURE
 };
index fb46a989ae0139e20adb9e944c92ada9971b0bf1..eb3e948dd8acd9e7057d513a44dfe7b4c510f9e2 100644 (file)
@@ -97,12 +97,14 @@ struct StaticParameterTraits<LoadRepresentation> {
   V(Int64UMod, Operator::kNoProperties, 2, 1)                                 \
   V(Int64LessThan, Operator::kNoProperties, 2, 1)                             \
   V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 1)                      \
+  V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 1)                    \
   V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 1)                      \
   V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 1)                     \
   V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 1)                      \
   V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 1)                        \
   V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 1)                     \
   V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 1)                      \
+  V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 1)                  \
   V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 1)                    \
   V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 1)                      \
   V(Float64Add, Operator::kCommutative, 2, 1)                                 \
index bff0821ec4d25c99c07d6d643f6b53cc59121f5c..23b7ef6453215b4b0e5d8b1ec7f684da30b51309 100644 (file)
@@ -104,23 +104,23 @@ class MachineOperatorBuilder FINAL {
   const Operator* Int64LessThan();
   const Operator* Int64LessThanOrEqual();
 
-  // Convert representation of integers between float64 and int32/uint32.
-  // The precise rounding mode and handling of out of range inputs are *not*
-  // defined for these operators, since they are intended only for use with
-  // integers.
+  // These operators change the representation of numbers while preserving the
+  // value of the number. Narrowing operators assume the input is representable
+  // in the target type and are *not* defined for other inputs.
+  // Use narrowing change operators only when there is a static guarantee that
+  // the input value is representable in the target value.
+  const Operator* ChangeFloat32ToFloat64();
+  const Operator* ChangeFloat64ToInt32();   // narrowing
+  const Operator* ChangeFloat64ToUint32();  // narrowing
   const Operator* ChangeInt32ToFloat64();
-  const Operator* ChangeUint32ToFloat64();
-  const Operator* ChangeFloat64ToInt32();
-  const Operator* ChangeFloat64ToUint32();
-
-  // Sign/zero extend int32/uint32 to int64/uint64.
   const Operator* ChangeInt32ToInt64();
+  const Operator* ChangeUint32ToFloat64();
   const Operator* ChangeUint32ToUint64();
 
-  // Truncate double to int32 using JavaScript semantics.
-  const Operator* TruncateFloat64ToInt32();
-
-  // Truncate the high order bits and convert the remaining bits to int32.
+  // These operators truncate numbers, both changing the representation of
+  // the number and mapping multiple input values onto the same output value.
+  const Operator* TruncateFloat64ToFloat32();
+  const Operator* TruncateFloat64ToInt32();  // JavaScript semantics.
   const Operator* TruncateInt64ToInt32();
 
   // Floating point operators always operate with IEEE 754 round-to-nearest.
index d73a9268b65c23f9c5d788bfea381d0ff64bdf0e..e62eaeea8e678368a4ff451dbbb53d6f2f6722e8 100644 (file)
@@ -90,6 +90,7 @@ struct FloatMatcher FINAL : public ValueMatcher<T, kOpcode> {
   bool IsNaN() const { return this->HasValue() && std::isnan(this->Value()); }
 };
 
+typedef FloatMatcher<float, IrOpcode::kFloat32Constant> Float32Matcher;
 typedef FloatMatcher<double, IrOpcode::kFloat64Constant> Float64Matcher;
 typedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher;
 
index f295eac09ef3529a3802719f464810d93bdc19ba..dabf5c57ef86261869756f18587b74a1786201bf 100644 (file)
@@ -25,6 +25,7 @@
 #define LEAF_OP_LIST(V) \
   V(Int32Constant)      \
   V(Int64Constant)      \
+  V(Float32Constant)    \
   V(Float64Constant)    \
   V(ExternalConstant)   \
   V(NumberConstant)     \
   V(StoreElement)
 
 // Opcodes for Machine-level operators.
-#define MACHINE_OP_LIST(V)  \
-  V(Load)                   \
-  V(Store)                  \
-  V(Word32And)              \
-  V(Word32Or)               \
-  V(Word32Xor)              \
-  V(Word32Shl)              \
-  V(Word32Shr)              \
-  V(Word32Sar)              \
-  V(Word32Ror)              \
-  V(Word32Equal)            \
-  V(Word64And)              \
-  V(Word64Or)               \
-  V(Word64Xor)              \
-  V(Word64Shl)              \
-  V(Word64Shr)              \
-  V(Word64Sar)              \
-  V(Word64Ror)              \
-  V(Word64Equal)            \
-  V(Int32Add)               \
-  V(Int32AddWithOverflow)   \
-  V(Int32Sub)               \
-  V(Int32SubWithOverflow)   \
-  V(Int32Mul)               \
-  V(Int32Div)               \
-  V(Int32UDiv)              \
-  V(Int32Mod)               \
-  V(Int32UMod)              \
-  V(Int32LessThan)          \
-  V(Int32LessThanOrEqual)   \
-  V(Uint32LessThan)         \
-  V(Uint32LessThanOrEqual)  \
-  V(Int64Add)               \
-  V(Int64Sub)               \
-  V(Int64Mul)               \
-  V(Int64Div)               \
-  V(Int64UDiv)              \
-  V(Int64Mod)               \
-  V(Int64UMod)              \
-  V(Int64LessThan)          \
-  V(Int64LessThanOrEqual)   \
-  V(ChangeInt32ToFloat64)   \
-  V(ChangeUint32ToFloat64)  \
-  V(ChangeFloat64ToInt32)   \
-  V(ChangeFloat64ToUint32)  \
-  V(ChangeInt32ToInt64)     \
-  V(ChangeUint32ToUint64)   \
-  V(TruncateFloat64ToInt32) \
-  V(TruncateInt64ToInt32)   \
-  V(Float64Add)             \
-  V(Float64Sub)             \
-  V(Float64Mul)             \
-  V(Float64Div)             \
-  V(Float64Mod)             \
-  V(Float64Equal)           \
-  V(Float64LessThan)        \
+#define MACHINE_OP_LIST(V)    \
+  V(Load)                     \
+  V(Store)                    \
+  V(Word32And)                \
+  V(Word32Or)                 \
+  V(Word32Xor)                \
+  V(Word32Shl)                \
+  V(Word32Shr)                \
+  V(Word32Sar)                \
+  V(Word32Ror)                \
+  V(Word32Equal)              \
+  V(Word64And)                \
+  V(Word64Or)                 \
+  V(Word64Xor)                \
+  V(Word64Shl)                \
+  V(Word64Shr)                \
+  V(Word64Sar)                \
+  V(Word64Ror)                \
+  V(Word64Equal)              \
+  V(Int32Add)                 \
+  V(Int32AddWithOverflow)     \
+  V(Int32Sub)                 \
+  V(Int32SubWithOverflow)     \
+  V(Int32Mul)                 \
+  V(Int32Div)                 \
+  V(Int32UDiv)                \
+  V(Int32Mod)                 \
+  V(Int32UMod)                \
+  V(Int32LessThan)            \
+  V(Int32LessThanOrEqual)     \
+  V(Uint32LessThan)           \
+  V(Uint32LessThanOrEqual)    \
+  V(Int64Add)                 \
+  V(Int64Sub)                 \
+  V(Int64Mul)                 \
+  V(Int64Div)                 \
+  V(Int64UDiv)                \
+  V(Int64Mod)                 \
+  V(Int64UMod)                \
+  V(Int64LessThan)            \
+  V(Int64LessThanOrEqual)     \
+  V(ChangeFloat32ToFloat64)   \
+  V(ChangeFloat64ToInt32)     \
+  V(ChangeFloat64ToUint32)    \
+  V(ChangeInt32ToFloat64)     \
+  V(ChangeInt32ToInt64)       \
+  V(ChangeUint32ToFloat64)    \
+  V(ChangeUint32ToUint64)     \
+  V(TruncateFloat64ToFloat32) \
+  V(TruncateFloat64ToInt32)   \
+  V(TruncateInt64ToInt32)     \
+  V(Float64Add)               \
+  V(Float64Sub)               \
+  V(Float64Mul)               \
+  V(Float64Div)               \
+  V(Float64Mod)               \
+  V(Float64Equal)             \
+  V(Float64LessThan)          \
   V(Float64LessThanOrEqual)
 
 #define VALUE_OP_LIST(V) \
index c4af35e16dd1b04db09fcf76e59199266dd8eb2e..bfecdef61e9b5f80413d3a0c653cd0d9e5c9ba81 100644 (file)
@@ -255,6 +255,12 @@ Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
 }
 
 
+Bounds Typer::Visitor::TypeFloat32Constant(Node* node) {
+  // TODO(titzer): only call Type::Of() if the type is not already known.
+  return Bounds(Type::Of(OpParameter<float>(node), zone()));
+}
+
+
 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
   // TODO(titzer): only call Type::Of() if the type is not already known.
   return Bounds(Type::Of(OpParameter<double>(node), zone()));
index bac15768270f4fe0808c31332e261dac81312dce..ae87dc4d31b01763eef756a1058a05ca0dc1561e 100644 (file)
@@ -67,6 +67,14 @@ inline unsigned int FastD2UI(double x) {
 }
 
 
+inline float DoubleToFloat32(double x) {
+  // TODO(yanggou): This static_cast is implementation-defined behaviour in C++,
+  // so we may need to do the conversion manually instead to match the spec.
+  volatile float f = static_cast<float>(x);
+  return f;
+}
+
+
 inline double DoubleToInteger(double x) {
   if (std::isnan(x)) return 0;
   if (!std::isfinite(x) || x == 0) return x;
index 1b76ac5b67606310acea32ccfb6120d58416b469..6a28b5f1ea0209036955e71fdbb22fd5873db08b 100644 (file)
@@ -77,6 +77,10 @@ inline double FastUI2D(unsigned x) {
 }
 
 
+// This function should match the exact semantics of ECMA-262 20.2.2.17.
+inline float DoubleToFloat32(double x);
+
+
 // This function should match the exact semantics of ECMA-262 9.4.
 inline double DoubleToInteger(double x);
 
index 3acbb81d89dff0c0d2c21003762bb785c6a7df85..f5789f68d92b796f5f2a07fcb2510f41efa321ad 100644 (file)
@@ -7971,7 +7971,7 @@ RUNTIME_FUNCTION(Runtime_MathFround) {
   DCHECK(args.length() == 1);
 
   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  float xf = static_cast<float>(x);
+  float xf = DoubleToFloat32(x);
   return *isolate->factory()->NewNumber(xf);
 }