int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
- // Skip a slot if for a double-width slot.
- if (kind == DOUBLE_REGISTERS) {
- spill_slot_count_++;
- spill_slot_count_ |= 1;
- num_double_slots_++;
+ switch (kind) {
+ case GENERAL_REGISTERS: return spill_slot_count_++;
+ case DOUBLE_REGISTERS: {
+ // Skip a slot if for a double-width slot.
+ spill_slot_count_++;
+ spill_slot_count_ |= 1;
+ num_double_slots_++;
+ return spill_slot_count_++;
+ }
+ case FLOAT32x4_REGISTERS:
+ case INT32x4_REGISTERS: {
+ // Skip three slots if for a quad-width slot.
+ spill_slot_count_ += 3;
+ num_double_slots_ += 2; // for dynamic frame alignment
+ return spill_slot_count_++;
+ }
+ default:
+ UNREACHABLE();
+ return -1;
}
- return spill_slot_count_++;
}
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
int index = GetNextSpillIndex(kind);
- if (kind == DOUBLE_REGISTERS) {
- return LDoubleStackSlot::Create(index, zone());
- } else {
- ASSERT(kind == GENERAL_REGISTERS);
- return LStackSlot::Create(index, zone());
+ switch (kind) {
+ case GENERAL_REGISTERS: return LStackSlot::Create(index, zone());
+ case DOUBLE_REGISTERS: return LDoubleStackSlot::Create(index, zone());
+ case FLOAT32x4_REGISTERS: return LFloat32x4StackSlot::Create(index, zone());
+ case INT32x4_REGISTERS: return LInt32x4StackSlot::Create(index, zone());
+ default:
+ UNREACHABLE();
+ return NULL;
}
}
if (current->OperandCount() == 0) {
instr = DefineAsRegister(new(zone()) LDummy());
} else {
+ ASSERT(!current->OperandAt(0)->IsControlInstruction());
instr = DefineAsRegister(new(zone())
LDummyUse(UseAny(current->OperandAt(0))));
}
for (int i = 1; i < current->OperandCount(); ++i) {
+ if (current->OperandAt(i)->IsControlInstruction()) continue;
LInstruction* dummy =
new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
dummy->set_hydrogen_value(current);
LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
+ LInstruction* goto_instr = CheckElideControlInstruction(instr);
+ if (goto_instr != NULL) return goto_instr;
+
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());
return new(zone()) LCmpMapAndBranch(value);
}
-LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
- LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LOuterContext(context));
-}
-
-
LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
LOperand* context = UseFixed(instr->context(), esi);
return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
}
-LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
- LOperand* context = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LGlobalObject(context));
-}
-
-
-LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
- LOperand* global_object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LGlobalReceiver(global_object));
-}
-
-
LInstruction* LChunkBuilder::DoCallJSFunction(
HCallJSFunction* instr) {
LOperand* function = UseFixed(instr->function(), edi);
LOperand* context = UseFixed(instr->context(), esi);
LOperand* function = UseFixed(instr->function(), edi);
LCallFunction* call = new(zone()) LCallFunction(context, function);
- LInstruction* result = DefineFixed(call, eax);
- if (instr->IsTailCall()) return result;
- return MarkAsCall(result, instr);
+ return MarkAsCall(DefineFixed(call, eax), instr);
}
}
-LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) {
- LOperand* object = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LElementsKind(object));
-}
-
-
-LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
- LOperand* object = UseRegister(instr->value());
- LValueOf* result = new(zone()) LValueOf(object, TempRegister());
- return DefineSameAsFirst(result);
-}
-
-
LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
LOperand* date = UseFixed(instr->value(), eax);
LDateField* result =
}
-LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
- LOperand* context = UseFixed(instr->context(), esi);
- LOperand* value = UseFixed(instr->value(), eax);
- return MarkAsCall(new(zone()) LThrow(context, value), instr);
-}
-
-
LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
return NULL;
}
LOperand* temp = TempRegister();
LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
return AssignEnvironment(DefineAsRegister(res));
+ } else if (to.IsSIMD128()) {
+ LOperand* value = UseRegister(instr->value());
+ LOperand* temp = TempRegister();
+ LTaggedToSIMD128* res = new(zone()) LTaggedToSIMD128(value, temp, to);
+ return AssignEnvironment(DefineAsRegister(res));
} else if (to.IsSmi()) {
HValue* val = instr->value();
LOperand* value = UseRegister(val);
new(zone()) LInteger32ToDouble(Use(instr->value())));
}
}
+ } else if (from.IsSIMD128()) {
+ ASSERT(to.IsTagged());
+ info()->MarkAsDeferredCalling();
+ LOperand* value = UseRegister(instr->value());
+ LOperand* temp = TempRegister();
+
+ // Make sure that temp and result_temp are different registers.
+ LUnallocated* result_temp = TempRegister();
+ LSIMD128ToTagged* result = new(zone()) LSIMD128ToTagged(value, temp);
+ return AssignPointerMap(Define(result, result_temp));
}
UNREACHABLE();
return NULL;
}
-LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
- HLoadExternalArrayPointer* instr) {
- LOperand* input = UseRegisterAtStart(instr->value());
- return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input));
-}
-
-
LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
ASSERT(instr->key()->representation().IsSmiOrInteger32());
ElementsKind elements_kind = instr->elements_kind();
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
+ bool load_128bits_without_sse2 = IsSIMD128ElementsKind(elements_kind) &&
+ !CPU::SupportsSIMD128InCrankshaft();
if (!instr->is_typed_elements()) {
LOperand* obj = UseRegisterAtStart(instr->elements());
- result = new(zone()) LLoadKeyed(obj, key);
+ result = new(zone()) LLoadKeyed(obj, key, NULL);
} else {
ASSERT(
(instr->representation().IsInteger32() &&
!(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
(instr->representation().IsDouble() &&
- (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
+ (IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
+ (CPU::SupportsSIMD128InCrankshaft()
+ ? instr->representation().IsFloat32x4()
+ : instr->representation().IsTagged() &&
+ (IsFloat32x4ElementsKind(instr->elements_kind()))) ||
+ (CPU::SupportsSIMD128InCrankshaft()
+ ? instr->representation().IsInt32x4()
+ : instr->representation().IsTagged() &&
+ (IsInt32x4ElementsKind(instr->elements_kind()))));
LOperand* backing_store = UseRegister(instr->elements());
- result = new(zone()) LLoadKeyed(backing_store, key);
+ result = new(zone()) LLoadKeyed(backing_store, key,
+ load_128bits_without_sse2 ? TempRegister() : NULL);
+ if (load_128bits_without_sse2) {
+ info()->MarkAsDeferredCalling();
+ AssignPointerMap(result);
+ }
}
DefineAsRegister(result);
LOperand* val = NULL;
val = UseRegisterAtStart(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
- return new(zone()) LStoreKeyed(object, key, val);
+ return new(zone()) LStoreKeyed(object, key, val, NULL);
} else {
ASSERT(instr->value()->representation().IsSmiOrTagged());
bool needs_write_barrier = instr->NeedsWriteBarrier();
val = UseRegisterOrConstantAtStart(instr->value());
key = UseRegisterOrConstantAtStart(instr->key());
}
- return new(zone()) LStoreKeyed(obj, key, val);
+ return new(zone()) LStoreKeyed(obj, key, val, NULL);
}
}
(instr->value()->representation().IsInteger32() &&
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
- IsDoubleOrFloatElementsKind(elements_kind)));
+ IsDoubleOrFloatElementsKind(elements_kind)) ||
+ (CPU::SupportsSIMD128InCrankshaft()
+ ? instr->value()->representation().IsFloat32x4()
+ : instr->value()->representation().IsTagged() &&
+ IsFloat32x4ElementsKind(elements_kind)) ||
+ (CPU::SupportsSIMD128InCrankshaft()
+ ? instr->value()->representation().IsInt32x4()
+ : instr->value()->representation().IsTagged() &&
+ IsInt32x4ElementsKind(elements_kind)));
ASSERT((instr->is_fixed_typed_array() &&
instr->elements()->representation().IsTagged()) ||
(instr->is_external() &&
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
- return new(zone()) LStoreKeyed(backing_store, key, val);
+ bool store_128bits_without_sse2 = IsSIMD128ElementsKind(elements_kind) &&
+ !CPU::SupportsSIMD128InCrankshaft();
+ LStoreKeyed* result =
+ new(zone()) LStoreKeyed(backing_store, key, val,
+ store_128bits_without_sse2 ? TempRegister() : NULL);
+ return store_128bits_without_sse2 ? AssignEnvironment(result) : result;
}
}
+const char* LNullarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_NULLARY_OPERATION_CASE_ITEM(module, function, name, p4) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
+#undef SIMD_NULLARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoNullarySIMDOperation(
+ HNullarySIMDOperation* instr) {
+ LNullarySIMDOperation* result =
+ new(zone()) LNullarySIMDOperation(instr->op());
+ switch (instr->op()) {
+#define SIMD_NULLARY_OPERATION_CASE_ITEM(module, function, name, p4) \
+ case k##name:
+SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
+#undef SIMD_NULLARY_OPERATION_CASE_ITEM
+ return DefineAsRegister(result);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LUnarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+ case kSIMD128Change: return "SIMD128-change";
+#define SIMD_UNARY_OPERATION_CASE_ITEM(module, function, name, p4, p5) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
+SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
+#undef SIMD_UNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoUnarySIMDOperation(HUnarySIMDOperation* instr) {
+ LOperand* input = UseRegisterAtStart(instr->value());
+ LUnarySIMDOperation* result =
+ new(zone()) LUnarySIMDOperation(input, instr->op());
+ switch (instr->op()) {
+ case kSIMD128Change:
+ return AssignEnvironment(DefineAsRegister(result));
+ case kFloat32x4Abs:
+ case kFloat32x4Neg:
+ case kFloat32x4Reciprocal:
+ case kFloat32x4ReciprocalSqrt:
+ case kFloat32x4Sqrt:
+ case kInt32x4Neg:
+ case kInt32x4Not:
+ return DefineSameAsFirst(result);
+ case kFloat32x4BitsToInt32x4:
+ case kFloat32x4ToInt32x4:
+ case kInt32x4BitsToFloat32x4:
+ case kInt32x4ToFloat32x4:
+ case kFloat32x4Splat:
+ case kInt32x4Splat:
+ case kFloat32x4GetSignMask:
+ case kFloat32x4GetX:
+ case kFloat32x4GetY:
+ case kFloat32x4GetZ:
+ case kFloat32x4GetW:
+ case kInt32x4GetSignMask:
+ case kInt32x4GetX:
+ case kInt32x4GetY:
+ case kInt32x4GetZ:
+ case kInt32x4GetW:
+ case kInt32x4GetFlagX:
+ case kInt32x4GetFlagY:
+ case kInt32x4GetFlagZ:
+ case kInt32x4GetFlagW:
+ return DefineAsRegister(result);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LBinarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_BINARY_OPERATION_CASE_ITEM(module, function, name, p4, p5, p6) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
+#undef SIMD_BINARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoBinarySIMDOperation(
+ HBinarySIMDOperation* instr) {
+ switch (instr->op()) {
+ case kFloat32x4Add:
+ case kFloat32x4Div:
+ case kFloat32x4Max:
+ case kFloat32x4Min:
+ case kFloat32x4Mul:
+ case kFloat32x4Sub:
+ case kFloat32x4Scale:
+ case kFloat32x4WithX:
+ case kFloat32x4WithY:
+ case kFloat32x4WithZ:
+ case kFloat32x4WithW:
+ case kInt32x4Add:
+ case kInt32x4And:
+ case kInt32x4Mul:
+ case kInt32x4Or:
+ case kInt32x4Sub:
+ case kInt32x4Xor:
+ case kInt32x4WithX:
+ case kInt32x4WithY:
+ case kInt32x4WithZ:
+ case kInt32x4WithW:
+ case kInt32x4WithFlagX:
+ case kInt32x4WithFlagY:
+ case kInt32x4WithFlagZ:
+ case kInt32x4WithFlagW:
+ case kInt32x4GreaterThan:
+ case kInt32x4Equal:
+ case kInt32x4LessThan: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseRegisterAtStart(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ if (instr->op() == kInt32x4WithFlagX ||
+ instr->op() == kInt32x4WithFlagY ||
+ instr->op() == kInt32x4WithFlagZ ||
+ instr->op() == kInt32x4WithFlagW) {
+ return AssignEnvironment(DefineSameAsFirst(result));
+ } else {
+ return DefineSameAsFirst(result);
+ }
+ }
+ case kFloat32x4Shuffle:
+ case kInt32x4Shuffle:
+ case kInt32x4ShiftLeft:
+ case kInt32x4ShiftRight:
+ case kInt32x4ShiftRightArithmetic: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseOrConstant(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ return AssignEnvironment(DefineSameAsFirst(result));
+ }
+ case kFloat32x4LessThan:
+ case kFloat32x4LessThanOrEqual:
+ case kFloat32x4Equal:
+ case kFloat32x4NotEqual:
+ case kFloat32x4GreaterThanOrEqual:
+ case kFloat32x4GreaterThan: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseRegisterAtStart(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ return DefineAsRegister(result);
+ }
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LTernarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_TERNARY_OPERATION_CASE_ITEM(module, function, name, p4, p5, p6, \
+ p7) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_TERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoTernarySIMDOperation(
+ HTernarySIMDOperation* instr) {
+ LOperand* first = UseRegisterAtStart(instr->first());
+ LOperand* second = UseRegisterAtStart(instr->second());
+ LOperand* third = instr->op() == kFloat32x4ShuffleMix
+ ? UseOrConstant(instr->third())
+ : UseRegisterAtStart(instr->third());
+ LTernarySIMDOperation* result =
+ new(zone()) LTernarySIMDOperation(first, second, third, instr->op());
+ switch (instr->op()) {
+ case kInt32x4Select: {
+ return DefineAsRegister(result);
+ }
+ case kFloat32x4ShuffleMix: {
+ return AssignEnvironment(DefineSameAsFirst(result));
+ }
+ case kFloat32x4Clamp: {
+ return DefineSameAsFirst(result);
+ }
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LQuarternarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(module, function, name, p4, p5, \
+ p6, p7, p8) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoQuarternarySIMDOperation(
+ HQuarternarySIMDOperation* instr) {
+ LOperand* x = UseRegisterAtStart(instr->x());
+ LOperand* y = UseRegisterAtStart(instr->y());
+ LOperand* z = UseRegisterAtStart(instr->z());
+ LOperand* w = UseRegisterAtStart(instr->w());
+ LQuarternarySIMDOperation* result =
+ new(zone()) LQuarternarySIMDOperation(x, y, z, w, instr->op());
+ if (instr->op() == kInt32x4Bool) {
+ return AssignEnvironment(DefineAsRegister(result));
+ } else {
+ return DefineAsRegister(result);
+ }
+}
+
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_IA32