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

Unified Diff: src/ia32/lithium-codegen-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-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index eb1f960c0a738d48595287a90429882c4ea9faaa..cd34868742db673c3763d5610e6618f4e115c7bd 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -541,6 +541,21 @@ XMMRegister LCodeGen::ToDoubleRegister(int index) const {
}
+XMMRegister LCodeGen::ToXMMRegister(int index) const {
+ return XMMRegister::FromAllocationIndex(index);
+}
+
+
+XMMRegister LCodeGen::ToFloat32x4Register(int index) const {
+ return Float32x4Register::FromAllocationIndex(index);
+}
+
+
+XMMRegister LCodeGen::ToInt32x4Register(int index) const {
+ return Int32x4Register::FromAllocationIndex(index);
+}
+
+
void LCodeGen::X87LoadForUsage(X87Register reg) {
ASSERT(x87_stack_.Contains(reg));
x87_stack_.Fxch(reg);
@@ -763,6 +778,24 @@ XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
}
+XMMRegister LCodeGen::ToFloat32x4Register(LOperand* op) const {
+ ASSERT(op->IsFloat32x4Register());
+ return ToFloat32x4Register(op->index());
+}
+
+
+XMMRegister LCodeGen::ToInt32x4Register(LOperand* op) const {
+ ASSERT(op->IsInt32x4Register());
+ return ToInt32x4Register(op->index());
+}
+
+
+XMMRegister LCodeGen::ToXMMRegister(LOperand* op) const {
+ ASSERT(op->IsFloat32x4Register() || op->IsInt32x4Register());
+ return ToXMMRegister(op->index());
+}
+
+
int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
return ToRepresentation(op, Representation::Integer32());
}
@@ -818,7 +851,10 @@ static int ArgumentsOffsetWithoutFrame(int index) {
Operand LCodeGen::ToOperand(LOperand* op) const {
if (op->IsRegister()) return Operand(ToRegister(op));
if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op));
- ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
+ if (op->IsFloat32x4Register()) return Operand(ToFloat32x4Register(op));
+ if (op->IsInt32x4Register()) return Operand(ToInt32x4Register(op));
+ ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot() ||
+ op->IsFloat32x4StackSlot() || op->IsInt32x4StackSlot());
if (NeedsEagerFrame()) {
return Operand(ebp, StackSlotOffset(op->index()));
} else {
@@ -945,6 +981,10 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
}
} else if (op->IsDoubleStackSlot()) {
translation->StoreDoubleStackSlot(op->index());
+ } else if (op->IsFloat32x4StackSlot()) {
+ translation->StoreFloat32x4StackSlot(op->index());
+ } else if (op->IsInt32x4StackSlot()) {
+ translation->StoreInt32x4StackSlot(op->index());
} else if (op->IsArgument()) {
ASSERT(is_tagged);
int src_index = GetStackSlotCount() + op->index();
@@ -961,6 +1001,12 @@ void LCodeGen::AddToTranslation(LEnvironment* environment,
} else if (op->IsDoubleRegister()) {
XMMRegister reg = ToDoubleRegister(op);
translation->StoreDoubleRegister(reg);
+ } else if (op->IsFloat32x4Register()) {
+ XMMRegister reg = ToFloat32x4Register(op);
+ translation->StoreFloat32x4Register(reg);
+ } else if (op->IsInt32x4Register()) {
+ XMMRegister reg = ToInt32x4Register(op);
+ translation->StoreInt32x4Register(reg);
} else if (op->IsConstantOperand()) {
HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
@@ -3439,13 +3485,49 @@ void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
+ class DeferredFloat32x4ToTagged V8_FINAL : public LDeferredCode {
+ public:
+ DeferredFloat32x4ToTagged(LCodeGen* codegen,
+ LInstruction* instr,
+ const X87Stack& x87_stack)
+ : LDeferredCode(codegen, x87_stack), instr_(instr) { }
+ virtual void Generate() V8_OVERRIDE {
+ codegen()->DoDeferredFloat32x4ToTagged(instr_);
+ }
+ virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
+ private:
+ LInstruction* instr_;
+ };
+
+ class DeferredInt32x4ToTagged V8_FINAL : public LDeferredCode {
+ public:
+ DeferredInt32x4ToTagged(LCodeGen* codegen,
+ LInstruction* instr,
+ const X87Stack& x87_stack)
+ : LDeferredCode(codegen, x87_stack), instr_(instr) { }
+ virtual void Generate() V8_OVERRIDE {
+ codegen()->DoDeferredInt32x4ToTagged(instr_);
+ }
+ virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
+ private:
+ LInstruction* instr_;
+ };
+
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
- if (!key->IsConstantOperand() &&
- ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
- elements_kind)) {
- __ SmiUntag(ToRegister(key));
+ if (!key->IsConstantOperand()) {
+ if (ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
+ elements_kind)) {
+ if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
+ elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
+ // Double the index as Float32x4 and Int32x4 need scale 16.
+ __ shl(ToRegister(key), 1);
+ } else {
+ __ SmiUntag(ToRegister(key));
+ }
+ }
}
+
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
@@ -3469,6 +3551,47 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
} else {
X87Mov(ToX87Register(instr->result()), operand);
}
+ } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) {
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ __ movups(ToFloat32x4Register(instr->result()), operand);
+ } else {
+ Register reg = ToRegister(instr->result());
+ Register tmp = ToRegister(instr->temp());
+ DeferredFloat32x4ToTagged* deferred =
+ new(zone()) DeferredFloat32x4ToTagged(this, instr, x87_stack_);
+ if (FLAG_inline_new) {
+ __ AllocateFloat32x4(reg, tmp, deferred->entry());
+ } else {
+ __ jmp(deferred->entry());
+ }
+ __ bind(deferred->exit());
+ for (int offset = 0; offset < kFloat32x4Size; offset += kFloatSize) {
+ __ mov(tmp, Operand(operand, offset));
+ __ mov(Operand(FieldOperand(reg, Float32x4::kValueOffset), offset),
+ tmp);
+ }
+ }
+ } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ __ movups(ToInt32x4Register(instr->result()), operand);
+ } else {
+ Register reg = ToRegister(instr->result());
+ Register tmp = ToRegister(instr->temp());
+ DeferredInt32x4ToTagged* deferred =
+ new(zone()) DeferredInt32x4ToTagged(this, instr, x87_stack_);
+ if (FLAG_inline_new) {
+ __ AllocateInt32x4(reg, tmp, deferred->entry());
+ } else {
+ __ jmp(deferred->entry());
+ }
+ __ bind(deferred->exit());
+ for (int offset = 0; offset < kInt32x4Size; offset += kInt32Size) {
+ __ mov(tmp, Operand(operand, offset));
+ __ mov(Operand(FieldOperand(reg, Int32x4::kValueOffset), offset), tmp);
+ }
+ }
} else {
Register result(ToRegister(instr->result()));
switch (elements_kind) {
@@ -3497,6 +3620,8 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
break;
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
+ case EXTERNAL_FLOAT32x4_ELEMENTS:
+ case EXTERNAL_INT32x4_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
@@ -3589,11 +3714,21 @@ Operand LCodeGen::BuildFastArrayOperand(
Register elements_pointer_reg = ToRegister(elements_pointer);
int element_shift_size = ElementsKindToShiftSize(elements_kind);
int shift_size = element_shift_size;
+ if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
+ elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
+ // Double the index and use scale 8. Float32x4 needs scale 16.
+ additional_index *= 2;
+ }
if (key->IsConstantOperand()) {
int constant_value = ToInteger32(LConstantOperand::cast(key));
if (constant_value & 0xF0000000) {
Abort(kArrayIndexConstantValueTooBig);
}
+ if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
+ elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
+ // Double the index and use scale 8. Float32x4 needs scale 16.
+ constant_value *= 2;
+ }
return Operand(elements_pointer_reg,
((constant_value + additional_index) << shift_size)
+ offset);
@@ -3603,6 +3738,8 @@ Operand LCodeGen::BuildFastArrayOperand(
shift_size -= kSmiTagSize;
}
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
+ // For Float32x4, make sure the index register is doubled before
+ // calling this function and restored after its usage.
return Operand(elements_pointer_reg,
ToRegister(key),
scale_factor,
@@ -4603,11 +4740,19 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
LOperand* key = instr->key();
- if (!key->IsConstantOperand() &&
- ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
- elements_kind)) {
- __ SmiUntag(ToRegister(key));
+ if (!key->IsConstantOperand()) {
+ if (ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
+ elements_kind)) {
+ if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
+ elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
+ // Double the index as Float32x4 and Int32x4 need scale 16.
+ __ shl(ToRegister(key), 1);
+ } else {
+ __ SmiUntag(ToRegister(key));
+ }
+ }
}
+
Operand operand(BuildFastArrayOperand(
instr->elements(),
key,
@@ -4632,6 +4777,42 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
} else {
X87Mov(operand, ToX87Register(instr->value()));
}
+ } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) {
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ __ movups(operand, ToFloat32x4Register(instr->value()));
+ } else {
+ ASSERT(instr->value()->IsRegister());
+ Register temp = ToRegister(instr->temp());
+ Register input_reg = ToRegister(instr->value());
+ __ test(input_reg, Immediate(kSmiTagMask));
+ DeoptimizeIf(zero, instr->environment());
+ __ CmpObjectType(input_reg, FLOAT32x4_TYPE, temp);
+ DeoptimizeIf(not_equal, instr->environment());
+ for (int offset = 0; offset < kFloat32x4Size; offset += kFloatSize) {
+ __ mov(temp,
+ Operand(FieldOperand(input_reg, Float32x4::kValueOffset), offset));
+ __ mov(Operand(operand, offset), temp);
+ }
+ }
+ } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
+ if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
+ CpuFeatureScope scope(masm(), SSE2);
+ __ movups(operand, ToInt32x4Register(instr->value()));
+ } else {
+ ASSERT(instr->value()->IsRegister());
+ Register temp = ToRegister(instr->temp());
+ Register input_reg = ToRegister(instr->value());
+ __ test(input_reg, Immediate(kSmiTagMask));
+ DeoptimizeIf(zero, instr->environment());
+ __ CmpObjectType(input_reg, INT32x4_TYPE, temp);
+ DeoptimizeIf(not_equal, instr->environment());
+ for (int offset = 0; offset < kInt32x4Size; offset += kInt32Size) {
+ __ mov(temp,
+ Operand(FieldOperand(input_reg, Int32x4::kValueOffset), offset));
+ __ mov(Operand(operand, offset), temp);
+ }
+ }
} else {
Register value = ToRegister(instr->value());
switch (elements_kind) {
@@ -4649,6 +4830,8 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
__ mov(operand, value);
break;
case EXTERNAL_FLOAT_ELEMENTS:
+ case EXTERNAL_FLOAT32x4_ELEMENTS:
+ case EXTERNAL_INT32x4_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_SMI_ELEMENTS:
case FAST_ELEMENTS:
@@ -6126,6 +6309,16 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
factory()->heap_number_map());
final_branch_condition = equal;
+ } else if (type_name->Equals(heap()->float32x4_string())) {
+ __ JumpIfSmi(input, false_label, false_distance);
+ __ CmpObjectType(input, FLOAT32x4_TYPE, input);
+ final_branch_condition = equal;
+
+ } else if (type_name->Equals(heap()->int32x4_string())) {
+ __ JumpIfSmi(input, false_label, false_distance);
+ __ CmpObjectType(input, INT32x4_TYPE, input);
+ final_branch_condition = equal;
+
} else if (type_name->Equals(heap()->string_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
@@ -6433,6 +6626,869 @@ void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
}
+void LCodeGen::DoFloat32x4ToTagged(LFloat32x4ToTagged* instr) {
+ class DeferredFloat32x4ToTagged V8_FINAL : public LDeferredCode {
+ public:
+ DeferredFloat32x4ToTagged(LCodeGen* codegen,
+ LInstruction* instr,
+ const X87Stack& x87_stack)
+ : LDeferredCode(codegen, x87_stack), instr_(instr) { }
+ virtual void Generate() V8_OVERRIDE {
+ codegen()->DoDeferredFloat32x4ToTagged(instr_);
+ }
+ virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
+ private:
+ LInstruction* instr_;
+ };
+
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ Register reg = ToRegister(instr->result());
+ Register tmp = ToRegister(instr->temp());
+
+ DeferredFloat32x4ToTagged* deferred =
+ new(zone()) DeferredFloat32x4ToTagged(this, instr, x87_stack_);
+ if (FLAG_inline_new) {
+ __ AllocateFloat32x4(reg, tmp, deferred->entry());
+ } else {
+ __ jmp(deferred->entry());
+ }
+ __ bind(deferred->exit());
+ __ movups(FieldOperand(reg, Float32x4::kValueOffset), input_reg);
+}
+
+
+void LCodeGen::DoDeferredFloat32x4ToTagged(LInstruction* instr) {
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ Register reg = ToRegister(instr->result());
+ __ Set(reg, Immediate(0));
+
+ PushSafepointRegistersScope scope(this);
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateFloat32x4);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+ __ StoreToSafepointRegisterSlot(reg, eax);
+}
+
+
+void LCodeGen::DoTaggedToFloat32x4(LTaggedToFloat32x4* instr) {
+ CpuFeatureScope scope(masm(), SSE2);
+ Register input_reg = ToRegister(instr->value());
+ Register scratch = ToRegister(instr->temp());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+
+ __ test(input_reg, Immediate(kSmiTagMask));
+ DeoptimizeIf(zero, instr->environment());
+ __ CmpObjectType(input_reg, FLOAT32x4_TYPE, scratch);
+ DeoptimizeIf(not_equal, instr->environment());
+ __ movups(result_reg, FieldOperand(input_reg, Float32x4::kValueOffset));
+}
+
+
+void LCodeGen::DoInt32x4ToTagged(LInt32x4ToTagged* instr) {
+ class DeferredInt32x4ToTagged V8_FINAL : public LDeferredCode {
+ public:
+ DeferredInt32x4ToTagged(LCodeGen* codegen,
+ LInstruction* instr,
+ const X87Stack& x87_stack)
+ : LDeferredCode(codegen, x87_stack), instr_(instr) { }
+ virtual void Generate() V8_OVERRIDE {
+ codegen()->DoDeferredInt32x4ToTagged(instr_);
+ }
+ virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
+ private:
+ LInstruction* instr_;
+ };
+
+ CpuFeatureScope scope(masm(), SSE2);
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ Register reg = ToRegister(instr->result());
+ Register tmp = ToRegister(instr->temp());
+
+ DeferredInt32x4ToTagged* deferred =
+ new(zone()) DeferredInt32x4ToTagged(this, instr, x87_stack_);
+ if (FLAG_inline_new) {
+ __ AllocateInt32x4(reg, tmp, deferred->entry());
+ } else {
+ __ jmp(deferred->entry());
+ }
+ __ bind(deferred->exit());
+ __ movups(FieldOperand(reg, Int32x4::kValueOffset), input_reg);
+}
+
+
+void LCodeGen::DoDeferredInt32x4ToTagged(LInstruction* instr) {
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ Register reg = ToRegister(instr->result());
+ __ Set(reg, Immediate(0));
+
+ PushSafepointRegistersScope scope(this);
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateInt32x4);
+ // Ensure that value in rax survives popping registers.
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+ __ StoreToSafepointRegisterSlot(reg, eax);
+}
+
+
+void LCodeGen::DoTaggedToInt32x4(LTaggedToInt32x4* instr) {
+ LOperand* input = instr->value();
+ ASSERT(input->IsRegister());
+ LOperand* result = instr->result();
+ ASSERT(result->IsInt32x4Register());
+
+ Register input_reg = ToRegister(input);
+ Register scratch = ToRegister(instr->temp());
+ XMMRegister result_reg = ToInt32x4Register(result);
+
+ CpuFeatureScope scope(masm(), SSE2);
+ __ test(input_reg, Immediate(kSmiTagMask));
+ DeoptimizeIf(zero, instr->environment());
+ __ CmpObjectType(input_reg, INT32x4_TYPE, scratch);
+ DeoptimizeIf(not_equal, instr->environment());
+ __ movups(result_reg, FieldOperand(input_reg, Int32x4::kValueOffset));
+}
+
+
+void LCodeGen::DoNullarySIMDOperation(LNullarySIMDOperation* instr) {
+ CpuFeatureScope scope(masm(), SSE2);
+ switch (instr->op()) {
+ case kFloat32x4Zero: {
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ __ xorps(result_reg, result_reg);
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoUnarySIMDOperation(LUnarySIMDOperation* instr) {
+ CpuFeatureScope scope(masm(), SSE2);
+ uint8_t select = 0;
+ switch (instr->op()) {
+ case kFloat32x4OrInt32x4Change: {
+ Comment(";;; deoptimize: can not perform representation change"
+ "for float32x4 or int32x4");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ case kSIMDAbs:
+ case kSIMDNeg:
+ case kSIMDReciprocal:
+ case kSIMDReciprocalSqrt:
+ case kSIMDSqrt: {
+ ASSERT(instr->value()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ switch (instr->op()) {
+ case kSIMDAbs:
+ __ absps(input_reg);
+ break;
+ case kSIMDNeg:
+ __ negateps(input_reg);
+ break;
+ case kSIMDReciprocal:
+ __ rcpps(input_reg, input_reg);
+ break;
+ case kSIMDReciprocalSqrt:
+ __ rsqrtps(input_reg, input_reg);
+ break;
+ case kSIMDSqrt:
+ __ sqrtps(input_reg, input_reg);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kSIMDNot:
+ case kSIMDNegU32: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ switch (instr->op()) {
+ case kSIMDNot:
+ __ notps(input_reg);
+ break;
+ case kSIMDNegU32:
+ __ pnegd(input_reg);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kSIMDBitsToFloat32x4:
+ case kSIMDToFloat32x4: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ if (instr->op() == kSIMDBitsToFloat32x4) {
+ if (!result_reg.is(input_reg)) {
+ __ movaps(result_reg, input_reg);
+ }
+ } else {
+ ASSERT(instr->op() == kSIMDToFloat32x4);
+ __ cvtdq2ps(result_reg, input_reg);
+ }
+ return;
+ }
+ case kSIMDBitsToInt32x4:
+ case kSIMDToInt32x4: {
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ if (instr->op() == kSIMDBitsToInt32x4) {
+ if (!result_reg.is(input_reg)) {
+ __ movaps(result_reg, input_reg);
+ }
+ } else {
+ ASSERT(instr->op() == kSIMDToInt32x4);
+ __ cvtps2dq(result_reg, input_reg);
+ }
+ return;
+ }
+ case kFloat32x4Splat: {
+ ASSERT(instr->hydrogen()->value()->representation().IsDouble());
+ XMMRegister input_reg = ToDoubleRegister(instr->value());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ XMMRegister xmm_scratch = xmm0;
+ __ xorps(xmm_scratch, xmm_scratch);
+ __ cvtsd2ss(xmm_scratch, input_reg);
+ __ shufps(xmm_scratch, xmm_scratch, 0x0);
+ __ movaps(result_reg, xmm_scratch);
+ return;
+ }
+ case kInt32x4Splat: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
+ Register input_reg = ToRegister(instr->value());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ __ movd(result_reg, input_reg);
+ __ shufps(result_reg, result_reg, 0x0);
+ return;
+ }
+ case kInt32x4SignMask: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ Register result = ToRegister(instr->result());
+ __ movmskps(result, input_reg);
+ return;
+ }
+ case kFloat32x4SignMask: {
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ Register result = ToRegister(instr->result());
+ __ movmskps(result, input_reg);
+ return;
+ }
+ case kFloat32x4W:
+ select++;
+ case kFloat32x4Z:
+ select++;
+ case kFloat32x4Y:
+ select++;
+ case kFloat32x4X: {
+ ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
+ XMMRegister input_reg = ToFloat32x4Register(instr->value());
+ XMMRegister result = ToDoubleRegister(instr->result());
+ XMMRegister xmm_scratch = result.is(input_reg) ? xmm0 : result;
+
+ if (select == 0x0) {
+ __ xorps(xmm_scratch, xmm_scratch);
+ __ cvtss2sd(xmm_scratch, input_reg);
+ if (!xmm_scratch.is(result)) {
+ __ movaps(result, xmm_scratch);
+ }
+ } else {
+ __ pshufd(xmm_scratch, input_reg, select);
+ if (!xmm_scratch.is(result)) {
+ __ xorps(result, result);
+ }
+ __ cvtss2sd(result, xmm_scratch);
+ }
+ return;
+ }
+ case kInt32x4X:
+ case kInt32x4Y:
+ case kInt32x4Z:
+ case kInt32x4W:
+ case kInt32x4FlagX:
+ case kInt32x4FlagY:
+ case kInt32x4FlagZ:
+ case kInt32x4FlagW: {
+ ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
+ bool flag = false;
+ switch (instr->op()) {
+ case kInt32x4FlagX:
+ flag = true;
+ case kInt32x4X:
+ break;
+ case kInt32x4FlagY:
+ flag = true;
+ case kInt32x4Y:
+ select = 0x1;
+ break;
+ case kInt32x4FlagZ:
+ flag = true;
+ case kInt32x4Z:
+ select = 0x2;
+ break;
+ case kInt32x4FlagW:
+ flag = true;
+ case kInt32x4W:
+ select = 0x3;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ XMMRegister input_reg = ToInt32x4Register(instr->value());
+ Register result = ToRegister(instr->result());
+ if (select == 0x0) {
+ __ movd(result, input_reg);
+ } else {
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ extractps(result, input_reg, select);
+ } else {
+ XMMRegister xmm_scratch = xmm0;
+ __ pshufd(xmm_scratch, input_reg, select);
+ __ movd(result, xmm_scratch);
+ }
+ }
+
+ if (flag) {
+ Label false_value, done;
+ __ test(result, result);
+ __ j(zero, &false_value, Label::kNear);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+ __ jmp(&done, Label::kNear);
+ __ bind(&false_value);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ bind(&done);
+ }
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoBinarySIMDOperation(LBinarySIMDOperation* instr) {
+ CpuFeatureScope scope(masm(), SSE2);
+ uint8_t imm8 = 0; // for with operation
+ switch (instr->op()) {
+ case kSIMDAdd:
+ case kSIMDSub:
+ case kSIMDMul:
+ case kSIMDDiv:
+ case kSIMDMin:
+ case kSIMDMax: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToFloat32x4Register(instr->right());
+ switch (instr->op()) {
+ case kSIMDAdd:
+ __ addps(left_reg, right_reg);
+ break;
+ case kSIMDSub:
+ __ subps(left_reg, right_reg);
+ break;
+ case kSIMDMul:
+ __ mulps(left_reg, right_reg);
+ break;
+ case kSIMDDiv:
+ __ divps(left_reg, right_reg);
+ break;
+ case kSIMDMin:
+ __ minps(left_reg, right_reg);
+ break;
+ case kSIMDMax:
+ __ maxps(left_reg, right_reg);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kSIMDScale: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsDouble());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToDoubleRegister(instr->right());
+ XMMRegister scratch_reg = xmm0;
+ __ xorps(scratch_reg, scratch_reg);
+ __ cvtsd2ss(scratch_reg, right_reg);
+ __ shufps(scratch_reg, scratch_reg, 0x0);
+ __ mulps(left_reg, scratch_reg);
+ return;
+ }
+ case kSIMDShuffle: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ if (instr->hydrogen()->right()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
+ uint8_t select = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ __ shufps(left_reg, left_reg, select);
+ return;
+ } else {
+ Comment(";;; deoptimize: non-constant selector for shuffle");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ }
+ case kSIMDShuffleU32: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ if (instr->hydrogen()->right()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
+ uint8_t select = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ __ pshufd(left_reg, left_reg, select);
+ return;
+ } else {
+ Comment(";;; deoptimize: non-constant selector for shuffle");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ }
+ case kSIMDLessThan:
+ case kSIMDLessThanOrEqual:
+ case kSIMDEqual:
+ case kSIMDNotEqual:
+ case kSIMDGreaterThanOrEqual:
+ case kSIMDGreaterThan: {
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToFloat32x4Register(instr->right());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ switch (instr->op()) {
+ case kSIMDLessThan:
+ if (result_reg.is(left_reg)) {
+ __ cmpltps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpnltps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpltps(result_reg, right_reg);
+ }
+ break;
+ case kSIMDLessThanOrEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpleps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpnleps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpleps(result_reg, right_reg);
+ }
+ break;
+ case kSIMDEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpeqps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpeqps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpeqps(result_reg, right_reg);
+ }
+ break;
+ case kSIMDNotEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpneqps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpneqps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpneqps(result_reg, right_reg);
+ }
+ break;
+ case kSIMDGreaterThanOrEqual:
+ if (result_reg.is(left_reg)) {
+ __ cmpnltps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpltps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpnltps(result_reg, right_reg);
+ }
+ break;
+ case kSIMDGreaterThan:
+ if (result_reg.is(left_reg)) {
+ __ cmpnleps(result_reg, right_reg);
+ } else if (result_reg.is(right_reg)) {
+ __ cmpleps(result_reg, left_reg);
+ } else {
+ __ movaps(result_reg, left_reg);
+ __ cmpnleps(result_reg, right_reg);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kSIMDAnd:
+ case kSIMDOr:
+ case kSIMDXor:
+ case kSIMDAddU32:
+ case kSIMDSubU32:
+ case kSIMDMulU32: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsInt32x4());
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ XMMRegister right_reg = ToInt32x4Register(instr->right());
+ switch (instr->op()) {
+ case kSIMDAnd:
+ __ andps(left_reg, right_reg);
+ break;
+ case kSIMDOr:
+ __ orps(left_reg, right_reg);
+ break;
+ case kSIMDXor:
+ __ xorps(left_reg, right_reg);
+ break;
+ case kSIMDAddU32:
+ __ paddd(left_reg, right_reg);
+ break;
+ case kSIMDSubU32:
+ __ psubd(left_reg, right_reg);
+ break;
+ case kSIMDMulU32:
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ pmulld(left_reg, right_reg);
+ } else {
+ // The algorithm is from http://stackoverflow.com/questions/10500766/sse-multiplication-of-4-32-bit-integers
+ XMMRegister xmm_scratch = xmm0;
+ __ movaps(xmm_scratch, left_reg);
+ __ pmuludq(left_reg, right_reg);
+ __ psrlq(xmm_scratch, 4);
+ __ psrlq(right_reg, 4);
+ __ pmuludq(xmm_scratch, right_reg);
+ __ pshufd(left_reg, left_reg, 8);
+ __ pshufd(xmm_scratch, xmm_scratch, 8);
+ __ punpackldq(left_reg, xmm_scratch);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+ case kSIMDWithW:
+ imm8++;
+ case kSIMDWithZ:
+ imm8++;
+ case kSIMDWithY:
+ imm8++;
+ case kSIMDWithX: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsDouble());
+ XMMRegister left_reg = ToFloat32x4Register(instr->left());
+ XMMRegister right_reg = ToDoubleRegister(instr->right());
+ XMMRegister xmm_scratch = xmm0;
+ __ xorps(xmm_scratch, xmm_scratch);
+ __ cvtsd2ss(xmm_scratch, right_reg);
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ imm8 = imm8 << 4;
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ insertps(left_reg, xmm_scratch, imm8);
+ } else {
+ __ sub(esp, Immediate(kFloat32x4Size));
+ __ movups(Operand(esp, 0), left_reg);
+ __ movss(Operand(esp, imm8 * kFloatSize), xmm_scratch);
+ __ movups(left_reg, Operand(esp, 0));
+ __ add(esp, Immediate(kFloat32x4Size));
+ }
+ return;
+ }
+ case kSIMDWithWu32:
+ imm8++;
+ case kSIMDWithZu32:
+ imm8++;
+ case kSIMDWithYu32:
+ imm8++;
+ case kSIMDWithXu32: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsInteger32());
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ Register right_reg = ToRegister(instr->right());
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatureScope scope(masm(), SSE4_1);
+ __ pinsrd(left_reg, right_reg, imm8);
+ } else {
+ __ sub(esp, Immediate(kInt32x4Size));
+ __ movdqu(Operand(esp, 0), left_reg);
+ __ mov(Operand(esp, imm8 * kFloatSize), right_reg);
+ __ movdqu(left_reg, Operand(esp, 0));
+ __ add(esp, Immediate(kInt32x4Size));
+ }
+ return;
+ }
+ case kSIMDWithFlagW:
+ imm8++;
+ case kSIMDWithFlagZ:
+ imm8++;
+ case kSIMDWithFlagY:
+ imm8++;
+ case kSIMDWithFlagX: {
+ ASSERT(instr->left()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->right()->representation().IsTagged());
+ HType type = instr->hydrogen()->right()->type();
+ XMMRegister left_reg = ToInt32x4Register(instr->left());
+ Register right_reg = ToRegister(instr->right());
+ Label load_false_value, done;
+ if (type.IsBoolean()) {
+ __ sub(esp, Immediate(kInt32x4Size));
+ __ movups(Operand(esp, 0), left_reg);
+ __ CompareRoot(right_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_value, Label::kNear);
+ } else {
+ Comment(";;; deoptimize: other types for SIMD.withFlagX/Y/Z/W.");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ // load true value.
+ __ mov(Operand(esp, imm8 * kFloatSize), Immediate(0xFFFFFFFF));
+ __ jmp(&done, Label::kNear);
+ __ bind(&load_false_value);
+ __ mov(Operand(esp, imm8 * kFloatSize), Immediate(0x0));
+ __ bind(&done);
+ __ movups(left_reg, Operand(esp, 0));
+ __ add(esp, Immediate(kInt32x4Size));
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoTernarySIMDOperation(LTernarySIMDOperation* instr) {
+ CpuFeatureScope scope(masm(), SSE2);
+ switch (instr->op()) {
+ case kSIMDSelect: {
+ ASSERT(instr->hydrogen()->first()->representation().IsInt32x4());
+ ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
+
+ XMMRegister mask_reg = ToInt32x4Register(instr->first());
+ XMMRegister left_reg = ToFloat32x4Register(instr->second());
+ XMMRegister right_reg = ToFloat32x4Register(instr->third());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ XMMRegister temp_reg = xmm0;
+
+ // Copy mask.
+ __ movaps(temp_reg, mask_reg);
+ // Invert it.
+ __ notps(temp_reg);
+ // temp_reg = temp_reg & falseValue.
+ __ andps(temp_reg, right_reg);
+
+ if (!result_reg.is(mask_reg)) {
+ if (result_reg.is(left_reg)) {
+ // result_reg = result_reg & trueValue.
+ __ andps(result_reg, mask_reg);
+ // out = result_reg | temp_reg.
+ __ orps(result_reg, temp_reg);
+ } else {
+ __ movaps(result_reg, mask_reg);
+ // result_reg = result_reg & trueValue.
+ __ andps(result_reg, left_reg);
+ // out = result_reg | temp_reg.
+ __ orps(result_reg, temp_reg);
+ }
+ } else {
+ // result_reg = result_reg & trueValue.
+ __ andps(result_reg, left_reg);
+ // out = result_reg | temp_reg.
+ __ orps(result_reg, temp_reg);
+ }
+ return;
+ }
+ case kSIMDShuffleMix: {
+ ASSERT(instr->first()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->third()->representation().IsInteger32());
+ if (instr->hydrogen()->third()->IsConstant() &&
+ HConstant::cast(instr->hydrogen()->third())->HasInteger32Value()) {
+ int32_t value = ToInteger32(LConstantOperand::cast(instr->third()));
+ uint8_t select = static_cast<uint8_t>(value & 0xFF);
+ XMMRegister first_reg = ToFloat32x4Register(instr->first());
+ XMMRegister second_reg = ToFloat32x4Register(instr->second());
+ __ shufps(first_reg, second_reg, select);
+ return;
+ } else {
+ Comment(";;; deoptimize: non-constant selector for shuffle");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ }
+ case kSIMDClamp: {
+ ASSERT(instr->first()->Equals(instr->result()));
+ ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
+ ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
+
+ XMMRegister value_reg = ToFloat32x4Register(instr->first());
+ XMMRegister lower_reg = ToFloat32x4Register(instr->second());
+ XMMRegister upper_reg = ToFloat32x4Register(instr->third());
+ __ minps(value_reg, upper_reg);
+ __ maxps(value_reg, lower_reg);
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
+void LCodeGen::DoQuarternarySIMDOperation(LQuarternarySIMDOperation* instr) {
+ CpuFeatureScope scope(masm(), SSE2);
+ switch (instr->op()) {
+ case kFloat32x4Constructor: {
+ ASSERT(instr->hydrogen()->x()->representation().IsDouble());
+ ASSERT(instr->hydrogen()->y()->representation().IsDouble());
+ ASSERT(instr->hydrogen()->z()->representation().IsDouble());
+ ASSERT(instr->hydrogen()->w()->representation().IsDouble());
+ XMMRegister x_reg = ToDoubleRegister(instr->x());
+ XMMRegister y_reg = ToDoubleRegister(instr->y());
+ XMMRegister z_reg = ToDoubleRegister(instr->z());
+ XMMRegister w_reg = ToDoubleRegister(instr->w());
+ XMMRegister result_reg = ToFloat32x4Register(instr->result());
+ __ sub(esp, Immediate(kFloat32x4Size));
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, x_reg);
+ __ movss(Operand(esp, 0 * kFloatSize), xmm0);
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, y_reg);
+ __ movss(Operand(esp, 1 * kFloatSize), xmm0);
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, z_reg);
+ __ movss(Operand(esp, 2 * kFloatSize), xmm0);
+ __ xorps(xmm0, xmm0);
+ __ cvtsd2ss(xmm0, w_reg);
+ __ movss(Operand(esp, 3 * kFloatSize), xmm0);
+ __ movups(result_reg, Operand(esp, 0 * kFloatSize));
+ __ add(esp, Immediate(kFloat32x4Size));
+ return;
+ }
+ case kInt32x4Constructor: {
+ ASSERT(instr->hydrogen()->x()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->y()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->z()->representation().IsInteger32());
+ ASSERT(instr->hydrogen()->w()->representation().IsInteger32());
+ Register x_reg = ToRegister(instr->x());
+ Register y_reg = ToRegister(instr->y());
+ Register z_reg = ToRegister(instr->z());
+ Register w_reg = ToRegister(instr->w());
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ __ sub(esp, Immediate(kInt32x4Size));
+ __ mov(Operand(esp, 0 * kInt32Size), x_reg);
+ __ mov(Operand(esp, 1 * kInt32Size), y_reg);
+ __ mov(Operand(esp, 2 * kInt32Size), z_reg);
+ __ mov(Operand(esp, 3 * kInt32Size), w_reg);
+ __ movups(result_reg, Operand(esp, 0 * kInt32Size));
+ __ add(esp, Immediate(kInt32x4Size));
+ return;
+ }
+ case kInt32x4Bool: {
+ ASSERT(instr->hydrogen()->x()->representation().IsTagged());
+ ASSERT(instr->hydrogen()->y()->representation().IsTagged());
+ ASSERT(instr->hydrogen()->z()->representation().IsTagged());
+ ASSERT(instr->hydrogen()->w()->representation().IsTagged());
+ HType x_type = instr->hydrogen()->x()->type();
+ HType y_type = instr->hydrogen()->y()->type();
+ HType z_type = instr->hydrogen()->z()->type();
+ HType w_type = instr->hydrogen()->w()->type();
+ if (!x_type.IsBoolean() || !y_type.IsBoolean() ||
+ !z_type.IsBoolean() || !w_type.IsBoolean()) {
+ Comment(";;; deoptimize: other types for int32x4.bool.");
+ DeoptimizeIf(no_condition, instr->environment());
+ return;
+ }
+ XMMRegister result_reg = ToInt32x4Register(instr->result());
+ Register x_reg = ToRegister(instr->x());
+ Register y_reg = ToRegister(instr->y());
+ Register z_reg = ToRegister(instr->z());
+ Register w_reg = ToRegister(instr->w());
+ Label load_false_x, done_x, load_false_y, done_y,
+ load_false_z, done_z, load_false_w, done_w;
+ __ sub(esp, Immediate(kInt32x4Size));
+
+ __ CompareRoot(x_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_x, Label::kNear);
+ __ mov(Operand(esp, 0 * kInt32Size), Immediate(-1));
+ __ jmp(&done_x, Label::kNear);
+ __ bind(&load_false_x);
+ __ mov(Operand(esp, 0 * kInt32Size), Immediate(0x0));
+ __ bind(&done_x);
+
+ __ CompareRoot(y_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_y, Label::kNear);
+ __ mov(Operand(esp, 1 * kInt32Size), Immediate(-1));
+ __ jmp(&done_y, Label::kNear);
+ __ bind(&load_false_y);
+ __ mov(Operand(esp, 1 * kInt32Size), Immediate(0x0));
+ __ bind(&done_y);
+
+ __ CompareRoot(z_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_z, Label::kNear);
+ __ mov(Operand(esp, 2 * kInt32Size), Immediate(-1));
+ __ jmp(&done_z, Label::kNear);
+ __ bind(&load_false_z);
+ __ mov(Operand(esp, 2 * kInt32Size), Immediate(0x0));
+ __ bind(&done_z);
+
+ __ CompareRoot(w_reg, Heap::kTrueValueRootIndex);
+ __ j(not_equal, &load_false_w, Label::kNear);
+ __ mov(Operand(esp, 3 * kInt32Size), Immediate(-1));
+ __ jmp(&done_w, Label::kNear);
+ __ bind(&load_false_w);
+ __ mov(Operand(esp, 3 * kInt32Size), Immediate(0x0));
+ __ bind(&done_w);
+
+ __ movups(result_reg, Operand(esp, 0));
+ __ add(esp, Immediate(kInt32x4Size));
+ return;
+ }
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+
#undef __
} } // namespace v8::internal
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698