Hack representation inference to assume current behavior of float32 loads and stores...
authortitzer@chromium.org <titzer@chromium.org>
Fri, 19 Sep 2014 09:56:12 +0000 (09:56 +0000)
committertitzer@chromium.org <titzer@chromium.org>
Fri, 19 Sep 2014 09:56:12 +0000 (09:56 +0000)
R=mstarzinger@chromium.org
BUG=

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

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

src/compiler/representation-change.h
src/compiler/simplified-lowering.cc
test/cctest/compiler/test-representation-change.cc
test/cctest/compiler/test-run-properties.cc
test/cctest/compiler/test-simplified-lowering.cc

index 3c6dcbac888ddf17336ef451da1675d5b5a88ad0..3ba5b4e5cb6b670fa6a2370135f208a9d431c583 100644 (file)
@@ -53,6 +53,8 @@ class RepresentationChanger {
       return GetTaggedRepresentationFor(node, output_type);
     } else if (use_type & kRepFloat64) {
       return GetFloat64RepresentationFor(node, output_type);
+    } else if (use_type & kRepFloat32) {
+      return TypeError(node, output_type, use_type);  // TODO(titzer): handle
     } else if (use_type & kRepBit) {
       return GetBitRepresentationFor(node, output_type);
     } else if (use_type & rWord) {
index 89c58685f1b43cbfd6b767f9160b3567eeb5fb49..e3ddf5c461d6dadc0f63736d1d3d47855873c2cf 100644 (file)
@@ -349,6 +349,15 @@ class RepresentationSelector {
     return changer_->Float64OperatorFor(node->opcode());
   }
 
+  static MachineType AssumeImplicitFloat32Change(MachineType type) {
+    // TODO(titzer): Assume loads of float32 change representation to float64.
+    // Fix this with full support for float32 representations.
+    if (type & kRepFloat32) {
+      return static_cast<MachineType>((type & ~kRepFloat32) | kRepFloat64);
+    }
+    return type;
+  }
+
   // Dispatching routine for visiting the node {node} with the usage {use}.
   // Depending on the operator, propagate new usage info to the inputs.
   void VisitNode(Node* node, MachineTypeUnion use,
@@ -570,14 +579,14 @@ class RepresentationSelector {
         FieldAccess access = FieldAccessOf(node->op());
         ProcessInput(node, 0, changer_->TypeForBasePointer(access));
         ProcessRemainingInputs(node, 1);
-        SetOutput(node, access.machine_type);
+        SetOutput(node, AssumeImplicitFloat32Change(access.machine_type));
         if (lower()) lowering->DoLoadField(node);
         break;
       }
       case IrOpcode::kStoreField: {
         FieldAccess access = FieldAccessOf(node->op());
         ProcessInput(node, 0, changer_->TypeForBasePointer(access));
-        ProcessInput(node, 1, access.machine_type);
+        ProcessInput(node, 1, AssumeImplicitFloat32Change(access.machine_type));
         ProcessRemainingInputs(node, 2);
         SetOutput(node, 0);
         if (lower()) lowering->DoStoreField(node);
@@ -588,7 +597,7 @@ class RepresentationSelector {
         ProcessInput(node, 0, changer_->TypeForBasePointer(access));
         ProcessInput(node, 1, kMachInt32);  // element index
         ProcessRemainingInputs(node, 2);
-        SetOutput(node, access.machine_type);
+        SetOutput(node, AssumeImplicitFloat32Change(access.machine_type));
         if (lower()) lowering->DoLoadElement(node);
         break;
       }
@@ -596,7 +605,7 @@ class RepresentationSelector {
         ElementAccess access = ElementAccessOf(node->op());
         ProcessInput(node, 0, changer_->TypeForBasePointer(access));
         ProcessInput(node, 1, kMachInt32);  // element index
-        ProcessInput(node, 2, access.machine_type);
+        ProcessInput(node, 2, AssumeImplicitFloat32Change(access.machine_type));
         ProcessRemainingInputs(node, 3);
         SetOutput(node, 0);
         if (lower()) lowering->DoStoreElement(node);
index 9c55a802c2c924961b3b034e4f21e4a3ad4d658d..6c9026b2e018ee7147b684239fbd3fc516249902 100644 (file)
@@ -88,6 +88,7 @@ class RepresentationChangerTester : public HandleAndZoneScope,
 }  // namespace v8::internal::compiler
 
 
+// TODO(titzer): add kRepFloat32 when fully supported.
 static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64,
                                        kRepFloat64, kRepTagged};
 
@@ -225,6 +226,11 @@ TEST(Nops) {
     r.CheckNop(all_reps[i], all_reps[i]);
   }
 
+  // 32-bit floats.
+  r.CheckNop(kRepFloat32, kRepFloat32);
+  r.CheckNop(kRepFloat32 | kTypeNumber, kRepFloat32);
+  r.CheckNop(kRepFloat32, kRepFloat32 | kTypeNumber);
+
   // 32-bit or 64-bit words can be used as branch conditions (kRepBit).
   r.CheckNop(kRepWord32, kRepBit);
   r.CheckNop(kRepWord32, kRepBit | kTypeBool);
@@ -261,6 +267,12 @@ TEST(TypeErrors) {
   r.CheckTypeError(kRepBit, kRepFloat64);
   r.CheckTypeError(kRepBit | kTypeBool, kRepFloat64);
 
+  // Floats cannot be implicitly converted to/from comparison conditions.
+  r.CheckTypeError(kRepFloat32, kRepBit);
+  r.CheckTypeError(kRepFloat32, kRepBit | kTypeBool);
+  r.CheckTypeError(kRepBit, kRepFloat32);
+  r.CheckTypeError(kRepBit | kTypeBool, kRepFloat32);
+
   // Word64 is internal and shouldn't be implicitly converted.
   r.CheckTypeError(kRepWord64, kRepTagged | kTypeBool);
   r.CheckTypeError(kRepWord64, kRepTagged);
@@ -283,24 +295,11 @@ TEST(TypeErrors) {
       r.CheckTypeError(all_reps[i] | all_reps[j], kRepTagged);
     }
   }
-}
 
-
-TEST(CompleteMatrix) {
-  // TODO(titzer): test all variants in the matrix.
-  // rB
-  // tBrB
-  // tBrT
-  // rW32
-  // tIrW32
-  // tUrW32
-  // rW64
-  // tIrW64
-  // tUrW64
-  // rF64
-  // tIrF64
-  // tUrF64
-  // tArF64
-  // rT
-  // tArT
+  // TODO(titzer): Float32 representation changes trigger type errors now.
+  // Enforce current behavior to test all paths through representation changer.
+  for (size_t i = 0; i < arraysize(all_reps); i++) {
+    r.CheckTypeError(all_reps[i], kRepFloat32);
+    r.CheckTypeError(kRepFloat32, all_reps[i]);
+  }
 }
index b1f04c51c2860d75927234b76e0896d04b9bd718..a76b0629659ef3a5384ef5cef9850fab891dad01 100644 (file)
@@ -47,9 +47,10 @@ static void TypedArrayLoadHelper(const char* array_type) {
       CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
   for (size_t i = 0; i < arraysize(kValues); ++i) {
     for (size_t j = 0; j < arraysize(kValues); ++j) {
-      double value_a = static_cast<U>(kValues[i]);
-      double value_b = static_cast<U>(kValues[j]);
-      double expected = value_a + value_b;
+      U value_a = static_cast<U>(kValues[i]);
+      U value_b = static_cast<U>(kValues[j]);
+      double expected =
+          static_cast<double>(value_a) + static_cast<double>(value_b);
       T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
                   T.Val(static_cast<double>(j)));
     }
@@ -65,8 +66,8 @@ TEST(TypedArrayLoad) {
   TypedArrayLoadHelper<uint16_t>("Uint16");
   TypedArrayLoadHelper<int32_t>("Int32");
   TypedArrayLoadHelper<uint32_t>("Uint32");
+  TypedArrayLoadHelper<float>("Float32");
   TypedArrayLoadHelper<double>("Float64");
-  // TODO(mstarzinger): Add tests for Float32.
   // TODO(mstarzinger): Add tests for ClampedUint8.
 }
 
@@ -115,9 +116,10 @@ static void TypedArrayStoreHelper(const char* array_type) {
       CompilationInfo::kContextSpecializing | CompilationInfo::kTypingEnabled);
   for (size_t i = 0; i < arraysize(kValues); ++i) {
     for (size_t j = 0; j < arraysize(kValues); ++j) {
-      double value_a = static_cast<U>(kValues[i]);
-      double value_b = static_cast<U>(kValues[j]);
-      double expected = value_b + value_a;
+      U value_a = static_cast<U>(kValues[i]);
+      U value_b = static_cast<U>(kValues[j]);
+      double expected =
+          static_cast<double>(value_a) + static_cast<double>(value_b);
       T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
                   T.Val(static_cast<double>(j)));
     }
@@ -133,7 +135,7 @@ TEST(TypedArrayStore) {
   TypedArrayStoreHelper<uint16_t>("Uint16");
   TypedArrayStoreHelper<int32_t>("Int32");
   TypedArrayStoreHelper<uint32_t>("Uint32");
+  TypedArrayStoreHelper<float>("Float32");
   TypedArrayStoreHelper<double>("Float64");
-  // TODO(mstarzinger): Add tests for Float32.
   // TODO(mstarzinger): Add tests for ClampedUint8.
 }
index 163fdc8fb731feb488ed490f817d31ddf9d82935..2c97379cbb0cd8eb1a85c6ae311feb6c8e9e8e22 100644 (file)
@@ -1510,3 +1510,38 @@ TEST(UpdatePhi) {
              RepresentationOf(OpParameter<MachineType>(phi)));
   }
 }
