[turbofan] Add support for reinterpreting integers as floating point and vice versa.
authortitzer <titzer@chromium.org>
Mon, 21 Sep 2015 14:00:51 +0000 (07:00 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 21 Sep 2015 14:01:05 +0000 (14:01 +0000)
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#30849}

26 files changed:
src/compiler/arm/instruction-selector-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/arm64/instruction-codes-arm64.h
src/compiler/arm64/instruction-selector-arm64.cc
src/compiler/ia32/code-generator-ia32.cc
src/compiler/ia32/instruction-codes-ia32.h
src/compiler/ia32/instruction-selector-ia32.cc
src/compiler/instruction-selector.cc
src/compiler/machine-operator.cc
src/compiler/machine-operator.h
src/compiler/mips/instruction-selector-mips.cc
src/compiler/mips64/code-generator-mips64.cc
src/compiler/mips64/instruction-codes-mips64.h
src/compiler/mips64/instruction-selector-mips64.cc
src/compiler/opcodes.h
src/compiler/ppc/code-generator-ppc.cc
src/compiler/ppc/instruction-codes-ppc.h
src/compiler/ppc/instruction-selector-ppc.cc
src/compiler/raw-machine-assembler.h
src/compiler/typer.cc
src/compiler/verifier.cc
src/compiler/x64/code-generator-x64.cc
src/compiler/x64/instruction-codes-x64.h
src/compiler/x64/instruction-selector-x64.cc
src/compiler/x87/instruction-selector-x87.cc
test/cctest/compiler/test-run-machops.cc

index aa59f2cbb76e9258afe88ce15f40cd9ce77172e7..d2c9e7727391ff70eaeb7e56025d3205aef68de6 100644 (file)
@@ -925,6 +925,19 @@ void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  VisitRR(this, kArmVmovLowU32F64, node);
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  ArmOperandGenerator g(this);
+  Emit(kArmVmovLowF64U32, g.DefineAsRegister(node),
+       ImmediateOperand(ImmediateOperand::INLINE, 0),
+       g.UseRegister(node->InputAt(0)));
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   ArmOperandGenerator g(this);
   Float32BinopMatcher m(node);
index fa3a04e55f285aee9d658f2dedeeff16457d6d27..b4a60046038588caf7b0bd350d76da8e0270e1e7 100644 (file)
@@ -886,10 +886,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       __ Fmov(i.OutputFloat64Register(), tmp);
       break;
     }
-    case kArm64Float64MoveU64: {
+    case kArm64Float64MoveU64:
       __ Fmov(i.OutputFloat64Register(), i.InputRegister(0));
       break;
-    }
+    case kArm64U64MoveFloat64:
+      __ Fmov(i.OutputRegister(), i.InputDoubleRegister(0));
+      break;
     case kArm64Ldrb:
       __ Ldrb(i.OutputRegister(), i.MemoryOperand());
       break;
index f76854611ee8b467cab7974ded78d043d2732662..c2a52af7cbbb5281331c310cd5a77a877739af4e 100644 (file)
@@ -115,6 +115,7 @@ namespace compiler {
   V(Arm64Float64InsertLowWord32)   \
   V(Arm64Float64InsertHighWord32)  \
   V(Arm64Float64MoveU64)           \
+  V(Arm64U64MoveFloat64)           \
   V(Arm64LdrS)                     \
   V(Arm64StrS)                     \
   V(Arm64LdrD)                     \
index fbc7df27e3157e33347a507d9769b86245865c5a..c24cecf4605dc68b091358c0d217e5720604936a 100644 (file)
@@ -1276,6 +1276,26 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  VisitRR(this, kArm64Float64ExtractLowWord32, node);
+}
+
+
+void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
+  VisitRR(this, kArm64U64MoveFloat64, node);
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  VisitRR(this, kArm64Float64MoveU64, node);
+}
+
+
+void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
+  VisitRR(this, kArm64Float64MoveU64, node);
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   VisitRRR(this, kArm64Float32Add, node);
 }
