Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(483)

Unified Diff: src/ia32/lithium-ia32.cc

Issue 90643003: Experimental implementation: Exposing SIMD instructions into JavaScript Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/lithium-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/lithium-ia32.cc
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 921b5aa933625703838bcfc9caf8cd52065cb2d4..d0d5744d19b28412e81dd00ed7c9cfe51989be64 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -387,23 +387,39 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
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 double-width slot.
+ spill_slot_count_ += 3;
+ num_double_slots_++; // 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;
}
}
@@ -1984,6 +2000,16 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
LOperand* temp = TempRegister();
LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp);
return AssignEnvironment(DefineAsRegister(res));
+ } else if (to.IsFloat32x4()) {
+ LOperand* value = UseRegister(instr->value());
+ LOperand* temp = TempRegister();
+ LTaggedToFloat32x4* res = new(zone()) LTaggedToFloat32x4(value, temp);
+ return AssignEnvironment(DefineAsRegister(res));
+ } else if (to.IsInt32x4()) {
+ LOperand* value = UseRegister(instr->value());
+ LOperand* temp = TempRegister();
+ LTaggedToInt32x4* res = new(zone()) LTaggedToInt32x4(value, temp);
+ return AssignEnvironment(DefineAsRegister(res));
} else if (to.IsSmi()) {
HValue* val = instr->value();
LOperand* value = UseRegister(val);
@@ -2067,6 +2093,27 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
new(zone()) LInteger32ToDouble(Use(instr->value())));
}
}
+ } else if (from.IsFloat32x4()) {
+ 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();
+ LFloat32x4ToTagged* result =
+ new(zone()) LFloat32x4ToTagged(value, temp);
+ return AssignPointerMap(Define(result, result_temp));
+ } else if (from.IsInt32x4()) {
+ 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();
+ LInt32x4ToTagged* result = new(zone()) LInt32x4ToTagged(value, temp);
+ return AssignPointerMap(Define(result, result_temp));
}
UNREACHABLE();
return NULL;
@@ -2283,19 +2330,33 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
: UseRegisterOrConstantAtStart(instr->key());
LLoadKeyed* result = NULL;
+ bool load_128bits_without_sse2 =
+ ExternalArrayOpRequiresSpecialHandling(elements_kind);
if (!instr->is_external()) {
LOperand* obj = UseRegisterAtStart(instr->elements());
- result = new(zone()) LLoadKeyed(obj, key);
+ result = new(zone()) LLoadKeyed(obj, key, NULL);
} else {
ASSERT(
(instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ (elements_kind != EXTERNAL_DOUBLE_ELEMENTS) &&
+ (elements_kind != EXTERNAL_FLOAT32x4_ELEMENTS) &&
+ (elements_kind != EXTERNAL_INT32x4_ELEMENTS)) ||
(instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+ (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))) ||
+ (CpuFeatures::IsSupported(SSE2) ?
+ instr->representation().IsFloat32x4() :
+ instr->representation().IsTagged() &&
+ elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) ||
+ (CpuFeatures::IsSupported(SSE2) ?
+ instr->representation().IsInt32x4() :
+ instr->representation().IsTagged() &&
+ elements_kind == EXTERNAL_INT32x4_ELEMENTS));
LOperand* external_pointer = UseRegister(instr->elements());
- result = new(zone()) LLoadKeyed(external_pointer, key);
+ result = new(zone()) LLoadKeyed(external_pointer, key,
+ load_128bits_without_sse2 ? TempRegister() : NULL);
+ if (load_128bits_without_sse2) info()->MarkAsDeferredCalling();
}
DefineAsRegister(result);
@@ -2303,7 +2364,8 @@ LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
(elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS);
// An unsigned int array load might overflow and cause a deopt, make sure it
// has an environment.
- return can_deoptimize ? AssignEnvironment(result) : result;
+ return can_deoptimize ? AssignEnvironment(result)
+ : load_128bits_without_sse2 ? AssignPointerMap(result) : result;
}
@@ -2350,7 +2412,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
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();
@@ -2365,7 +2427,7 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
val = UseRegisterOrConstantAtStart(instr->value());
key = UseRegisterOrConstantAtStart(instr->key());
}
- return new(zone()) LStoreKeyed(obj, key, val);
+ return new(zone()) LStoreKeyed(obj, key, val, NULL);
}
}
@@ -2373,10 +2435,19 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
ASSERT(
(instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
- (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
+ (elements_kind != EXTERNAL_DOUBLE_ELEMENTS) &&
+ (elements_kind != EXTERNAL_FLOAT32x4_ELEMENTS)) ||
(instr->value()->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
- (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
+ (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))) ||
+ (CpuFeatures::IsSupported(SSE2)
+ ? instr->value()->representation().IsFloat32x4()
+ : instr->value()->representation().IsTagged() &&
+ elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) ||
+ (CpuFeatures::IsSupported(SSE2)
+ ? instr->value()->representation().IsInt32x4()
+ : instr->value()->representation().IsTagged() &&
+ elements_kind == EXTERNAL_INT32x4_ELEMENTS));
ASSERT(instr->elements()->representation().IsExternal());
LOperand* external_pointer = UseRegister(instr->elements());
@@ -2386,9 +2457,12 @@ LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
LOperand* key = clobbers_key
? UseTempRegister(instr->key())
: UseRegisterOrConstantAtStart(instr->key());
- return new(zone()) LStoreKeyed(external_pointer,
- key,
- val);
+ bool store_128bits_without_sse2 =
+ ExternalArrayOpRequiresSpecialHandling(elements_kind);
+ LStoreKeyed* result =
+ new(zone()) LStoreKeyed(external_pointer, key, val,
+ store_128bits_without_sse2 ? TempRegister() : NULL);
+ return store_128bits_without_sse2 ? AssignEnvironment(result) : result;
}
@@ -2792,6 +2866,282 @@ LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
}
+const char* LNullarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+ case kFloat32x4Zero: return "float32x4-zero";
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoNullarySIMDOperation(
+ HNullarySIMDOperation* instr) {
+ LNullarySIMDOperation* result =
+ new(zone()) LNullarySIMDOperation(instr->op());
+ switch (instr->op()) {
+ case kFloat32x4Zero:
+ return DefineAsRegister(result);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LUnarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+ case kFloat32x4OrInt32x4Change: return "float32x4_int32x4-change";
+ case kSIMDAbs: return "simd-abs";
+ case kSIMDNeg: return "simd-neg";
+ case kSIMDNegU32: return "simd-negu32";
+ case kSIMDReciprocal: return "simd-reciprocal";
+ case kSIMDReciprocalSqrt: return "simd-reciprocalSqrt";
+ case kSIMDSqrt: return "simd-sqrt";
+ case kSIMDBitsToFloat32x4: return "simd-bitsToFloat32x4";
+ case kSIMDToFloat32x4: return "simd-toFloat32x4";
+ case kSIMDBitsToInt32x4: return "simd-bitsToInt32x4";
+ case kSIMDToInt32x4: return "simd-toInt32x4";
+ case kFloat32x4Splat: return "float32x4-splat";
+ case kInt32x4Splat: return "int32x4-splat";
+ case kFloat32x4SignMask: return "float32x4-signMask";
+ case kFloat32x4X: return "float32x4-x";
+ case kFloat32x4Y: return "float32x4-y";
+ case kFloat32x4Z: return "float32x4-z";
+ case kFloat32x4W: return "float32x4-w";
+ case kInt32x4SignMask: return "int32x4-signMask";
+ case kInt32x4X: return "int32x4-x";
+ case kInt32x4Y: return "int32x4-y";
+ case kInt32x4Z: return "int32x4-z";
+ case kInt32x4W: return "int32x4-w";
+ case kInt32x4FlagX: return "int32x4-flagX";
+ case kInt32x4FlagY: return "int32x4-flagY";
+ case kInt32x4FlagZ: return "int32x4-flagZ";
+ case kInt32x4FlagW: return "int32x4-flagW";
+ 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 kFloat32x4OrInt32x4Change:
+ return AssignEnvironment(DefineAsRegister(result));
+ case kSIMDAbs:
+ case kSIMDNeg:
+ case kSIMDNegU32:
+ case kSIMDReciprocal:
+ case kSIMDReciprocalSqrt:
+ case kSIMDSqrt:
+ return DefineSameAsFirst(result);
+ case kSIMDBitsToFloat32x4:
+ case kSIMDToFloat32x4:
+ case kSIMDBitsToInt32x4:
+ case kSIMDToInt32x4:
+ case kFloat32x4Splat:
+ case kInt32x4Splat:
+ case kFloat32x4SignMask:
+ case kFloat32x4X:
+ case kFloat32x4Y:
+ case kFloat32x4Z:
+ case kFloat32x4W:
+ case kInt32x4SignMask:
+ case kInt32x4X:
+ case kInt32x4Y:
+ case kInt32x4Z:
+ case kInt32x4W:
+ case kInt32x4FlagX:
+ case kInt32x4FlagY:
+ case kInt32x4FlagZ:
+ case kInt32x4FlagW:
+ return DefineAsRegister(result);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LBinarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+ case kSIMDAdd: return "simd-add";
+ case kSIMDSub: return "simd-sub";
+ case kSIMDMul: return "simd-mul";
+ case kSIMDDiv: return "simd-mul";
+ case kSIMDMin: return "simd-min";
+ case kSIMDMax: return "simd-max";
+ case kSIMDScale: return "simd-scale";
+ case kSIMDAnd: return "simd-and";
+ case kSIMDOr: return "simd-or";
+ case kSIMDXor: return "simd-xor";
+ case kSIMDAddU32: return "simd-addu32";
+ case kSIMDSubU32: return "simd-subu32";
+ case kSIMDMulU32: return "simd-mulu32";
+ case kSIMDShuffle: return "simd-shuffle";
+ case kSIMDShuffleU32: return "simd-shuffleu32";
+ case kSIMDLessThan: return "simd-lessThan";
+ case kSIMDLessThanOrEqual: return "simd-lessThanOrEqual";
+ case kSIMDEqual: return "simd-equal";
+ case kSIMDNotEqual: return "simd-notEqual";
+ case kSIMDGreaterThanOrEqual: return "simd-greaterThanOrEqual";
+ case kSIMDGreaterThan: return "simd-greaterThan";
+ case kSIMDWithX: return "simd-withX";
+ case kSIMDWithY: return "simd-withY";
+ case kSIMDWithZ: return "simd-withZ";
+ case kSIMDWithW: return "simd-withW";
+ case kSIMDWithXu32: return "simd-withXu32";
+ case kSIMDWithYu32: return "simd-withYu32";
+ case kSIMDWithZu32: return "simd-withZu32";
+ case kSIMDWithWu32: return "simd-withWu32";
+ case kSIMDWithFlagX: return "simd-withFlagX";
+ case kSIMDWithFlagY: return "simd-withFlagY";
+ case kSIMDWithFlagZ: return "simd-withFlagZ";
+ case kSIMDWithFlagW: return "simd-withFlagW";
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoBinarySIMDOperation(
+ HBinarySIMDOperation* instr) {
+ switch (instr->op()) {
+ case kSIMDAdd:
+ case kSIMDSub:
+ case kSIMDMul:
+ case kSIMDDiv:
+ case kSIMDMin:
+ case kSIMDMax:
+ case kSIMDScale:
+ case kSIMDAnd:
+ case kSIMDOr:
+ case kSIMDXor:
+ case kSIMDAddU32:
+ case kSIMDSubU32:
+ case kSIMDMulU32:
+ case kSIMDWithX:
+ case kSIMDWithY:
+ case kSIMDWithZ:
+ case kSIMDWithW:
+ case kSIMDWithXu32:
+ case kSIMDWithYu32:
+ case kSIMDWithZu32:
+ case kSIMDWithWu32:
+ case kSIMDWithFlagX:
+ case kSIMDWithFlagY:
+ case kSIMDWithFlagZ:
+ case kSIMDWithFlagW: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseRegisterAtStart(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ if (instr->op() == kSIMDWithFlagX || instr->op() == kSIMDWithFlagY ||
+ instr->op() == kSIMDWithFlagZ || instr->op() == kSIMDWithFlagW) {
+ return AssignEnvironment(DefineSameAsFirst(result));
+ } else {
+ return DefineSameAsFirst(result);
+ }
+ }
+ case kSIMDShuffle:
+ case kSIMDShuffleU32: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseOrConstant(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ return AssignEnvironment(DefineSameAsFirst(result));
+ }
+ case kSIMDLessThan:
+ case kSIMDLessThanOrEqual:
+ case kSIMDEqual:
+ case kSIMDNotEqual:
+ case kSIMDGreaterThanOrEqual:
+ case kSIMDGreaterThan: {
+ 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()) {
+ case kSIMDSelect: return "simd-select";
+ case kSIMDShuffleMix: return "simd-shuffleMix";
+ case kSIMDClamp: return "simd-clamp";
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoTernarySIMDOperation(
+ HTernarySIMDOperation* instr) {
+ LOperand* first = UseRegisterAtStart(instr->first());
+ LOperand* second = UseRegisterAtStart(instr->second());
+ LOperand* third = instr->op() == kSIMDShuffleMix
+ ? UseOrConstant(instr->third())
+ : UseRegisterAtStart(instr->third());
+ LTernarySIMDOperation* result =
+ new(zone()) LTernarySIMDOperation(first, second, third, instr->op());
+ switch (instr->op()) {
+ case kSIMDSelect: {
+ return DefineAsRegister(result);
+ }
+ case kSIMDShuffleMix: {
+ return AssignEnvironment(DefineSameAsFirst(result));
+ }
+ case kSIMDClamp: {
+ return DefineSameAsFirst(result);
+ }
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LQuarternarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+ case kFloat32x4Constructor: return "float32x4-constructor";
+ case kInt32x4Constructor: return "int32x4-constructor";
+ case kInt32x4Bool: return "int32x4-bool";
+ 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
« no previous file with comments | « src/ia32/lithium-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698