[turbofan] Add backend support for load/store float32 values.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Tue, 26 Aug 2014 08:29:12 +0000 (08:29 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Tue, 26 Aug 2014 08:29:12 +0000 (08:29 +0000)
This is the bare minimum required to support typed arrays. Support for
working with float32 values will be added based on this.

TEST=compiler-unittests,cctest
R=svenpanne@chromium.org

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

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

23 files changed:
src/compiler/arm/code-generator-arm.cc
src/compiler/arm/instruction-codes-arm.h
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-type.cc
src/compiler/machine-type.h
src/compiler/simplified-lowering.cc
src/compiler/x64/code-generator-x64.cc
src/compiler/x64/instruction-codes-x64.h
src/compiler/x64/instruction-selector-x64.cc
test/cctest/compiler/test-run-machops.cc
test/compiler-unittests/arm/instruction-selector-arm-unittest.cc
test/compiler-unittests/arm64/instruction-selector-arm64-unittest.cc
test/compiler-unittests/ia32/instruction-selector-ia32-unittest.cc
test/compiler-unittests/instruction-selector-unittest.cc
test/compiler-unittests/instruction-selector-unittest.h
test/compiler-unittests/x64/instruction-selector-x64-unittest.cc

index a8678bd37ef8a856834b94b1fb54de25a325a036..169d7005b21ce57e03a3f1413282b432f9cb236e 100644 (file)
@@ -415,6 +415,22 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       DCHECK_EQ(LeaveCC, i.OutputSBit());
       break;
     }
+    case kArmVldr32: {
+      SwVfpRegister scratch = kScratchDoubleReg.low();
+      __ vldr(scratch, i.InputOffset());
+      __ vcvt_f64_f32(i.OutputDoubleRegister(), scratch);
+      DCHECK_EQ(LeaveCC, i.OutputSBit());
+      break;
+    }
+    case kArmVstr32: {
+      int index = 0;
+      SwVfpRegister scratch = kScratchDoubleReg.low();
+      MemOperand operand = i.InputOffset(&index);
+      __ vcvt_f32_f64(scratch, i.InputDoubleRegister(index));
+      __ vstr(scratch, operand);
+      DCHECK_EQ(LeaveCC, i.OutputSBit());
+      break;
+    }
     case kArmVldr64:
       __ vldr(i.OutputDoubleRegister(), i.InputOffset());
       DCHECK_EQ(LeaveCC, i.OutputSBit());