index c21cc2df2497ecac875e6105c90f76d46cff510b..e9b3a9949a28cf00ea484b84708e5e8131d574ab 100644 (file)
@@ -840,6 +840,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         __ movss(operand, i.InputDoubleRegister(index));
       }
       break;
+    case kIA32BitcastFI:
+      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+        __ mov(i.OutputRegister(), i.InputOperand(0));
+      } else {
+        __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
+      }
+      break;
+    case kIA32BitcastIF:
+      if (instr->InputAt(0)->IsRegister()) {
+        __ movd(i.OutputDoubleRegister(), i.InputRegister(0));
+      } else {
+        __ movss(i.OutputDoubleRegister(), i.InputOperand(0));
+      }
+      break;
     case kIA32Lea: {
       AddressingMode mode = AddressingModeField::decode(instr->opcode());
       // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
index 4002a6776df6b08a1ad64c238a8682fc95cd1002..2119947e942447cc04cb37c129f68e7beb377e17 100644 (file)
@@ -89,6 +89,8 @@ namespace compiler {
   V(IA32Movl)                      \
   V(IA32Movss)                     \
   V(IA32Movsd)                     \
+  V(IA32BitcastFI)                 \
+  V(IA32BitcastIF)                 \
   V(IA32Lea)                       \
   V(IA32Push)                      \
   V(IA32Poke)                      \
index 9faf5ebcd87e97d075f61b369157c011eb08beaf..792d1d5a47e044bdcba913d094e0b429001c2516 100644 (file)
@@ -687,6 +687,18 @@ void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  IA32OperandGenerator g(this);
+  Emit(kIA32BitcastFI, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  IA32OperandGenerator g(this);
+  Emit(kIA32BitcastIF, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   VisitRROFloat(this, node, kAVXFloat32Add, kSSEFloat32Add);
 }
index 0efdd065551fefc346ebaf3240852de82fbf97cb..7200bf0e7a210e11016ff6e50e42a73bcd32710b 100644 (file)
@@ -699,6 +699,14 @@ void InstructionSelector::VisitNode(Node* node) {
       return MarkAsWord32(node), VisitTruncateFloat64ToInt32(node);
     case IrOpcode::kTruncateInt64ToInt32:
       return MarkAsWord32(node), VisitTruncateInt64ToInt32(node);
+    case IrOpcode::kBitcastFloat32ToInt32:
+      return MarkAsWord32(node), VisitBitcastFloat32ToInt32(node);
+    case IrOpcode::kBitcastFloat64ToInt64:
+      return MarkAsWord64(node), VisitBitcastFloat64ToInt64(node);
+    case IrOpcode::kBitcastInt32ToFloat32:
+      return MarkAsFloat32(node), VisitBitcastInt32ToFloat32(node);
+    case IrOpcode::kBitcastInt64ToFloat64:
+      return MarkAsFloat64(node), VisitBitcastInt64ToFloat64(node);
     case IrOpcode::kFloat32Add:
       return MarkAsFloat32(node), VisitFloat32Add(node);
     case IrOpcode::kFloat32Sub:
@@ -904,6 +912,16 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
   UNIMPLEMENTED();
 }
 
+
+void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
+  UNIMPLEMENTED();
+}
+
+
+void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
+  UNIMPLEMENTED();
+}
+
 #endif  // V8_TARGET_ARCH_32_BIT
 
 
index 6f5b3402f108f88d5b72a3ab9812154a795985a2..38bb056157d0b2d8ce393ee7cd007342f58aada5 100644 (file)
@@ -136,6 +136,10 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
   V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1)                   \
   V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1)               \
   V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1)                   \
+  V(BitcastFloat32ToInt32, Operator::kNoProperties, 1, 0, 1)                  \
+  V(BitcastFloat64ToInt64, Operator::kNoProperties, 1, 0, 1)                  \
+  V(BitcastInt32ToFloat32, Operator::kNoProperties, 1, 0, 1)                  \
+  V(BitcastInt64ToFloat64, Operator::kNoProperties, 1, 0, 1)                  \
   V(Float32Abs, Operator::kNoProperties, 1, 0, 1)                             \
   V(Float32Add, Operator::kCommutative, 2, 0, 1)                              \
   V(Float32Sub, Operator::kNoProperties, 2, 0, 1)                             \
