[turbofan] Add backend support for Float32Constant.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Thu, 25 Sep 2014 08:56:02 +0000 (08:56 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Thu, 25 Sep 2014 08:56:02 +0000 (08:56 +0000)
TEST=cctest,compiler-unittests,mjsunit
BUG=v8:3589
LOG=n
R=mstarzinger@chromium.org

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

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

12 files changed:
src/compiler/arm/code-generator-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/ia32/code-generator-ia32.cc
src/compiler/instruction-selector-impl.h
src/compiler/instruction-selector-unittest.cc
src/compiler/instruction-selector-unittest.h
src/compiler/instruction-selector.cc
src/compiler/instruction.cc
src/compiler/instruction.h
src/compiler/raw-machine-assembler.h
src/compiler/x64/code-generator-x64.cc
test/cctest/compiler/test-run-machops.cc

index 89a3a044be48d1df7f93bb08f4f313c40ce8bcc9..fabcfdcdc5f769ad7eafa59e07f6b6c0a289f2bd 100644 (file)
@@ -68,6 +68,9 @@ class ArmOperandConverter FINAL : public InstructionOperandConverter {
     switch (constant.type()) {
       case Constant::kInt32:
         return Operand(constant.ToInt32());
+      case Constant::kFloat32:
+        return Operand(
+            isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
       case Constant::kFloat64:
         return Operand(
             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
@@ -750,10 +753,10 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
       __ str(temp, g.ToMemOperand(destination));
     }
   } else if (source->IsConstant()) {
+    Constant src = g.ToConstant(source);
     if (destination->IsRegister() || destination->IsStackSlot()) {
       Register dst =
           destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
-      Constant src = g.ToConstant(source);
       switch (src.type()) {
         case Constant::kInt32:
           __ mov(dst, Operand(src.ToInt32()));
@@ -761,6 +764,10 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
         case Constant::kInt64:
           UNREACHABLE();
           break;
+        case Constant::kFloat32:
+          __ Move(dst,
+                  isolate()->factory()->NewNumber(src.ToFloat32(), TENURED));
+          break;
         case Constant::kFloat64:
           __ Move(dst,
                   isolate()->factory()->NewNumber(src.ToFloat64(), TENURED));
@@ -773,14 +780,25 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
           break;
       }
       if (destination->IsStackSlot()) __ str(dst, g.ToMemOperand(destination));
-    } else if (destination->IsDoubleRegister()) {
-      DwVfpRegister result = g.ToDoubleRegister(destination);
-      __ vmov(result, g.ToDouble(source));
+    } else if (src.type() == Constant::kFloat32) {
+      SwVfpRegister dst = destination->IsDoubleRegister()
+                              ? g.ToFloat32Register(destination)
+                              : kScratchDoubleReg.low();
+      // TODO(turbofan): Can we do better here?
+      __ mov(ip, Operand(bit_cast<int32_t>(src.ToFloat32())));
+      __ vmov(dst, ip);
+      if (destination->IsDoubleStackSlot()) {
+        __ vstr(dst, g.ToMemOperand(destination));
+      }
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
-      DwVfpRegister temp = kScratchDoubleReg;
-      __ vmov(temp, g.ToDouble(source));
-      __ vstr(temp, g.ToMemOperand(destination));
+      DCHECK_EQ(Constant::kFloat64, src.type());
+      DwVfpRegister dst = destination->IsDoubleRegister()
+                              ? g.ToFloat64Register(destination)
+                              : kScratchDoubleReg;
+      __ vmov(dst, src.ToFloat64());
+      if (destination->IsDoubleStackSlot()) {
+        __ vstr(dst, g.ToMemOperand(destination));
+      }
     }
   } else if (source->IsDoubleRegister()) {
     DwVfpRegister src = g.ToDoubleRegister(source);
index 28be056d6cd9dada2f6a3d81f9d8e81a9f8a03b0..a842a6ab8494d3dfeab70fa166ef6f1528381c80 100644 (file)
@@ -89,6 +89,9 @@ class Arm64OperandConverter FINAL : public InstructionOperandConverter {
         return Operand(constant.ToInt32());
       case Constant::kInt64:
         return Operand(constant.ToInt64());
+      case Constant::kFloat32:
+        return Operand(
+            isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
       case Constant::kFloat64:
         return Operand(
             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
@@ -758,12 +761,11 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
       __ Str(temp, g.ToMemOperand(destination, masm()));
     }
   } else if (source->IsConstant()) {
-    ConstantOperand* constant_source = ConstantOperand::cast(source);
+    Constant src = g.ToConstant(ConstantOperand::cast(source));
     if (destination->IsRegister() || destination->IsStackSlot()) {
       UseScratchRegisterScope scope(masm());
       Register dst = destination->IsRegister() ? g.ToRegister(destination)
                                                : scope.AcquireX();
-      Constant src = g.ToConstant(source);
       if (src.type() == Constant::kHeapObject) {
         __ LoadObject(dst, src.ToHeapObject());
       } else {
@@ -772,15 +774,29 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
       if (destination->IsStackSlot()) {
         __ Str(dst, g.ToMemOperand(destination, masm()));
       }
-    } else if (destination->IsDoubleRegister()) {
-      FPRegister result = g.ToDoubleRegister(destination);
-      __ Fmov(result, g.ToDouble(constant_source));
+    } else if (src.type() == Constant::kFloat32) {
+      if (destination->IsDoubleRegister()) {
+        FPRegister dst = g.ToDoubleRegister(destination).S();
+        __ Fmov(dst, src.ToFloat32());
+      } else {
+        DCHECK(destination->IsDoubleStackSlot());
+        UseScratchRegisterScope scope(masm());
+        FPRegister temp = scope.AcquireS();
+        __ Fmov(temp, src.ToFloat32());
+        __ Str(temp, g.ToMemOperand(destination, masm()));
+      }
     } else {
-      DCHECK(destination->IsDoubleStackSlot());
-      UseScratchRegisterScope scope(masm());
-      FPRegister temp = scope.AcquireD();
-      __ Fmov(temp, g.ToDouble(constant_source));
-      __ Str(temp, g.ToMemOperand(destination, masm()));
+      DCHECK_EQ(Constant::kFloat64, src.type());
+      if (destination->IsDoubleRegister()) {
+        FPRegister dst = g.ToDoubleRegister(destination);
+        __ Fmov(dst, src.ToFloat64());
+      } else {
+        DCHECK(destination->IsDoubleStackSlot());
+        UseScratchRegisterScope scope(masm());
+        FPRegister temp = scope.AcquireD();
+        __ Fmov(temp, src.ToFloat64());
+        __ Str(temp, g.ToMemOperand(destination, masm()));
+      }
     }
   } else if (source->IsDoubleRegister()) {
     FPRegister src = g.ToDoubleRegister(source);
index 9d9a5691c6c3454bf3b910b39dc1905a78ce1b48..97b37060be3ee12b14d012ce592a4da22bf239e2 100644 (file)
@@ -59,6 +59,9 @@ class IA32OperandConverter : public InstructionOperandConverter {
     switch (constant.type()) {
       case Constant::kInt32:
         return Immediate(constant.ToInt32());
+      case Constant::kFloat32:
+        return Immediate(
+            isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
       case Constant::kFloat64:
         return Immediate(
             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
@@ -839,8 +842,22 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
     } else if (destination->IsStackSlot()) {
       Operand dst = g.ToOperand(destination);
       __ mov(dst, g.ToImmediate(source));
+    } else if (src_constant.type() == Constant::kFloat32) {
+      // TODO(turbofan): Can we do better here?
+      Immediate src(bit_cast<int32_t>(src_constant.ToFloat32()));
+      if (destination->IsDoubleRegister()) {
+        XMMRegister dst = g.ToDoubleRegister(destination);
+        __ push(Immediate(src));
+        __ movss(dst, Operand(esp, 0));
+        __ add(esp, Immediate(kDoubleSize / 2));
+      } else {
+        DCHECK(destination->IsDoubleStackSlot());
+        Operand dst = g.ToOperand(destination);
+        __ mov(dst, src);
+      }
     } else {
-      double v = g.ToDouble(source);
+      DCHECK_EQ(Constant::kFloat64, src_constant.type());
+      double v = src_constant.ToFloat64();
       uint64_t int_val = bit_cast<uint64_t, double>(v);
       int32_t lower = static_cast<int32_t>(int_val);
       int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
index d00109e296fd85813ecdd422aa43fcae33234411..b860bc5187130ced1ef8329036c7c78bfa5ed299 100644 (file)
@@ -146,8 +146,10 @@ class OperandGenerator {
         return Constant(OpParameter<int32_t>(node));
       case IrOpcode::kInt64Constant:
         return Constant(OpParameter<int64_t>(node));
-      case IrOpcode::kNumberConstant:
+      case IrOpcode::kFloat32Constant:
+        return Constant(OpParameter<float>(node));
       case IrOpcode::kFloat64Constant:
+      case IrOpcode::kNumberConstant:
         return Constant(OpParameter<double>(node));
       case IrOpcode::kExternalConstant:
         return Constant(OpParameter<ExternalReference>(node));
index aa707357e991b5c43cb869654c3498d9f2bdd522..75159b09c1c30d5303ec56c31f23ba144fa2b146 100644 (file)
@@ -113,6 +113,20 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
 // Return.
 
 
+TARGET_TEST_F(InstructionSelectorTest, ReturnFloat32Constant) {
+  const float kValue = 4.2f;
+  StreamBuilder m(this, kMachFloat32);
+  m.Return(m.Float32Constant(kValue));
+  Stream s = m.Build(kAllInstructions);
+  ASSERT_EQ(2U, s.size());
+  EXPECT_EQ(kArchNop, s[0]->arch_opcode());
+  ASSERT_EQ(InstructionOperand::CONSTANT, s[0]->OutputAt(0)->kind());
+  EXPECT_FLOAT_EQ(kValue, s.ToFloat32(s[0]->OutputAt(0)));
+  EXPECT_EQ(kArchRet, s[1]->arch_opcode());
+  EXPECT_EQ(1U, s[1]->InputCount());
+}
+
+
 TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
   StreamBuilder m(this, kMachInt32, kMachInt32);
   m.Return(m.Parameter(0));
@@ -288,6 +302,8 @@ TARGET_TEST_F(InstructionSelectorTest, ValueEffect) {
 
 // -----------------------------------------------------------------------------
 // Calls with deoptimization.
+
+
 TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
   StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged,
                   kMachAnyTagged);
index 4e12dabbe1898d6a1a54911f86bae5d0a47b69c6..3e7f63aa60ae8ef6beb6d4a9e14951bea9b13364 100644 (file)
@@ -143,6 +143,10 @@ class InstructionSelectorTest : public TestWithContext, public TestWithZone {
       return references_.find(virtual_register) != references_.end();
     }
 
+    float ToFloat32(const InstructionOperand* operand) const {
+      return ToConstant(operand).ToFloat32();
+    }
+
     int32_t ToInt32(const InstructionOperand* operand) const {
       return ToConstant(operand).ToInt32();
     }
index d7d8c8b6ddae4902d20af1350b710eb2fcf783e6..f36b07ea7e6655185bb86dcf43fb90d312a293da 100644 (file)
@@ -476,6 +476,8 @@ void InstructionSelector::VisitNode(Node* node) {
     case IrOpcode::kInt64Constant:
     case IrOpcode::kExternalConstant:
       return VisitConstant(node);
+    case IrOpcode::kFloat32Constant:
+      return MarkAsDouble(node), VisitConstant(node);
     case IrOpcode::kFloat64Constant:
       return MarkAsDouble(node), VisitConstant(node);
     case IrOpcode::kHeapConstant:
index 9ab81b6ae1af42039b05e2bb1473cde84340e371..35232807e655f188e4dc55e694d4f141ff97b8b7 100644 (file)
@@ -300,6 +300,8 @@ OStream& operator<<(OStream& os, const Constant& constant) {
       return os << constant.ToInt32();
     case Constant::kInt64:
       return os << constant.ToInt64() << "l";
+    case Constant::kFloat32:
+      return os << constant.ToFloat32() << "f";
     case Constant::kFloat64:
       return os << constant.ToFloat64();
     case Constant::kExternalReference:
index 6d007841f42ad0b1dd010f6d03aa28adc9e62c4e..f8ad55e0e6f9eac0c582fb23ffa63036758cd2c3 100644 (file)
@@ -654,10 +654,18 @@ class SourcePositionInstruction FINAL : public Instruction {
 
 class Constant FINAL {
  public:
-  enum Type { kInt32, kInt64, kFloat64, kExternalReference, kHeapObject };
+  enum Type {
+    kInt32,
+    kInt64,
+    kFloat32,
+    kFloat64,
+    kExternalReference,
+    kHeapObject
+  };
 
   explicit Constant(int32_t v) : type_(kInt32), value_(v) {}
   explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
+  explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
   explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
   explicit Constant(ExternalReference ref)
       : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
@@ -677,6 +685,11 @@ class Constant FINAL {
     return value_;
   }
 
+  float ToFloat32() const {
+    DCHECK_EQ(kFloat32, type());
+    return bit_cast<float>(static_cast<int32_t>(value_));
+  }
+
   double ToFloat64() const {
     if (type() == kInt32) return ToInt32();
     DCHECK_EQ(kFloat64, type());
index cad9ae922208dbdbac6d4f7a70a69f3d7c2c35de..846ff1c03dc06eac8879a91cb1cc4247970328c7 100644 (file)
@@ -80,6 +80,9 @@ class RawMachineAssembler : public GraphBuilder {
   Node* NumberConstant(double value) {
     return NewNode(common()->NumberConstant(value));
   }
+  Node* Float32Constant(float value) {
+    return NewNode(common()->Float32Constant(value));
+  }
   Node* Float64Constant(double value) {
     return NewNode(common()->Float64Constant(value));
   }
index c88c101c408fcfc01e9858c2193c4b1570aa4858..10cafeedffe2fc1be2918160e300f6ab5f1721c7 100644 (file)
@@ -75,6 +75,11 @@ class X64OperandConverter : public InstructionOperandConverter {
       case Constant::kInt64:
         immediate.value = constant.ToInt64();
         return immediate;
+      case Constant::kFloat32:
+        immediate.type = kImm64Handle;
+        immediate.handle =
+            isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED);
+        return immediate;
       case Constant::kFloat64:
         immediate.type = kImm64Handle;
         immediate.handle =
@@ -99,6 +104,7 @@ class X64OperandConverter : public InstructionOperandConverter {
       case Constant::kInt32:
         return Immediate(constant.ToInt32());
       case Constant::kInt64:
+      case Constant::kFloat32:
       case Constant::kFloat64:
       case Constant::kExternalReference:
       case Constant::kHeapObject:
@@ -901,6 +907,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
     }
   } else if (source->IsConstant()) {
     ConstantOperand* constant_source = ConstantOperand::cast(source);
+    Constant src = g.ToConstant(constant_source);
     if (destination->IsRegister() || destination->IsStackSlot()) {
       Register dst = destination->IsRegister() ? g.ToRegister(destination)
                                                : kScratchRegister;
@@ -919,9 +926,20 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
       if (destination->IsStackSlot()) {
         __ movq(g.ToOperand(destination), kScratchRegister);
       }
+    } else if (src.type() == Constant::kFloat32) {
+      // TODO(turbofan): Can we do better here?
+      __ movl(kScratchRegister, Immediate(bit_cast<int32_t>(src.ToFloat32())));
+      if (destination->IsDoubleRegister()) {
+        XMMRegister dst = g.ToDoubleRegister(destination);
+        __ movq(dst, kScratchRegister);
+      } else {
+        DCHECK(destination->IsDoubleStackSlot());
+        Operand dst = g.ToOperand(destination);
+        __ movl(dst, kScratchRegister);
+      }
     } else {
-      __ movq(kScratchRegister,
-              bit_cast<uint64_t, double>(g.ToDouble(constant_source)));
+      DCHECK_EQ(Constant::kFloat64, src.type());
+      __ movq(kScratchRegister, bit_cast<int64_t>(src.ToFloat64()));
       if (destination->IsDoubleRegister()) {
         __ movq(g.ToDoubleRegister(destination), kScratchRegister);
       } else {
index 3c8d909e7ee3def3167a815e5ed07feff1315008..5606126e062d7f0e18cf7daa2e4dcf2d0d556d8a 100644 (file)
@@ -4275,4 +4275,17 @@ TEST(RunTruncateFloat64ToFloat32) {
   }
 }
 
+
+TEST(RunFloat32Constant) {
+  FOR_FLOAT32_INPUTS(i) {
+    float expected = *i;
+    float actual = *i;
+    RawMachineAssemblerTester<int32_t> m;
+    m.StoreToPointer(&actual, kMachFloat32, m.Float32Constant(expected));
+    m.Return(m.Int32Constant(0));
+    CHECK_EQ(0, m.Call());
+    CHECK_EQ(expected, actual);
+  }
+}
+
 #endif  // V8_TURBOFAN_TARGET