+
+
+// TODO(titzer): this tests current behavior of assuming an implicit
+// representation change in loading float32s. Fix when float32 is fully
+// supported.
+TEST(ImplicitFloat32ToFloat64InLoads) {
+  TestingGraph t(Type::Any());
+
+  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+                        Handle<Name>::null(), Type::Any(), kMachFloat32};
+
+  Node* load =
+      t.graph()->NewNode(t.simplified()->LoadField(access), t.p0, t.start);
+  t.Return(load);
+  t.Lower();
+  CHECK_EQ(IrOpcode::kLoad, load->opcode());
+  CHECK_EQ(t.p0, load->InputAt(0));
+  CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, load, t.ret->InputAt(0));
+}
+
+
+TEST(ImplicitFloat64ToFloat32InStores) {
+  TestingGraph t(Type::Any(), Type::Signed32());
+  FieldAccess access = {kTaggedBase, FixedArrayBase::kHeaderSize,
+                        Handle<Name>::null(), Type::Any(), kMachFloat32};
+
+  Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0,
+                                   t.p1, t.start, t.start);
+  t.Effect(store);
+  t.Lower();
+
+  CHECK_EQ(IrOpcode::kStore, store->opcode());
+  CHECK_EQ(t.p0, store->InputAt(0));
+  CheckChangeOf(IrOpcode::kChangeTaggedToFloat64, t.p1, store->InputAt(2));
+}