index 9eaf640cd9db62b8ee3d94a449b661d8e1fe8eed..27abfb4accca6e52ecbfe5c481fe82256a2d8402 100644 (file)
@@ -195,6 +195,13 @@ class MachineOperatorBuilder final : public ZoneObject {
   const Operator* TruncateFloat64ToInt32(TruncationMode);
   const Operator* TruncateInt64ToInt32();
 
+  // These operators reinterpret the bits of a floating point number as an
+  // integer and vice versa.
+  const Operator* BitcastFloat32ToInt32();
+  const Operator* BitcastFloat64ToInt64();
+  const Operator* BitcastInt32ToFloat32();
+  const Operator* BitcastInt64ToFloat64();
+
   // Floating point operators always operate with IEEE 754 round-to-nearest
   // (single-precision).
   const Operator* Float32Add();
index 8f2f6b212892d302eaa9bffd65a93d2877fd20e1..3c4b378553e69a9e66060fcff69dfaafb2971062 100644 (file)
@@ -402,6 +402,19 @@ void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  VisitRR(this, kMipsFloat64ExtractLowWord32, node);
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  MipsOperandGenerator g(this);
+  Emit(kMipsFloat64InsertLowWord32, g.DefineAsRegister(node),
+       ImmediateOperand(ImmediateOperand::INLINE, 0),
+       g.UseRegister(node->InputAt(0)));
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   VisitRRR(this, kMipsAddS, node);
 }
index debca20ca31bfe83b69c33237f5ccd9b1f99caf3..053434eec9a916f4e9eb287ffbb712002d70fc85 100644 (file)
@@ -799,6 +799,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       __ Trunc_uw_d(i.InputDoubleRegister(0), i.OutputRegister(), scratch);
       break;
     }
+    case kMips64BitcastDL:
+      __ dmfc1(i.OutputRegister(), i.InputDoubleRegister(0));
+      break;
+    case kMips64BitcastLD:
+      __ dmtc1(i.InputRegister(0), i.OutputDoubleRegister());
+      break;
     case kMips64Float64ExtractLowWord32:
       __ FmoveLow(i.OutputRegister(), i.InputDoubleRegister(0));
       break;
index ce95ad4e374afe0272f0125f72548ef59c7cd7b8..38e4c46485ecbca3c655aa4e5f82261e8dc5aa07 100644 (file)
@@ -88,6 +88,8 @@ namespace compiler {
   V(Mips64Swc1)                     \
   V(Mips64Ldc1)                     \
   V(Mips64Sdc1)                     \
+  V(Mips64BitcastDL)                \
+  V(Mips64BitcastLD)                \
   V(Mips64Float64ExtractLowWord32)  \
   V(Mips64Float64ExtractHighWord32) \
   V(Mips64Float64InsertLowWord32)   \
index 09c3411e196b93146805e5d0e485ed90728eae7e..d20c1c72f66a162b231b09f16bc07a78d9b6be50 100644 (file)
@@ -578,6 +578,29 @@ void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  VisitRR(this, kMips64Float64ExtractLowWord32, node);
+}
+
+
+void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
+  VisitRR(this, kMips64BitcastDL, node);
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  Mips64OperandGenerator g(this);
+  Emit(kMips64Float64InsertLowWord32, g.DefineAsRegister(node),
+       ImmediateOperand(ImmediateOperand::INLINE, 0),
+       g.UseRegister(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
+  VisitRR(this, kMips64BitcastLD, node);
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   VisitRRR(this, kMips64AddS, node);
 }
@@ -1331,16 +1354,12 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
 
 
 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
-  Mips64OperandGenerator g(this);
-  Emit(kMips64Float64ExtractLowWord32, g.DefineAsRegister(node),
-       g.UseRegister(node->InputAt(0)));
+  VisitRR(this, kMips64Float64ExtractLowWord32, node);
 }
 
 
 void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