index ab86ce4d17beef57d944bed2ab3f48b52d0b5185..5445d178ab7248a1bfc0f801ca4dbdf0f3718be0 100644 (file)
@@ -50,6 +50,8 @@ namespace compiler {
   V(ArmVcvtF64U32)                 \
   V(ArmVcvtS32F64)                 \
   V(ArmVcvtU32F64)                 \
+  V(ArmVldr32)                     \
+  V(ArmVstr32)                     \
   V(ArmVldr64)                     \
   V(ArmVstr64)                     \
   V(ArmLdrb)                       \
index 6ec86bd6413d9c3e3ff04b6d5877e97218f4a0f3..85969716015f4b3e4bfef64478ab53256823c41b 100644 (file)
@@ -55,6 +55,8 @@ class ArmOperandGenerator V8_FINAL : public OperandGenerator {
       case kArmRsb:
         return ImmediateFitsAddrMode1Instruction(value);
 
+      case kArmVldr32:
+      case kArmVstr32:
       case kArmVldr64:
       case kArmVstr64:
         return value >= -1020 && value <= 1020 && (value % 4) == 0;
@@ -294,12 +296,15 @@ void InstructionSelector::VisitLoad(Node* node) {
   Node* base = node->InputAt(0);
   Node* index = node->InputAt(1);
 
-  InstructionOperand* result = rep == kRepFloat64
+  InstructionOperand* result = (rep == kRepFloat32 || rep == kRepFloat64)
                                    ? g.DefineAsDoubleRegister(node)
                                    : g.DefineAsRegister(node);
 
   ArchOpcode opcode;
   switch (rep) {
+    case kRepFloat32:
+      opcode = kArmVldr32;
+      break;
     case kRepFloat64:
       opcode = kArmVldr64;
       break;
@@ -349,11 +354,15 @@ void InstructionSelector::VisitStore(Node* node) {
     return;
   }
   DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind);
-  InstructionOperand* val =
-      rep == kRepFloat64 ? g.UseDoubleRegister(value) : g.UseRegister(value);
+  InstructionOperand* val = (rep == kRepFloat32 || rep == kRepFloat64)
+                                ? g.UseDoubleRegister(value)
+                                : g.UseRegister(value);
 
   ArchOpcode opcode;
   switch (rep) {
+    case kRepFloat32:
+      opcode = kArmVstr32;
+      break;
     case kRepFloat64:
       opcode = kArmVstr64;
       break;
index baacc854c0dde758833bfb2be8190f8fd99d9d73..edd023dc1838d8cf87af8c08b1cf1c9f15a0255a 100644 (file)
@@ -426,6 +426,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
     case kArm64Str:
       __ Str(i.InputRegister(2), i.MemoryOperand());
       break;
+    case kArm64LdrS: {
+      UseScratchRegisterScope scope(masm());
+      FPRegister scratch = scope.AcquireS();
+      __ Ldr(scratch, i.MemoryOperand());
+      __ Fcvt(i.OutputDoubleRegister(), scratch);
+      break;
+    }
+    case kArm64StrS: {
+      UseScratchRegisterScope scope(masm());
+      FPRegister scratch = scope.AcquireS();
+      __ Fcvt(scratch, i.InputDoubleRegister(2));
+      __ Str(scratch, i.MemoryOperand());
+      break;
+    }
     case kArm64LdrD:
       __ Ldr(i.OutputDoubleRegister(), i.MemoryOperand());
       break;
index bce47f85acedcdb473e0b424a9547cdb918b8ed7..f0231557045032e35f3730dd999b042a93ee9555 100644 (file)
@@ -68,6 +68,8 @@ namespace compiler {
   V(Arm64Float64ToUint32)          \
   V(Arm64Int32ToFloat64)           \
   V(Arm64Uint32ToFloat64)          \
+  V(Arm64LdrS)                     \
+  V(Arm64StrS)                     \
   V(Arm64LdrD)                     \
   V(Arm64StrD)                     \
   V(Arm64Ldrb)                     \
index 410105c1880b3f0c97534d96c625627993202fd9..46cb7feb5aa0bf66ae4d7a67a41dab44887f96dc 100644 (file)
@@ -148,13 +148,16 @@ void InstructionSelector::VisitLoad(Node* node) {
   Node* base = node->InputAt(0);
   Node* index = node->InputAt(1);
 
-  InstructionOperand* result = rep == kRepFloat64
+  InstructionOperand* result = (rep == kRepFloat32 || rep == kRepFloat64)
                                    ? g.DefineAsDoubleRegister(node)
                                    : g.DefineAsRegister(node);
 
   ArchOpcode opcode;
   // TODO(titzer): signed/unsigned small loads
   switch (rep) {
+    case kRepFloat32:
+      opcode = kArm64LdrS;
+      break;
     case kRepFloat64:
       opcode = kArm64LdrD;
       break;
@@ -207,13 +210,16 @@ void InstructionSelector::VisitStore(Node* node) {
   }
   DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind);
   InstructionOperand* val;
-  if (rep == kRepFloat64) {
+  if (rep == kRepFloat32 || rep == kRepFloat64) {
     val = g.UseDoubleRegister(value);
   } else {
     val = g.UseRegister(value);
   }
   ArchOpcode opcode;
   switch (rep) {
+    case kRepFloat32:
+      opcode = kArm64StrS;
+      break;
     case kRepFloat64:
       opcode = kArm64StrD;
       break;
index 19b4ddf7f287c56ceb56ec955aed82d277a4756b..ea641f77421bb1e3525736088b6dbe02adbcdc2b 100644 (file)
@@ -389,6 +389,17 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         __ movsd(operand, i.InputDoubleRegister(index));
       }
       break;
+    case kIA32Movss:
+      if (instr->HasOutput()) {
+        __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
+        __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
+      } else {
+        int index = 0;
+        Operand operand = i.MemoryOperand(&index);
+        __ cvtsd2ss(xmm0, i.InputDoubleRegister(index));
+        __ movss(operand, xmm0);
+      }
+      break;
     case kIA32StoreWriteBarrier: {
       Register object = i.InputRegister(0);
       Register index = i.InputRegister(1);
index 9ddff374d8f0f937f45b03520b489f848da58e06..50dc051b4bc1eb2ecc66415baa27080eef225c53 100644 (file)
@@ -50,6 +50,7 @@ namespace compiler {
   V(IA32Movzxwl)                   \
   V(IA32Movw)                      \
   V(IA32Movl)                      \
+  V(IA32Movss)                     \
   V(IA32Movsd)                     \
   V(IA32StoreWriteBarrier)
 
index 03f35fe306a86ec27cdc4f33891338de87c03bca..7de35fa8eb8511710b0607434990b5364a0e667f 100644 (file)
@@ -47,12 +47,15 @@ void InstructionSelector::VisitLoad(Node* node) {
   Node* base = node->InputAt(0);
   Node* index = node->InputAt(1);
 
-  InstructionOperand* output = rep == kRepFloat64
+  InstructionOperand* output = (rep == kRepFloat32 || rep == kRepFloat64)
                                    ? g.DefineAsDoubleRegister(node)
                                    : g.DefineAsRegister(node);
   ArchOpcode opcode;
   // TODO(titzer): signed/unsigned small loads
   switch (rep) {
+    case kRepFloat32:
+      opcode = kIA32Movss;
+      break;
     case kRepFloat64:
       opcode = kIA32Movsd;
       break;
@@ -111,7 +114,7 @@ void InstructionSelector::VisitStore(Node* node) {
   }
   DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind);
   InstructionOperand* val;
-  if (rep == kRepFloat64) {
+  if (rep == kRepFloat32 || rep == kRepFloat64) {
     val = g.UseDoubleRegister(value);
   } else {
     if (g.CanBeImmediate(value)) {
@@ -124,6 +127,9 @@ void InstructionSelector::VisitStore(Node* node) {
   }
   ArchOpcode opcode;
   switch (rep) {
+    case kRepFloat32:
+      opcode = kIA32Movss;
+      break;
     case kRepFloat64:
       opcode = kIA32Movsd;
       break;
index 143bd696311781bdda8666e5d614e324feba4738..e950b4a16ca5649dcc5caa5f307f868862c86c03 100644 (file)
@@ -244,8 +244,17 @@ void InstructionSelector::MarkAsReference(Node* node) {
 
 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) {
   DCHECK_NOT_NULL(node);
-  if (RepresentationOf(rep) == kRepFloat64) MarkAsDouble(node);
-  if (RepresentationOf(rep) == kRepTagged) MarkAsReference(node);
+  switch (RepresentationOf(rep)) {
+    case kRepFloat32:
+    case kRepFloat64:
+      MarkAsDouble(node);
+      break;
+    case kRepTagged:
+      MarkAsReference(node);
+      break;
+    default:
+      break;
+  }
 }
 
 
index b27727cb7a3b03c1f7bc4b559242533c9c119da0..94aa124e03e948b7d9d1793727640c42a8546aa2 100644 (file)
@@ -24,6 +24,7 @@ OStream& operator<<(OStream& os, const MachineType& type) {
   PRINT(kRepWord16);
   PRINT(kRepWord32);
   PRINT(kRepWord64);
+  PRINT(kRepFloat32);
   PRINT(kRepFloat64);
   PRINT(kRepTagged);
 
index 3b1b9bdcd8f508965cc527d404ff8dcc8b028122..ca37527cb941a6bb9d44b5395b866d3ce25b37a8 100644 (file)
@@ -23,17 +23,18 @@ enum MachineType {
   kRepWord16 = 1 << 2,
   kRepWord32 = 1 << 3,
   kRepWord64 = 1 << 4,
-  kRepFloat64 = 1 << 5,
-  kRepTagged = 1 << 6,
+  kRepFloat32 = 1 << 5,
+  kRepFloat64 = 1 << 6,
+  kRepTagged = 1 << 7,
 
   // Types.
-  kTypeBool = 1 << 7,
-  kTypeInt32 = 1 << 8,
-  kTypeUint32 = 1 << 9,
-  kTypeInt64 = 1 << 10,
-  kTypeUint64 = 1 << 11,
-  kTypeNumber = 1 << 12,
-  kTypeAny = 1 << 13
+  kTypeBool = 1 << 8,
+  kTypeInt32 = 1 << 9,
+  kTypeUint32 = 1 << 10,
+  kTypeInt64 = 1 << 11,
+  kTypeUint64 = 1 << 12,
+  kTypeNumber = 1 << 13,
+  kTypeAny = 1 << 14
 };
 
 OStream& operator<<(OStream& os, const MachineType& type);
@@ -42,13 +43,15 @@ typedef uint16_t MachineTypeUnion;
 
 // Globally useful machine types and constants.
 const MachineTypeUnion kRepMask = kRepBit | kRepWord8 | kRepWord16 |
-                                  kRepWord32 | kRepWord64 | kRepFloat64 |
-                                  kRepTagged;
+                                  kRepWord32 | kRepWord64 | kRepFloat32 |
+                                  kRepFloat64 | kRepTagged;
 const MachineTypeUnion kTypeMask = kTypeBool | kTypeInt32 | kTypeUint32 |
                                    kTypeInt64 | kTypeUint64 | kTypeNumber |
                                    kTypeAny;
 
 const MachineType kMachNone = static_cast<MachineType>(0);
+const MachineType kMachFloat32 =
+    static_cast<MachineType>(kRepFloat32 | kTypeNumber);
 const MachineType kMachFloat64 =
     static_cast<MachineType>(kRepFloat64 | kTypeNumber);
 const MachineType kMachInt8 = static_cast<MachineType>(kRepWord8 | kTypeInt32);
@@ -92,6 +95,7 @@ inline int ElementSizeOf(MachineType machine_type) {
     case kRepWord16:
       return 2;
     case kRepWord32:
+    case kRepFloat32:
       return 4;
     case kRepWord64:
     case kRepFloat64:
index 0ffbdcc192bdc021bc59942687c3c5c59d81a3c0..12f953fcef102bad5347699543302851246cd289 100644 (file)
@@ -54,10 +54,10 @@ class RepresentationSelector {
  public:
   // Information for each node tracked during the fixpoint.
   struct NodeInfo {
-    MachineTypeUnion use : 14;     // Union of all usages for the node.
+    MachineTypeUnion use : 15;     // Union of all usages for the node.
     bool queued : 1;           // Bookkeeping for the traversal.
     bool visited : 1;          // Bookkeeping for the traversal.
-    MachineTypeUnion output : 14;  // Output type of the node.
+    MachineTypeUnion output : 15;  // Output type of the node.
   };
 
   RepresentationSelector(JSGraph* jsgraph, Zone* zone,
index 950652546880ae8bb4c311ffcbc37a6c4344158a..5743cd71389c51bcb17a112e2bfa0b130cd38727 100644 (file)
@@ -514,15 +514,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       break;
     }
 
-    case kX64Movsd:
-      if (instr->HasOutput()) {
-        __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
-      } else {
-        int index = 0;
-        Operand operand = i.MemoryOperand(&index);
-        __ movsd(operand, i.InputDoubleRegister(index));
-      }
-      break;
     case kX64Movsxbl:
       __ movsxbl(i.OutputRegister(), i.MemoryOperand());
       break;
@@ -599,6 +590,26 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         }
       }
       break;
+    case kX64Movss:
+      if (instr->HasOutput()) {
+        __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
+        __ cvtss2sd(i.OutputDoubleRegister(), i.OutputDoubleRegister());
+      } else {
+        int index = 0;
+        Operand operand = i.MemoryOperand(&index);
+        __ cvtsd2ss(xmm0, i.InputDoubleRegister(index));
+        __ movss(operand, xmm0);
+      }
+      break;
+    case kX64Movsd:
+      if (instr->HasOutput()) {
+        __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
+      } else {
+        int index = 0;
+        Operand operand = i.MemoryOperand(&index);
+        __ movsd(operand, i.InputDoubleRegister(index));
+      }
+      break;
     case kX64StoreWriteBarrier: {
       Register object = i.InputRegister(0);
       Register index = i.InputRegister(1);
index b0a159557de6112ad404cc8d164b0dfac9bb30d0..fab1e70bd5fce5bc33577635bba6ddc055e8d417 100644 (file)
@@ -60,7 +60,6 @@ namespace compiler {
   V(SSEFloat64ToUint32)            \
   V(SSEInt32ToFloat64)             \
   V(SSEUint32ToFloat64)            \
-  V(X64Movsd)                      \
   V(X64Movsxbl)                    \
   V(X64Movzxbl)                    \
   V(X64Movb)                       \
@@ -70,6 +69,8 @@ namespace compiler {
   V(X64Movl)                       \
   V(X64Movsxlq)                    \
   V(X64Movq)                       \
+  V(X64Movsd)                      \
+  V(X64Movss)                      \
   V(X64StoreWriteBarrier)
 
 
index 138a63d7f7bdac4ece457b603a3bcbe8ecda2394..4a2bfe91a0d9493dac9ad7bea30eeb4c83858f75 100644 (file)
@@ -62,12 +62,15 @@ void InstructionSelector::VisitLoad(Node* node) {
   Node* base = node->InputAt(0);
   Node* index = node->InputAt(1);
 
-  InstructionOperand* output = rep == kRepFloat64
+  InstructionOperand* output = (rep == kRepFloat32 || rep == kRepFloat64)
                                    ? g.DefineAsDoubleRegister(node)
                                    : g.DefineAsRegister(node);
   ArchOpcode opcode;
   // TODO(titzer): signed/unsigned small loads
   switch (rep) {
+    case kRepFloat32:
+      opcode = kX64Movss;
+      break;
     case kRepFloat64:
       opcode = kX64Movsd;
       break;
@@ -125,7 +128,7 @@ void InstructionSelector::VisitStore(Node* node) {
   }
   DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind);
   InstructionOperand* val;
-  if (rep == kRepFloat64) {
+  if (rep == kRepFloat32 || rep == kRepFloat64) {
     val = g.UseDoubleRegister(value);
   } else {
     if (g.CanBeImmediate(value)) {
@@ -138,6 +141,9 @@ void InstructionSelector::VisitStore(Node* node) {
   }
   ArchOpcode opcode;
   switch (rep) {
+    case kRepFloat32:
+      opcode = kX64Movss;
+      break;
     case kRepFloat64:
       opcode = kX64Movsd;
       break;
index 9a80daf58842c90989a3e91b9c289f500628c4a2..0a67398bbf507271b7691991368790c908724831 100644 (file)
@@ -2751,6 +2751,7 @@ TEST(RunLoadStore) {
   RunLoadStore<int32_t>(kMachInt32);
   RunLoadStore<uint32_t>(kMachUint32);
   RunLoadStore<void*>(kMachAnyTagged);
+  RunLoadStore<float>(kMachFloat32);
   RunLoadStore<double>(kMachFloat64);
 }
 
index d8fbcf145d60e97d382f29c4079de8470560c18a..f3fa9c5e15a7e5318d0a9795b52059e18aa9154d 100644 (file)
@@ -1197,6 +1197,8 @@ struct MemoryAccess {
   MachineType type;
   ArchOpcode ldr_opcode;
   ArchOpcode str_opcode;
+  bool (InstructionSelectorTest::Stream::*val_predicate)(
+      const InstructionOperand*) const;
   const int32_t immediates[40];
 };
 
@@ -1212,36 +1214,49 @@ static const MemoryAccess kMemoryAccesses[] = {
     {kMachInt8,
      kArmLdrsb,
      kArmStrb,
+     &InstructionSelectorTest::Stream::IsInteger,
      {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89,
       -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109,
       115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}},
     {kMachUint8,
      kArmLdrb,
      kArmStrb,
+     &InstructionSelectorTest::Stream::IsInteger,
      {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434,
       -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28,
       39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}},
     {kMachInt16,
      kArmLdrsh,
      kArmStrh,
+     &InstructionSelectorTest::Stream::IsInteger,
      {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101,
       -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98,
       102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}},
     {kMachUint16,
      kArmLdrh,
      kArmStrh,
+     &InstructionSelectorTest::Stream::IsInteger,
      {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41,
       -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109,
       114, 116, 120, 138, 150, 161, 166, 172, 228, 255}},
     {kMachInt32,
      kArmLdr,
      kArmStr,
+     &InstructionSelectorTest::Stream::IsInteger,
      {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92,
       -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88,
       93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}},
+    {kMachFloat32,
+     kArmVldr32,
+     kArmVstr32,
+     &InstructionSelectorTest::Stream::IsDouble,
+     {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92,
+      -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20,
+      24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}},
     {kMachFloat64,
      kArmVldr64,
      kArmVstr64,
+     &InstructionSelectorTest::Stream::IsDouble,
      {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104,
       -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100,
       108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}};
@@ -1262,7 +1277,8 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) {
   EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode());
   EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode());
   EXPECT_EQ(2U, s[0]->InputCount());
-  EXPECT_EQ(1U, s[0]->OutputCount());
+  ASSERT_EQ(1U, s[0]->OutputCount());
+  EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
 }
 
 
@@ -1278,7 +1294,8 @@ TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) {
     ASSERT_EQ(2U, s[0]->InputCount());
     ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
     EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1)));
-    EXPECT_EQ(1U, s[0]->OutputCount());
+    ASSERT_EQ(1U, s[0]->OutputCount());
+    EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output()));
   }
 }
 
index 109986c4b5fa63808e50015b08bc166cae01a115..2e894719769a83c35d93cfb88f480ec000501be1 100644 (file)
@@ -330,6 +330,7 @@ static const MemoryAccess kMemoryAccesses[] = {
     {kMachUint32, kArm64LdrW, kArm64StrW},
     {kMachInt64, kArm64Ldr, kArm64Str},
     {kMachUint64, kArm64Ldr, kArm64Str},
+    {kMachFloat32, kArm64LdrS, kArm64StrS},
     {kMachFloat64, kArm64LdrD, kArm64StrD}};
 
 
index bab8f9495b7610d0f00a5af633535c1d00dcb9df..8d59496f7e7394926c9be072a75e6e103590053e 100644 (file)
@@ -100,6 +100,7 @@ static const MemoryAccess kMemoryAccesses[] = {
     {kMachUint16, kIA32Movzxwl, kIA32Movw},
     {kMachInt32, kIA32Movl, kIA32Movl},
     {kMachUint32, kIA32Movl, kIA32Movl},
+    {kMachFloat32, kIA32Movss, kIA32Movss},
     {kMachFloat64, kIA32Movsd, kIA32Movsd}};
 
 }  // namespace
index 27241898a7beaa013a666d00e4d5d2189f835fbb..e53be7ede1bcfbd44ba18e7978c5d16d369c0efc 100644 (file)
@@ -186,18 +186,15 @@ TARGET_TEST_P(InstructionSelectorFinishTest, Parameter) {
   EXPECT_EQ(kArchNop, s[0]->arch_opcode());
   ASSERT_EQ(1U, s[0]->OutputCount());
   ASSERT_TRUE(s[0]->Output()->IsUnallocated());
-  EXPECT_EQ(param->id(),
-            UnallocatedOperand::cast(s[0]->Output())->virtual_register());
+  EXPECT_EQ(param->id(), s.ToVreg(s[0]->Output()));
   EXPECT_EQ(kArchNop, s[1]->arch_opcode());
   ASSERT_EQ(1U, s[1]->InputCount());
   ASSERT_TRUE(s[1]->InputAt(0)->IsUnallocated());
-  EXPECT_EQ(param->id(),
-            UnallocatedOperand::cast(s[1]->InputAt(0))->virtual_register());
+  EXPECT_EQ(param->id(), s.ToVreg(s[1]->InputAt(0)));
   ASSERT_EQ(1U, s[1]->OutputCount());
   ASSERT_TRUE(s[1]->Output()->IsUnallocated());
   EXPECT_TRUE(UnallocatedOperand::cast(s[1]->Output())->HasSameAsInputPolicy());
-  EXPECT_EQ(finish->id(),
-            UnallocatedOperand::cast(s[1]->Output())->virtual_register());
+  EXPECT_EQ(finish->id(), s.ToVreg(s[1]->Output()));
 }
 
 
index 42aac9f44ebaba619bc03f7c610d207439fa6363..127cc1d479df10ccf367f31094908f8717ff9a61 100644 (file)
@@ -24,7 +24,6 @@ class InstructionSelectorTest : public CompilerTest {
 
   base::RandomNumberGenerator* rng() { return &rng_; }
 
- protected:
   class Stream;
 
   enum StreamBuilderMode { kAllInstructions, kTargetInstructions };
@@ -116,10 +115,23 @@ class InstructionSelectorTest : public CompilerTest {
       return instructions_[index];
     }
 
+    bool IsDouble(const InstructionOperand* operand) const {
+      return IsDouble(ToVreg(operand));
+    }
     bool IsDouble(int virtual_register) const {
       return doubles_.find(virtual_register) != doubles_.end();
     }
 
+    bool IsInteger(const InstructionOperand* operand) const {
+      return IsInteger(ToVreg(operand));
+    }
+    bool IsInteger(int virtual_register) const {
+      return !IsDouble(virtual_register) && !IsReference(virtual_register);
+    }
+
+    bool IsReference(const InstructionOperand* operand) const {
+      return IsReference(ToVreg(operand));
+    }
     bool IsReference(int virtual_register) const {
       return references_.find(virtual_register) != references_.end();
     }
@@ -129,6 +141,7 @@ class InstructionSelectorTest : public CompilerTest {
     }
 
     int ToVreg(const InstructionOperand* operand) const {
+      if (operand->IsConstant()) return operand->index();
       EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
       return UnallocatedOperand::cast(operand)->virtual_register();
     }
index 2d815a364a85154c805c016c8dc582c1f243f404..19c517326b862b8994d52b61595d5daeb9dc3444 100644 (file)
@@ -67,6 +67,7 @@ static const MemoryAccess kMemoryAccesses[] = {
     {kMachUint32, kX64Movl, kX64Movl},
     {kMachInt64, kX64Movq, kX64Movq},
     {kMachUint64, kX64Movq, kX64Movq},
+    {kMachFloat32, kX64Movss, kX64Movss},
     {kMachFloat64, kX64Movsd, kX64Movsd}};
 
 }  // namespace