-  Mips64OperandGenerator g(this);
-  Emit(kMips64Float64ExtractHighWord32, g.DefineAsRegister(node),
-       g.UseRegister(node->InputAt(0)));
+  VisitRR(this, kMips64Float64ExtractHighWord32, node);
 }
 
 
index 2b49b63c9039514cfdf4e5cc4c094ec5cfb46627..33e17f6dd0d1eefc6c9b3d42ef9135dfea6b05ab 100644 (file)
   V(TruncateFloat64ToFloat32)   \
   V(TruncateFloat64ToInt32)     \
   V(TruncateInt64ToInt32)       \
+  V(BitcastFloat32ToInt32)      \
+  V(BitcastFloat64ToInt64)      \
+  V(BitcastInt32ToFloat32)      \
+  V(BitcastInt64ToFloat64)      \
   V(Float32Add)                 \
   V(Float32Sub)                 \
   V(Float32Mul)                 \
index 3d99b06eb91efb400042fb2f456b1830ab6718f2..47d4f2b7dc6769e33ac5bbd018aabeb558f1014c 100644 (file)
@@ -1076,6 +1076,14 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
 #endif
       DCHECK_EQ(LeaveRC, i.OutputRCBit());
       break;
+#if V8_TARGET_ARCH_PPC64
+    case kPPC_BitcastDL:
+      __ mffprd(i.OutputRegister(), i.InputDoubleRegister(0));
+      break;
+    case kPPC_BitcastLD:
+      __ mtfprd(i.OutputDoubleRegister(), i.InputRegister(0));
+      break;
+#endif
     case kPPC_LoadWordU8:
       ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
       break;
index c817ef2a92df2b178ca4f80b692e311baa91c53b..1cce3806f2304970dae75d8f2fad4049f6d4c13f 100644 (file)
@@ -86,6 +86,8 @@ namespace compiler {
   V(PPC_DoubleInsertLowWord32)     \
   V(PPC_DoubleInsertHighWord32)    \
   V(PPC_DoubleConstruct)           \
+  V(PPC_BitcastDL)                 \
+  V(PPC_BitcastLD)                 \
   V(PPC_LoadWordS8)                \
   V(PPC_LoadWordU8)                \
   V(PPC_LoadWordS16)               \
index d8543a377dacadaadc60fdd444401f4b5a90bcfc..5df5b781889efec325c6667aa27a44545da69546 100644 (file)
@@ -910,6 +910,33 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
 #endif
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  VisitRR(this, kPPC_DoubleExtractLowWord32, node);
+}
+
+
+#if V8_TARGET_ARCH_PPC64
+void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
+  VisitRR(this, kPPC_BitcastDL, node);
+}
+#endif
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  PPCOperandGenerator g(this);
+  Emit(kPPC_DoubleInsertLowWord32, g.DefineAsRegister(node),
+       ImmediateOperand(ImmediateOperand::INLINE, 0),
+       g.UseRegister(node->InputAt(0)));
+}
+
+
+#if V8_TARGET_ARCH_PPC64
+void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
+  VisitRR(this, kPPC_BitcastLD, node);
+}
+#endif
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   VisitRRR(this, kPPC_AddDouble, node);
 }
index 7329af0598232a8560c44e9fe272c4b765bda17c..03023b42a00ca695ade4e46a79bae467df1144c1 100644 (file)
@@ -433,6 +433,18 @@ class RawMachineAssembler {
   Node* TruncateInt64ToInt32(Node* a) {
     return NewNode(machine()->TruncateInt64ToInt32(), a);
   }
+  Node* BitcastFloat32ToInt32(Node* a) {
+    return NewNode(machine()->BitcastFloat32ToInt32(), a);
+  }
+  Node* BitcastFloat64ToInt64(Node* a) {
+    return NewNode(machine()->BitcastFloat64ToInt64(), a);
+  }
+  Node* BitcastInt32ToFloat32(Node* a) {
+    return NewNode(machine()->BitcastInt32ToFloat32(), a);
+  }
+  Node* BitcastInt64ToFloat64(Node* a) {
+    return NewNode(machine()->BitcastInt64ToFloat64(), a);
+  }
   Node* Float64RoundDown(Node* a) {
     return NewNode(machine()->Float64RoundDown().op(), a);
   }
index a6a9e67948818b24c377b755577dc054a066816f..4707aef1e519cafcb5de1d29375ca4f5be8e9e77 100644 (file)
@@ -1865,6 +1865,26 @@ Type* Typer::Visitor::TypeTruncateInt64ToInt32(Node* node) {
 }
 
 
+Type* Typer::Visitor::TypeBitcastFloat32ToInt32(Node* node) {
+  return Type::Number();
+}
+
+
+Type* Typer::Visitor::TypeBitcastFloat64ToInt64(Node* node) {
+  return Type::Number();
+}
+
+
+Type* Typer::Visitor::TypeBitcastInt32ToFloat32(Node* node) {
+  return Type::Number();
+}
+
+
+Type* Typer::Visitor::TypeBitcastInt64ToFloat64(Node* node) {
+  return Type::Number();
+}
+
+
 Type* Typer::Visitor::TypeFloat32Add(Node* node) { return Type::Number(); }
 
 
index 8f12b5fc409ce4f642dee41f38a8ba5dba6d0d3a..20a0d76248100473cbee7c83e55e47ada12541c3 100644 (file)
@@ -870,6 +870,10 @@ void Verifier::Visitor::Check(Node* node) {
     case IrOpcode::kTruncateInt64ToInt32:
     case IrOpcode::kTruncateFloat64ToFloat32:
     case IrOpcode::kTruncateFloat64ToInt32:
+    case IrOpcode::kBitcastFloat32ToInt32:
+    case IrOpcode::kBitcastFloat64ToInt64:
+    case IrOpcode::kBitcastInt32ToFloat32:
+    case IrOpcode::kBitcastInt64ToFloat64:
     case IrOpcode::kChangeInt32ToInt64:
     case IrOpcode::kChangeUint32ToUint64:
     case IrOpcode::kChangeInt32ToFloat64:
index 56260804806fd904a506bf5c776b2ee7005cf200..06befa83f4c53144037a45d8f77728d1055e4594 100644 (file)
@@ -1171,6 +1171,34 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         __ movsd(operand, i.InputDoubleRegister(index));
       }
       break;
+    case kX64BitcastFI:
+      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+        __ movl(i.OutputRegister(), i.InputOperand(0));
+      } else {
+        __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
+      }
+      break;
+    case kX64BitcastDL:
+      if (instr->InputAt(0)->IsDoubleStackSlot()) {
+        __ movq(i.OutputRegister(), i.InputOperand(0));
+      } else {
+        __ movq(i.OutputRegister(), i.InputDoubleRegister(0));
+      }
+      break;
+    case kX64BitcastIF:
+      if (instr->InputAt(0)->IsRegister()) {
+        __ movd(i.OutputDoubleRegister(), i.InputRegister(0));
+      } else {
+        __ movss(i.OutputDoubleRegister(), i.InputOperand(0));
+      }
+      break;
+    case kX64BitcastLD:
+      if (instr->InputAt(0)->IsRegister()) {
+        __ movq(i.OutputDoubleRegister(), i.InputRegister(0));
+      } else {
+        __ movsd(i.OutputDoubleRegister(), i.InputOperand(0));
+      }
+      break;
     case kX64Lea32: {
       AddressingMode mode = AddressingModeField::decode(instr->opcode());
       // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
index 2e107299545c13f7ee67991471dbb53743d4de3c..7d3b434d158ad93637ea5eaf1cdb151790b54ba3 100644 (file)
@@ -109,6 +109,10 @@ namespace compiler {
   V(X64Movq)                       \
   V(X64Movsd)                      \
   V(X64Movss)                      \
+  V(X64BitcastFI)                  \
+  V(X64BitcastDL)                  \
+  V(X64BitcastIF)                  \
+  V(X64BitcastLD)                  \
   V(X64Lea32)                      \
   V(X64Lea)                        \
   V(X64Dec32)                      \
index fa63138f2799841c5af49c2ac93a7493541881cb..516a9a7691ca0d7c2ba9c33a47857bc07dec48e3 100644 (file)
@@ -906,6 +906,30 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  X64OperandGenerator g(this);
+  Emit(kX64BitcastFI, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
+  X64OperandGenerator g(this);
+  Emit(kX64BitcastDL, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  X64OperandGenerator g(this);
+  Emit(kX64BitcastIF, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
+  X64OperandGenerator g(this);
+  Emit(kX64BitcastLD, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   VisitFloatBinop(this, node, kAVXFloat32Add, kSSEFloat32Add);
 }
index fbf0ed9515a0973d2e6b40da12dcf042ab746d77..2051b147bb099fee90f57d33e871fefcf74f0c72 100644 (file)
@@ -664,6 +664,16 @@ void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
 }
 
 
+void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
+  UNIMPLEMENTED();
+}
+
+
+void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
+  UNIMPLEMENTED();
+}
+
+
 void InstructionSelector::VisitFloat32Add(Node* node) {
   X87OperandGenerator g(this);
   Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0)));
index 2206181f19013cb6d288a84dc866a553e1d506f3..a12c383da519421b8f64a4f3316fcb9f7db5901f 100644 (file)
@@ -5322,4 +5322,69 @@ TEST(RunCheckedStoreInt64) {
   CHECK_EQ(write, buffer[0]);
   CHECK_EQ(write, buffer[1]);
 }
+
+
+TEST(RunBitcastInt64ToFloat64) {
+  // TODO(titzer): run int64 tests on all platforms when supported.
+  int64_t input = 1;
+  double output = 0.0;
+  RawMachineAssemblerTester<int32_t> m;
+  m.StoreToPointer(
+      &output, kMachFloat64,
+      m.BitcastInt64ToFloat64(m.LoadFromPointer(&input, kMachInt64)));
+  m.Return(m.Int32Constant(11));
+  FOR_INT32_INPUTS(i) {
+    input = static_cast<int64_t>(*i) * 14444;
+    CHECK_EQ(11, m.Call());
+    double expected = bit_cast<double>(input);
+    CHECK_EQ(bit_cast<int64_t>(expected), bit_cast<int64_t>(output));
+  }
+}
+
+
+TEST(RunBitcastFloat64ToInt64) {
+  // TODO(titzer): run int64 tests on all platforms when supported.
+  double input = 0;
+  int64_t output = 0;
+  RawMachineAssemblerTester<int32_t> m;
+  m.StoreToPointer(
+      &output, kMachInt64,
+      m.BitcastFloat64ToInt64(m.LoadFromPointer(&input, kMachFloat64)));
+  m.Return(m.Int32Constant(11));
+  FOR_FLOAT64_INPUTS(i) {
+    input = *i;
+    CHECK_EQ(11, m.Call());
+    double expected = bit_cast<int64_t>(input);
+    CHECK_EQ(expected, output);
+  }
+}
 #endif
+
+
+TEST(RunBitcastFloat32ToInt32) {
+  float input = 32.25;
+  RawMachineAssemblerTester<int32_t> m;
+  m.Return(m.BitcastFloat32ToInt32(m.LoadFromPointer(&input, kMachFloat32)));
+  FOR_FLOAT32_INPUTS(i) {
+    input = *i;
+    int32_t expected = bit_cast<int32_t>(input);
+    CHECK_EQ(expected, m.Call());
+  }
+}
+
+
+TEST(RunBitcastInt32ToFloat32) {
+  int32_t input = 1;
+  float output = 0.0;
+  RawMachineAssemblerTester<int32_t> m;
+  m.StoreToPointer(
+      &output, kMachFloat32,
+      m.BitcastInt32ToFloat32(m.LoadFromPointer(&input, kMachInt32)));
+  m.Return(m.Int32Constant(11));
+  FOR_INT32_INPUTS(i) {
+    input = *i;
+    CHECK_EQ(11, m.Call());
+    float expected = bit_cast<float>(input);
+    CHECK_EQ(bit_cast<int32_t>(expected), bit_cast<int32_t>(output));
+  }
+}