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

Side by Side Diff: src/x64/lithium-codegen-x64.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 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-gap-resolver-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 Register LCodeGen::ToRegister(int index) const { 373 Register LCodeGen::ToRegister(int index) const {
374 return Register::FromAllocationIndex(index); 374 return Register::FromAllocationIndex(index);
375 } 375 }
376 376
377 377
378 XMMRegister LCodeGen::ToDoubleRegister(int index) const { 378 XMMRegister LCodeGen::ToDoubleRegister(int index) const {
379 return XMMRegister::FromAllocationIndex(index); 379 return XMMRegister::FromAllocationIndex(index);
380 } 380 }
381 381
382 382
383 XMMRegister LCodeGen::ToFloat32x4Register(int index) const {
384 return Float32x4Register::FromAllocationIndex(index);
385 }
386
387
388 XMMRegister LCodeGen::ToInt32x4Register(int index) const {
389 return Int32x4Register::FromAllocationIndex(index);
390 }
391
392
383 Register LCodeGen::ToRegister(LOperand* op) const { 393 Register LCodeGen::ToRegister(LOperand* op) const {
384 ASSERT(op->IsRegister()); 394 ASSERT(op->IsRegister());
385 return ToRegister(op->index()); 395 return ToRegister(op->index());
386 } 396 }
387 397
388 398
389 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 399 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
390 ASSERT(op->IsDoubleRegister()); 400 ASSERT(op->IsDoubleRegister());
391 return ToDoubleRegister(op->index()); 401 return ToDoubleRegister(op->index());
392 } 402 }
393 403
394 404
405 XMMRegister LCodeGen::ToFloat32x4Register(LOperand* op) const {
406 ASSERT(op->IsFloat32x4Register());
407 return ToFloat32x4Register(op->index());
408 }
409
410
411 XMMRegister LCodeGen::ToInt32x4Register(LOperand* op) const {
412 ASSERT(op->IsInt32x4Register());
413 return ToInt32x4Register(op->index());
414 }
415
416
395 bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { 417 bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const {
396 return op->IsConstantOperand() && 418 return op->IsConstantOperand() &&
397 chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); 419 chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
398 } 420 }
399 421
400 422
401 bool LCodeGen::IsSmiConstant(LConstantOperand* op) const { 423 bool LCodeGen::IsSmiConstant(LConstantOperand* op) const {
402 return op->IsConstantOperand() && 424 return op->IsConstantOperand() &&
403 chunk_->LookupLiteralRepresentation(op).IsSmi(); 425 chunk_->LookupLiteralRepresentation(op).IsSmi();
404 } 426 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 467
446 static int ArgumentsOffsetWithoutFrame(int index) { 468 static int ArgumentsOffsetWithoutFrame(int index) {
447 ASSERT(index < 0); 469 ASSERT(index < 0);
448 return -(index + 1) * kPointerSize + kPCOnStackSize; 470 return -(index + 1) * kPointerSize + kPCOnStackSize;
449 } 471 }
450 472
451 473
452 Operand LCodeGen::ToOperand(LOperand* op) const { 474 Operand LCodeGen::ToOperand(LOperand* op) const {
453 // Does not handle registers. In X64 assembler, plain registers are not 475 // Does not handle registers. In X64 assembler, plain registers are not
454 // representable as an Operand. 476 // representable as an Operand.
455 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 477 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot() ||
478 op->IsFloat32x4StackSlot() || op->IsInt32x4StackSlot());
456 if (NeedsEagerFrame()) { 479 if (NeedsEagerFrame()) {
457 return Operand(rbp, StackSlotOffset(op->index())); 480 return Operand(rbp, StackSlotOffset(op->index()));
458 } else { 481 } else {
459 // Retrieve parameter without eager stack-frame relative to the 482 // Retrieve parameter without eager stack-frame relative to the
460 // stack-pointer. 483 // stack-pointer.
461 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index())); 484 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index()));
462 } 485 }
463 } 486 }
464 487
465 488
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 if (op->IsStackSlot()) { 581 if (op->IsStackSlot()) {
559 if (is_tagged) { 582 if (is_tagged) {
560 translation->StoreStackSlot(op->index()); 583 translation->StoreStackSlot(op->index());
561 } else if (is_uint32) { 584 } else if (is_uint32) {
562 translation->StoreUint32StackSlot(op->index()); 585 translation->StoreUint32StackSlot(op->index());
563 } else { 586 } else {
564 translation->StoreInt32StackSlot(op->index()); 587 translation->StoreInt32StackSlot(op->index());
565 } 588 }
566 } else if (op->IsDoubleStackSlot()) { 589 } else if (op->IsDoubleStackSlot()) {
567 translation->StoreDoubleStackSlot(op->index()); 590 translation->StoreDoubleStackSlot(op->index());
591 } else if (op->IsFloat32x4StackSlot()) {
592 translation->StoreFloat32x4StackSlot(op->index());
593 } else if (op->IsInt32x4StackSlot()) {
594 translation->StoreInt32x4StackSlot(op->index());
568 } else if (op->IsArgument()) { 595 } else if (op->IsArgument()) {
569 ASSERT(is_tagged); 596 ASSERT(is_tagged);
570 int src_index = GetStackSlotCount() + op->index(); 597 int src_index = GetStackSlotCount() + op->index();
571 translation->StoreStackSlot(src_index); 598 translation->StoreStackSlot(src_index);
572 } else if (op->IsRegister()) { 599 } else if (op->IsRegister()) {
573 Register reg = ToRegister(op); 600 Register reg = ToRegister(op);
574 if (is_tagged) { 601 if (is_tagged) {
575 translation->StoreRegister(reg); 602 translation->StoreRegister(reg);
576 } else if (is_uint32) { 603 } else if (is_uint32) {
577 translation->StoreUint32Register(reg); 604 translation->StoreUint32Register(reg);
578 } else { 605 } else {
579 translation->StoreInt32Register(reg); 606 translation->StoreInt32Register(reg);
580 } 607 }
581 } else if (op->IsDoubleRegister()) { 608 } else if (op->IsDoubleRegister()) {
582 XMMRegister reg = ToDoubleRegister(op); 609 XMMRegister reg = ToDoubleRegister(op);
583 translation->StoreDoubleRegister(reg); 610 translation->StoreDoubleRegister(reg);
611 } else if (op->IsFloat32x4Register()) {
612 XMMRegister reg = ToFloat32x4Register(op);
613 translation->StoreFloat32x4Register(reg);
614 } else if (op->IsInt32x4Register()) {
615 XMMRegister reg = ToInt32x4Register(op);
616 translation->StoreInt32x4Register(reg);
584 } else if (op->IsConstantOperand()) { 617 } else if (op->IsConstantOperand()) {
585 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); 618 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
586 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); 619 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
587 translation->StoreLiteral(src_index); 620 translation->StoreLiteral(src_index);
588 } else { 621 } else {
589 UNREACHABLE(); 622 UNREACHABLE();
590 } 623 }
591 } 624 }
592 625
593 626
(...skipping 2385 matching lines...) Expand 10 before | Expand all | Expand 10 after
2979 // Even though the HLoad/StoreKeyed (in this case) instructions force 3012 // Even though the HLoad/StoreKeyed (in this case) instructions force
2980 // the input representation for the key to be an integer, the input 3013 // the input representation for the key to be an integer, the input
2981 // gets replaced during bound check elimination with the index argument 3014 // gets replaced during bound check elimination with the index argument
2982 // to the bounds check, which can be tagged, so that case must be 3015 // to the bounds check, which can be tagged, so that case must be
2983 // handled here, too. 3016 // handled here, too.
2984 if (instr->hydrogen()->IsDehoisted()) { 3017 if (instr->hydrogen()->IsDehoisted()) {
2985 // Sign extend key because it could be a 32 bit negative value 3018 // Sign extend key because it could be a 32 bit negative value
2986 // and the dehoisted address computation happens in 64 bits 3019 // and the dehoisted address computation happens in 64 bits
2987 __ movsxlq(key_reg, key_reg); 3020 __ movsxlq(key_reg, key_reg);
2988 } 3021 }
3022
3023 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
3024 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3025 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16.
3026 __ shl(key_reg, Immediate(0x1));
3027 }
2989 } 3028 }
2990 Operand operand(BuildFastArrayOperand( 3029 Operand operand(BuildFastArrayOperand(
2991 instr->elements(), 3030 instr->elements(),
2992 key, 3031 key,
2993 elements_kind, 3032 elements_kind,
2994 0, 3033 0,
2995 instr->additional_index())); 3034 instr->additional_index()));
2996 3035
2997 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 3036 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
2998 XMMRegister result(ToDoubleRegister(instr->result())); 3037 XMMRegister result(ToDoubleRegister(instr->result()));
2999 __ movss(result, operand); 3038 __ movss(result, operand);
3000 __ cvtss2sd(result, result); 3039 __ cvtss2sd(result, result);
3001 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3040 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3002 __ movsd(ToDoubleRegister(instr->result()), operand); 3041 __ movsd(ToDoubleRegister(instr->result()), operand);
3042 } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) {
3043 __ movups(ToFloat32x4Register(instr->result()), operand);
3044 if (!key->IsConstantOperand()) {
3045 // Restore the index register.
3046 __ shr(ToRegister(key), Immediate(0x1));
3047 }
3048 } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3049 __ movups(ToInt32x4Register(instr->result()), operand);
3050 if (!key->IsConstantOperand()) {
3051 // Restore the index register.
3052 __ shr(ToRegister(key), Immediate(0x1));
3053 }
3003 } else { 3054 } else {
3004 Register result(ToRegister(instr->result())); 3055 Register result(ToRegister(instr->result()));
3005 switch (elements_kind) { 3056 switch (elements_kind) {
3006 case EXTERNAL_BYTE_ELEMENTS: 3057 case EXTERNAL_BYTE_ELEMENTS:
3007 __ movsxbq(result, operand); 3058 __ movsxbq(result, operand);
3008 break; 3059 break;
3009 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3060 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3010 case EXTERNAL_PIXEL_ELEMENTS: 3061 case EXTERNAL_PIXEL_ELEMENTS:
3011 __ movzxbq(result, operand); 3062 __ movzxbq(result, operand);
3012 break; 3063 break;
3013 case EXTERNAL_SHORT_ELEMENTS: 3064 case EXTERNAL_SHORT_ELEMENTS:
3014 __ movsxwq(result, operand); 3065 __ movsxwq(result, operand);
3015 break; 3066 break;
3016 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3067 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3017 __ movzxwq(result, operand); 3068 __ movzxwq(result, operand);
3018 break; 3069 break;
3019 case EXTERNAL_INT_ELEMENTS: 3070 case EXTERNAL_INT_ELEMENTS:
3020 __ movsxlq(result, operand); 3071 __ movsxlq(result, operand);
3021 break; 3072 break;
3022 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3073 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3023 __ movl(result, operand); 3074 __ movl(result, operand);
3024 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3075 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3025 __ testl(result, result); 3076 __ testl(result, result);
3026 DeoptimizeIf(negative, instr->environment()); 3077 DeoptimizeIf(negative, instr->environment());
3027 } 3078 }
3028 break; 3079 break;
3029 case EXTERNAL_FLOAT_ELEMENTS: 3080 case EXTERNAL_FLOAT_ELEMENTS:
3030 case EXTERNAL_DOUBLE_ELEMENTS: 3081 case EXTERNAL_DOUBLE_ELEMENTS:
3082 case EXTERNAL_FLOAT32x4_ELEMENTS:
3083 case EXTERNAL_INT32x4_ELEMENTS:
3031 case FAST_ELEMENTS: 3084 case FAST_ELEMENTS:
3032 case FAST_SMI_ELEMENTS: 3085 case FAST_SMI_ELEMENTS:
3033 case FAST_DOUBLE_ELEMENTS: 3086 case FAST_DOUBLE_ELEMENTS:
3034 case FAST_HOLEY_ELEMENTS: 3087 case FAST_HOLEY_ELEMENTS:
3035 case FAST_HOLEY_SMI_ELEMENTS: 3088 case FAST_HOLEY_SMI_ELEMENTS:
3036 case FAST_HOLEY_DOUBLE_ELEMENTS: 3089 case FAST_HOLEY_DOUBLE_ELEMENTS:
3037 case DICTIONARY_ELEMENTS: 3090 case DICTIONARY_ELEMENTS:
3038 case NON_STRICT_ARGUMENTS_ELEMENTS: 3091 case NON_STRICT_ARGUMENTS_ELEMENTS:
3039 UNREACHABLE(); 3092 UNREACHABLE();
3040 break; 3093 break;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3132 3185
3133 3186
3134 Operand LCodeGen::BuildFastArrayOperand( 3187 Operand LCodeGen::BuildFastArrayOperand(
3135 LOperand* elements_pointer, 3188 LOperand* elements_pointer,
3136 LOperand* key, 3189 LOperand* key,
3137 ElementsKind elements_kind, 3190 ElementsKind elements_kind,
3138 uint32_t offset, 3191 uint32_t offset,
3139 uint32_t additional_index) { 3192 uint32_t additional_index) {
3140 Register elements_pointer_reg = ToRegister(elements_pointer); 3193 Register elements_pointer_reg = ToRegister(elements_pointer);
3141 int shift_size = ElementsKindToShiftSize(elements_kind); 3194 int shift_size = ElementsKindToShiftSize(elements_kind);
3195 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
3196 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3197 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16.
3198 additional_index *= 2;
3199 }
3142 if (key->IsConstantOperand()) { 3200 if (key->IsConstantOperand()) {
3143 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); 3201 int32_t constant_value = ToInteger32(LConstantOperand::cast(key));
3144 if (constant_value & 0xF0000000) { 3202 if (constant_value & 0xF0000000) {
3145 Abort(kArrayIndexConstantValueTooBig); 3203 Abort(kArrayIndexConstantValueTooBig);
3146 } 3204 }
3205 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
3206 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3207 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16.
3208 constant_value *= 2;
3209 }
3147 return Operand(elements_pointer_reg, 3210 return Operand(elements_pointer_reg,
3148 ((constant_value + additional_index) << shift_size) 3211 ((constant_value + additional_index) << shift_size)
3149 + offset); 3212 + offset);
3150 } else { 3213 } else {
3151 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 3214 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
3215 // For Float32x4, make sure the index register is doubled before
3216 // calling this function and restored after its usage.
3152 return Operand(elements_pointer_reg, 3217 return Operand(elements_pointer_reg,
3153 ToRegister(key), 3218 ToRegister(key),
3154 scale_factor, 3219 scale_factor,
3155 offset + (additional_index << shift_size)); 3220 offset + (additional_index << shift_size));
3156 } 3221 }
3157 } 3222 }
3158 3223
3159 3224
3160 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 3225 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3161 ASSERT(ToRegister(instr->context()).is(rsi)); 3226 ASSERT(ToRegister(instr->context()).is(rsi));
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
3691 3756
3692 // Square root. 3757 // Square root.
3693 __ bind(&sqrt); 3758 __ bind(&sqrt);
3694 __ xorps(xmm_scratch, xmm_scratch); 3759 __ xorps(xmm_scratch, xmm_scratch);
3695 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. 3760 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
3696 __ sqrtsd(input_reg, input_reg); 3761 __ sqrtsd(input_reg, input_reg);
3697 __ bind(&done); 3762 __ bind(&done);
3698 } 3763 }
3699 3764
3700 3765
3766 void LCodeGen::DoNullarySIMDOperation(LNullarySIMDOperation* instr) {
3767 switch (instr->op()) {
3768 case kFloat32x4Zero: {
3769 XMMRegister result_reg = ToFloat32x4Register(instr->result());
3770 __ xorps(result_reg, result_reg);
3771 return;
3772 }
3773 default:
3774 UNREACHABLE();
3775 return;
3776 }
3777 }
3778
3779
3780 void LCodeGen::DoUnarySIMDOperation(LUnarySIMDOperation* instr) {
3781 uint8_t select = 0;
3782 switch (instr->op()) {
3783 case kFloat32x4OrInt32x4Change: {
3784 Comment(";;; deoptimize: can not perform representation change"
3785 "for float32x4 or int32x4");
3786 DeoptimizeIf(no_condition, instr->environment());
3787 return;
3788 }
3789 case kSIMDAbs:
3790 case kSIMDNeg:
3791 case kSIMDReciprocal:
3792 case kSIMDReciprocalSqrt:
3793 case kSIMDSqrt: {
3794 ASSERT(instr->value()->Equals(instr->result()));
3795 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
3796 XMMRegister input_reg = ToFloat32x4Register(instr->value());
3797 switch (instr->op()) {
3798 case kSIMDAbs:
3799 __ absps(input_reg);
3800 break;
3801 case kSIMDNeg:
3802 __ negateps(input_reg);
3803 break;
3804 case kSIMDReciprocal:
3805 __ rcpps(input_reg, input_reg);
3806 break;
3807 case kSIMDReciprocalSqrt:
3808 __ rsqrtps(input_reg, input_reg);
3809 break;
3810 case kSIMDSqrt:
3811 __ sqrtps(input_reg, input_reg);
3812 break;
3813 default:
3814 UNREACHABLE();
3815 break;
3816 }
3817 return;
3818 }
3819 case kSIMDNot:
3820 case kSIMDNegU32: {
3821 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
3822 XMMRegister input_reg = ToInt32x4Register(instr->value());
3823 switch (instr->op()) {
3824 case kSIMDNot:
3825 __ notps(input_reg);
3826 break;
3827 case kSIMDNegU32:
3828 __ pnegd(input_reg);
3829 break;
3830 default:
3831 UNREACHABLE();
3832 break;
3833 }
3834 return;
3835 }
3836 case kSIMDBitsToFloat32x4:
3837 case kSIMDToFloat32x4: {
3838 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
3839 XMMRegister input_reg = ToInt32x4Register(instr->value());
3840 XMMRegister result_reg = ToFloat32x4Register(instr->result());
3841 if (instr->op() == kSIMDBitsToFloat32x4) {
3842 if (!result_reg.is(input_reg)) {
3843 __ movaps(result_reg, input_reg);
3844 }
3845 } else {
3846 ASSERT(instr->op() == kSIMDToFloat32x4);
3847 __ cvtdq2ps(result_reg, input_reg);
3848 }
3849 return;
3850 }
3851 case kSIMDBitsToInt32x4:
3852 case kSIMDToInt32x4: {
3853 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
3854 XMMRegister input_reg = ToFloat32x4Register(instr->value());
3855 XMMRegister result_reg = ToInt32x4Register(instr->result());
3856 if (instr->op() == kSIMDBitsToInt32x4) {
3857 if (!result_reg.is(input_reg)) {
3858 __ movaps(result_reg, input_reg);
3859 }
3860 } else {
3861 ASSERT(instr->op() == kSIMDToInt32x4);
3862 __ cvtps2dq(result_reg, input_reg);
3863 }
3864 return;
3865 }
3866 case kFloat32x4Splat: {
3867 ASSERT(instr->hydrogen()->value()->representation().IsDouble());
3868 XMMRegister input_reg = ToDoubleRegister(instr->value());
3869 XMMRegister result_reg = ToFloat32x4Register(instr->result());
3870 XMMRegister xmm_scratch = xmm0;
3871 __ xorps(xmm_scratch, xmm_scratch);
3872 __ cvtsd2ss(xmm_scratch, input_reg);
3873 __ shufps(xmm_scratch, xmm_scratch, 0x0);
3874 __ movaps(result_reg, xmm_scratch);
3875 return;
3876 }
3877 case kInt32x4Splat: {
3878 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
3879 Register input_reg = ToRegister(instr->value());
3880 XMMRegister result_reg = ToInt32x4Register(instr->result());
3881 __ movd(result_reg, input_reg);
3882 __ shufps(result_reg, result_reg, 0x0);
3883 return;
3884 }
3885 case kInt32x4SignMask: {
3886 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
3887 XMMRegister input_reg = ToInt32x4Register(instr->value());
3888 Register result = ToRegister(instr->result());
3889 __ movmskps(result, input_reg);
3890 return;
3891 }
3892 case kFloat32x4SignMask: {
3893 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
3894 XMMRegister input_reg = ToFloat32x4Register(instr->value());
3895 Register result = ToRegister(instr->result());
3896 __ movmskps(result, input_reg);
3897 return;
3898 }
3899 case kFloat32x4W:
3900 select++;
3901 case kFloat32x4Z:
3902 select++;
3903 case kFloat32x4Y:
3904 select++;
3905 case kFloat32x4X: {
3906 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
3907 XMMRegister input_reg = ToFloat32x4Register(instr->value());
3908 XMMRegister result = ToDoubleRegister(instr->result());
3909 XMMRegister xmm_scratch = result.is(input_reg) ? xmm0 : result;
3910
3911 if (select == 0x0) {
3912 __ xorps(xmm_scratch, xmm_scratch);
3913 __ cvtss2sd(xmm_scratch, input_reg);
3914 if (!xmm_scratch.is(result)) {
3915 __ movaps(result, xmm_scratch);
3916 }
3917 } else {
3918 __ pshufd(xmm_scratch, input_reg, select);
3919 if (!xmm_scratch.is(result)) {
3920 __ xorps(result, result);
3921 }
3922 __ cvtss2sd(result, xmm_scratch);
3923 }
3924 return;
3925 }
3926 case kInt32x4X:
3927 case kInt32x4Y:
3928 case kInt32x4Z:
3929 case kInt32x4W:
3930 case kInt32x4FlagX:
3931 case kInt32x4FlagY:
3932 case kInt32x4FlagZ:
3933 case kInt32x4FlagW: {
3934 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
3935 bool flag = false;
3936 switch (instr->op()) {
3937 case kInt32x4FlagX:
3938 flag = true;
3939 case kInt32x4X:
3940 break;
3941 case kInt32x4FlagY:
3942 flag = true;
3943 case kInt32x4Y:
3944 select = 0x1;
3945 break;
3946 case kInt32x4FlagZ:
3947 flag = true;
3948 case kInt32x4Z:
3949 select = 0x2;
3950 break;
3951 case kInt32x4FlagW:
3952 flag = true;
3953 case kInt32x4W:
3954 select = 0x3;
3955 break;
3956 default:
3957 UNREACHABLE();
3958 }
3959
3960 XMMRegister input_reg = ToInt32x4Register(instr->value());
3961 Register result = ToRegister(instr->result());
3962 if (select == 0x0) {
3963 __ movd(result, input_reg);
3964 } else {
3965 if (CpuFeatures::IsSupported(SSE4_1)) {
3966 CpuFeatureScope scope(masm(), SSE4_1);
3967 __ extractps(result, input_reg, select);
3968 } else {
3969 XMMRegister xmm_scratch = xmm0;
3970 __ pshufd(xmm_scratch, input_reg, select);
3971 __ movd(result, xmm_scratch);
3972 }
3973 }
3974
3975 if (flag) {
3976 Label false_value, done;
3977 __ testl(result, result);
3978 __ j(zero, &false_value, Label::kNear);
3979 __ LoadRoot(result, Heap::kTrueValueRootIndex);
3980 __ jmp(&done, Label::kNear);
3981 __ bind(&false_value);
3982 __ LoadRoot(result, Heap::kFalseValueRootIndex);
3983 __ bind(&done);
3984 }
3985 return;
3986 }
3987 default:
3988 UNREACHABLE();
3989 return;
3990 }
3991 }
3992
3993
3994 void LCodeGen::DoBinarySIMDOperation(LBinarySIMDOperation* instr) {
3995 uint8_t imm8 = 0; // for with operation
3996 switch (instr->op()) {
3997 case kSIMDAdd:
3998 case kSIMDSub:
3999 case kSIMDMul:
4000 case kSIMDDiv:
4001 case kSIMDMin:
4002 case kSIMDMax: {
4003 ASSERT(instr->left()->Equals(instr->result()));
4004 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
4005 ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
4006 XMMRegister left_reg = ToFloat32x4Register(instr->left());
4007 XMMRegister right_reg = ToFloat32x4Register(instr->right());
4008 switch (instr->op()) {
4009 case kSIMDAdd:
4010 __ addps(left_reg, right_reg);
4011 break;
4012 case kSIMDSub:
4013 __ subps(left_reg, right_reg);
4014 break;
4015 case kSIMDMul:
4016 __ mulps(left_reg, right_reg);
4017 break;
4018 case kSIMDDiv:
4019 __ divps(left_reg, right_reg);
4020 break;
4021 case kSIMDMin:
4022 __ minps(left_reg, right_reg);
4023 break;
4024 case kSIMDMax:
4025 __ maxps(left_reg, right_reg);
4026 break;
4027 default:
4028 UNREACHABLE();
4029 break;
4030 }
4031 return;
4032 }
4033 case kSIMDScale: {
4034 ASSERT(instr->left()->Equals(instr->result()));
4035 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
4036 ASSERT(instr->hydrogen()->right()->representation().IsDouble());
4037 XMMRegister left_reg = ToFloat32x4Register(instr->left());
4038 XMMRegister right_reg = ToDoubleRegister(instr->right());
4039 XMMRegister scratch_reg = xmm0;
4040 __ xorps(scratch_reg, scratch_reg);
4041 __ cvtsd2ss(scratch_reg, right_reg);
4042 __ shufps(scratch_reg, scratch_reg, 0x0);
4043 __ mulps(left_reg, scratch_reg);
4044 return;
4045 }
4046 case kSIMDShuffle: {
4047 ASSERT(instr->left()->Equals(instr->result()));
4048 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
4049 if (instr->hydrogen()->right()->IsConstant() &&
4050 HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
4051 int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
4052 uint8_t select = static_cast<uint8_t>(value & 0xFF);
4053 XMMRegister left_reg = ToFloat32x4Register(instr->left());
4054 __ shufps(left_reg, left_reg, select);
4055 return;
4056 } else {
4057 Comment(";;; deoptimize: non-constant selector for shuffle");
4058 DeoptimizeIf(no_condition, instr->environment());
4059 return;
4060 }
4061 }
4062 case kSIMDShuffleU32: {
4063 ASSERT(instr->left()->Equals(instr->result()));
4064 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
4065 if (instr->hydrogen()->right()->IsConstant() &&
4066 HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
4067 int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
4068 uint8_t select = static_cast<uint8_t>(value & 0xFF);
4069 XMMRegister left_reg = ToInt32x4Register(instr->left());
4070 __ pshufd(left_reg, left_reg, select);
4071 return;
4072 } else {
4073 Comment(";;; deoptimize: non-constant selector for shuffle");
4074 DeoptimizeIf(no_condition, instr->environment());
4075 return;
4076 }
4077 }
4078 case kSIMDLessThan:
4079 case kSIMDLessThanOrEqual:
4080 case kSIMDEqual:
4081 case kSIMDNotEqual:
4082 case kSIMDGreaterThanOrEqual:
4083 case kSIMDGreaterThan: {
4084 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
4085 ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
4086 XMMRegister left_reg = ToFloat32x4Register(instr->left());
4087 XMMRegister right_reg = ToFloat32x4Register(instr->right());
4088 XMMRegister result_reg = ToInt32x4Register(instr->result());
4089 switch (instr->op()) {
4090 case kSIMDLessThan:
4091 if (result_reg.is(left_reg)) {
4092 __ cmpltps(result_reg, right_reg);
4093 } else if (result_reg.is(right_reg)) {
4094 __ cmpnltps(result_reg, left_reg);
4095 } else {
4096 __ movaps(result_reg, left_reg);
4097 __ cmpltps(result_reg, right_reg);
4098 }
4099 break;
4100 case kSIMDLessThanOrEqual:
4101 if (result_reg.is(left_reg)) {
4102 __ cmpleps(result_reg, right_reg);
4103 } else if (result_reg.is(right_reg)) {
4104 __ cmpnleps(result_reg, left_reg);
4105 } else {
4106 __ movaps(result_reg, left_reg);
4107 __ cmpleps(result_reg, right_reg);
4108 }
4109 break;
4110 case kSIMDEqual:
4111 if (result_reg.is(left_reg)) {
4112 __ cmpeqps(result_reg, right_reg);
4113 } else if (result_reg.is(right_reg)) {
4114 __ cmpeqps(result_reg, left_reg);
4115 } else {
4116 __ movaps(result_reg, left_reg);
4117 __ cmpeqps(result_reg, right_reg);
4118 }
4119 break;
4120 case kSIMDNotEqual:
4121 if (result_reg.is(left_reg)) {
4122 __ cmpneqps(result_reg, right_reg);
4123 } else if (result_reg.is(right_reg)) {
4124 __ cmpneqps(result_reg, left_reg);
4125 } else {
4126 __ movaps(result_reg, left_reg);
4127 __ cmpneqps(result_reg, right_reg);
4128 }
4129 break;
4130 case kSIMDGreaterThanOrEqual:
4131 if (result_reg.is(left_reg)) {
4132 __ cmpnltps(result_reg, right_reg);
4133 } else if (result_reg.is(right_reg)) {
4134 __ cmpltps(result_reg, left_reg);
4135 } else {
4136 __ movaps(result_reg, left_reg);
4137 __ cmpnltps(result_reg, right_reg);
4138 }
4139 break;
4140 case kSIMDGreaterThan:
4141 if (result_reg.is(left_reg)) {
4142 __ cmpnleps(result_reg, right_reg);
4143 } else if (result_reg.is(right_reg)) {
4144 __ cmpleps(result_reg, left_reg);
4145 } else {
4146 __ movaps(result_reg, left_reg);
4147 __ cmpnleps(result_reg, right_reg);
4148 }
4149 break;
4150 default:
4151 UNREACHABLE();
4152 break;
4153 }
4154 return;
4155 }
4156 case kSIMDAnd:
4157 case kSIMDOr:
4158 case kSIMDXor:
4159 case kSIMDAddU32:
4160 case kSIMDSubU32:
4161 case kSIMDMulU32: {
4162 ASSERT(instr->left()->Equals(instr->result()));
4163 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
4164 ASSERT(instr->hydrogen()->right()->representation().IsInt32x4());
4165 XMMRegister left_reg = ToInt32x4Register(instr->left());
4166 XMMRegister right_reg = ToInt32x4Register(instr->right());
4167 switch (instr->op()) {
4168 case kSIMDAnd:
4169 __ andps(left_reg, right_reg);
4170 break;
4171 case kSIMDOr:
4172 __ orps(left_reg, right_reg);
4173 break;
4174 case kSIMDXor:
4175 __ xorps(left_reg, right_reg);
4176 break;
4177 case kSIMDAddU32:
4178 __ paddd(left_reg, right_reg);
4179 break;
4180 case kSIMDSubU32:
4181 __ psubd(left_reg, right_reg);
4182 break;
4183 case kSIMDMulU32:
4184 if (CpuFeatures::IsSupported(SSE4_1)) {
4185 CpuFeatureScope scope(masm(), SSE4_1);
4186 __ pmulld(left_reg, right_reg);
4187 } else {
4188 // The algorithm is from http://stackoverflow.com/questions/10500766 /sse-multiplication-of-4-32-bit-integers
4189 XMMRegister xmm_scratch = xmm0;
4190 __ movups(xmm_scratch, left_reg);
4191 __ pmuludq(left_reg, right_reg);
4192 __ psrldq(xmm_scratch, 4);
4193 __ psrldq(right_reg, 4);
4194 __ pmuludq(xmm_scratch, right_reg);
4195 __ pshufd(left_reg, left_reg, 8);
4196 __ pshufd(xmm_scratch, xmm_scratch, 8);
4197 __ punpackldq(left_reg, xmm_scratch);
4198 }
4199 break;
4200 default:
4201 UNREACHABLE();
4202 break;
4203 }
4204 return;
4205 }
4206 case kSIMDWithW:
4207 imm8++;
4208 case kSIMDWithZ:
4209 imm8++;
4210 case kSIMDWithY:
4211 imm8++;
4212 case kSIMDWithX: {
4213 ASSERT(instr->left()->Equals(instr->result()));
4214 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
4215 ASSERT(instr->hydrogen()->right()->representation().IsDouble());
4216 XMMRegister left_reg = ToFloat32x4Register(instr->left());
4217 XMMRegister right_reg = ToDoubleRegister(instr->right());
4218 XMMRegister xmm_scratch = xmm0;
4219 __ xorps(xmm_scratch, xmm_scratch);
4220 __ cvtsd2ss(xmm_scratch, right_reg);
4221 if (CpuFeatures::IsSupported(SSE4_1)) {
4222 imm8 = imm8 << 4;
4223 CpuFeatureScope scope(masm(), SSE4_1);
4224 __ insertps(left_reg, xmm_scratch, imm8);
4225 } else {
4226 __ subq(rsp, Immediate(kFloat32x4Size));
4227 __ movups(Operand(rsp, 0), left_reg);
4228 __ movss(Operand(rsp, imm8 * kFloatSize), xmm_scratch);
4229 __ movups(left_reg, Operand(rsp, 0));
4230 __ addq(rsp, Immediate(kFloat32x4Size));
4231 }
4232 return;
4233 }
4234 case kSIMDWithWu32:
4235 imm8++;
4236 case kSIMDWithZu32:
4237 imm8++;
4238 case kSIMDWithYu32:
4239 imm8++;
4240 case kSIMDWithXu32: {
4241 ASSERT(instr->left()->Equals(instr->result()));
4242 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
4243 ASSERT(instr->hydrogen()->right()->representation().IsInteger32());
4244 XMMRegister left_reg = ToInt32x4Register(instr->left());
4245 Register right_reg = ToRegister(instr->right());
4246 if (CpuFeatures::IsSupported(SSE4_1)) {
4247 CpuFeatureScope scope(masm(), SSE4_1);
4248 __ pinsrd(left_reg, right_reg, imm8);
4249 } else {
4250 __ subq(rsp, Immediate(kInt32x4Size));
4251 __ movdqu(Operand(rsp, 0), left_reg);
4252 __ movl(Operand(rsp, imm8 * kFloatSize), right_reg);
4253 __ movdqu(left_reg, Operand(rsp, 0));
4254 __ addq(rsp, Immediate(kInt32x4Size));
4255 }
4256 return;
4257 }
4258 case kSIMDWithFlagW:
4259 imm8++;
4260 case kSIMDWithFlagZ:
4261 imm8++;
4262 case kSIMDWithFlagY:
4263 imm8++;
4264 case kSIMDWithFlagX: {
4265 ASSERT(instr->left()->Equals(instr->result()));
4266 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
4267 ASSERT(instr->hydrogen()->right()->representation().IsTagged());
4268 HType type = instr->hydrogen()->right()->type();
4269 XMMRegister left_reg = ToInt32x4Register(instr->left());
4270 Register right_reg = ToRegister(instr->right());
4271 Label load_false_value, done;
4272 if (type.IsBoolean()) {
4273 __ subq(rsp, Immediate(kInt32x4Size));
4274 __ movups(Operand(rsp, 0), left_reg);
4275 __ CompareRoot(right_reg, Heap::kTrueValueRootIndex);
4276 __ j(not_equal, &load_false_value, Label::kNear);
4277 } else {
4278 Comment(";;; deoptimize: other types for SIMD.withFlagX/Y/Z/W.");
4279 DeoptimizeIf(no_condition, instr->environment());
4280 return;
4281 }
4282 // load true value.
4283 __ movl(Operand(rsp, imm8 * kFloatSize), Immediate(0xFFFFFFFF));
4284 __ jmp(&done, Label::kNear);
4285 __ bind(&load_false_value);
4286 __ movl(Operand(rsp, imm8 * kFloatSize), Immediate(0x0));
4287 __ bind(&done);
4288 __ movups(left_reg, Operand(rsp, 0));
4289 __ addq(rsp, Immediate(kInt32x4Size));
4290 return;
4291 }
4292 default:
4293 UNREACHABLE();
4294 return;
4295 }
4296 }
4297
4298
4299 void LCodeGen::DoTernarySIMDOperation(LTernarySIMDOperation* instr) {
4300 switch (instr->op()) {
4301 case kSIMDSelect: {
4302 ASSERT(instr->hydrogen()->first()->representation().IsInt32x4());
4303 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
4304 ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
4305
4306 XMMRegister mask_reg = ToInt32x4Register(instr->first());
4307 XMMRegister left_reg = ToFloat32x4Register(instr->second());
4308 XMMRegister right_reg = ToFloat32x4Register(instr->third());
4309 XMMRegister result_reg = ToFloat32x4Register(instr->result());
4310 XMMRegister temp_reg = xmm0;
4311
4312 // Copy mask.
4313 __ movaps(temp_reg, mask_reg);
4314 // Invert it.
4315 __ notps(temp_reg);
4316 // temp_reg = temp_reg & falseValue.
4317 __ andps(temp_reg, right_reg);
4318
4319 if (!result_reg.is(mask_reg)) {
4320 if (result_reg.is(left_reg)) {
4321 // result_reg = result_reg & trueValue.
4322 __ andps(result_reg, mask_reg);
4323 // out = result_reg | temp_reg.
4324 __ orps(result_reg, temp_reg);
4325 } else {
4326 __ movaps(result_reg, mask_reg);
4327 // result_reg = result_reg & trueValue.
4328 __ andps(result_reg, left_reg);
4329 // out = result_reg | temp_reg.
4330 __ orps(result_reg, temp_reg);
4331 }
4332 } else {
4333 // result_reg = result_reg & trueValue.
4334 __ andps(result_reg, left_reg);
4335 // out = result_reg | temp_reg.
4336 __ orps(result_reg, temp_reg);
4337 }
4338 return;
4339 }
4340 case kSIMDShuffleMix: {
4341 ASSERT(instr->first()->Equals(instr->result()));
4342 ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
4343 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
4344 ASSERT(instr->hydrogen()->third()->representation().IsInteger32());
4345 if (instr->hydrogen()->third()->IsConstant() &&
4346 HConstant::cast(instr->hydrogen()->third())->HasInteger32Value()) {
4347 int32_t value = ToInteger32(LConstantOperand::cast(instr->third()));
4348 uint8_t select = static_cast<uint8_t>(value & 0xFF);
4349 XMMRegister first_reg = ToFloat32x4Register(instr->first());
4350 XMMRegister second_reg = ToFloat32x4Register(instr->second());
4351 __ shufps(first_reg, second_reg, select);
4352 return;
4353 } else {
4354 Comment(";;; deoptimize: non-constant selector for shuffle");
4355 DeoptimizeIf(no_condition, instr->environment());
4356 return;
4357 }
4358 }
4359 case kSIMDClamp: {
4360 ASSERT(instr->first()->Equals(instr->result()));
4361 ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
4362 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
4363 ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
4364
4365 XMMRegister value_reg = ToFloat32x4Register(instr->first());
4366 XMMRegister lower_reg = ToFloat32x4Register(instr->second());
4367 XMMRegister upper_reg = ToFloat32x4Register(instr->third());
4368 __ minps(value_reg, upper_reg);
4369 __ maxps(value_reg, lower_reg);
4370 return;
4371 }
4372 default:
4373 UNREACHABLE();
4374 return;
4375 }
4376 }
4377
4378
4379 void LCodeGen::DoQuarternarySIMDOperation(LQuarternarySIMDOperation* instr) {
4380 switch (instr->op()) {
4381 case kFloat32x4Constructor: {
4382 ASSERT(instr->hydrogen()->x()->representation().IsDouble());
4383 ASSERT(instr->hydrogen()->y()->representation().IsDouble());
4384 ASSERT(instr->hydrogen()->z()->representation().IsDouble());
4385 ASSERT(instr->hydrogen()->w()->representation().IsDouble());
4386 XMMRegister x_reg = ToDoubleRegister(instr->x());
4387 XMMRegister y_reg = ToDoubleRegister(instr->y());
4388 XMMRegister z_reg = ToDoubleRegister(instr->z());
4389 XMMRegister w_reg = ToDoubleRegister(instr->w());
4390 XMMRegister result_reg = ToFloat32x4Register(instr->result());
4391 __ subq(rsp, Immediate(kFloat32x4Size));
4392 __ xorps(xmm0, xmm0);
4393 __ cvtsd2ss(xmm0, x_reg);
4394 __ movss(Operand(rsp, 0 * kFloatSize), xmm0);
4395 __ xorps(xmm0, xmm0);
4396 __ cvtsd2ss(xmm0, y_reg);
4397 __ movss(Operand(rsp, 1 * kFloatSize), xmm0);
4398 __ xorps(xmm0, xmm0);
4399 __ cvtsd2ss(xmm0, z_reg);
4400 __ movss(Operand(rsp, 2 * kFloatSize), xmm0);
4401 __ xorps(xmm0, xmm0);
4402 __ cvtsd2ss(xmm0, w_reg);
4403 __ movss(Operand(rsp, 3 * kFloatSize), xmm0);
4404 __ movups(result_reg, Operand(rsp, 0 * kFloatSize));
4405 __ addq(rsp, Immediate(kFloat32x4Size));
4406 return;
4407 }
4408 case kInt32x4Constructor: {
4409 ASSERT(instr->hydrogen()->x()->representation().IsInteger32());
4410 ASSERT(instr->hydrogen()->y()->representation().IsInteger32());
4411 ASSERT(instr->hydrogen()->z()->representation().IsInteger32());
4412 ASSERT(instr->hydrogen()->w()->representation().IsInteger32());
4413 Register x_reg = ToRegister(instr->x());
4414 Register y_reg = ToRegister(instr->y());
4415 Register z_reg = ToRegister(instr->z());
4416 Register w_reg = ToRegister(instr->w());
4417 XMMRegister result_reg = ToInt32x4Register(instr->result());
4418 __ subq(rsp, Immediate(kInt32x4Size));
4419 __ movl(Operand(rsp, 0 * kInt32Size), x_reg);
4420 __ movl(Operand(rsp, 1 * kInt32Size), y_reg);
4421 __ movl(Operand(rsp, 2 * kInt32Size), z_reg);
4422 __ movl(Operand(rsp, 3 * kInt32Size), w_reg);
4423 __ movups(result_reg, Operand(rsp, 0 * kInt32Size));
4424 __ addq(rsp, Immediate(kInt32x4Size));
4425 return;
4426 }
4427 case kInt32x4Bool: {
4428 ASSERT(instr->hydrogen()->x()->representation().IsTagged());
4429 ASSERT(instr->hydrogen()->y()->representation().IsTagged());
4430 ASSERT(instr->hydrogen()->z()->representation().IsTagged());
4431 ASSERT(instr->hydrogen()->w()->representation().IsTagged());
4432 HType x_type = instr->hydrogen()->x()->type();
4433 HType y_type = instr->hydrogen()->y()->type();
4434 HType z_type = instr->hydrogen()->z()->type();
4435 HType w_type = instr->hydrogen()->w()->type();
4436 if (!x_type.IsBoolean() || !y_type.IsBoolean() ||
4437 !z_type.IsBoolean() || !w_type.IsBoolean()) {
4438 Comment(";;; deoptimize: other types for int32x4.bool.");
4439 DeoptimizeIf(no_condition, instr->environment());
4440 return;
4441 }
4442 XMMRegister result_reg = ToInt32x4Register(instr->result());
4443 Register x_reg = ToRegister(instr->x());
4444 Register y_reg = ToRegister(instr->y());
4445 Register z_reg = ToRegister(instr->z());
4446 Register w_reg = ToRegister(instr->w());
4447 Label load_false_x, done_x, load_false_y, done_y,
4448 load_false_z, done_z, load_false_w, done_w;
4449 __ subq(rsp, Immediate(kInt32x4Size));
4450
4451 __ CompareRoot(x_reg, Heap::kTrueValueRootIndex);
4452 __ j(not_equal, &load_false_x, Label::kNear);
4453 __ movl(Operand(rsp, 0 * kInt32Size), Immediate(-1));
4454 __ jmp(&done_x, Label::kNear);
4455 __ bind(&load_false_x);
4456 __ movl(Operand(rsp, 0 * kInt32Size), Immediate(0x0));
4457 __ bind(&done_x);
4458
4459 __ CompareRoot(y_reg, Heap::kTrueValueRootIndex);
4460 __ j(not_equal, &load_false_y, Label::kNear);
4461 __ movl(Operand(rsp, 1 * kInt32Size), Immediate(-1));
4462 __ jmp(&done_y, Label::kNear);
4463 __ bind(&load_false_y);
4464 __ movl(Operand(rsp, 1 * kInt32Size), Immediate(0x0));
4465 __ bind(&done_y);
4466
4467 __ CompareRoot(z_reg, Heap::kTrueValueRootIndex);
4468 __ j(not_equal, &load_false_z, Label::kNear);
4469 __ movl(Operand(rsp, 2 * kInt32Size), Immediate(-1));
4470 __ jmp(&done_z, Label::kNear);
4471 __ bind(&load_false_z);
4472 __ movl(Operand(rsp, 2 * kInt32Size), Immediate(0x0));
4473 __ bind(&done_z);
4474
4475 __ CompareRoot(w_reg, Heap::kTrueValueRootIndex);
4476 __ j(not_equal, &load_false_w, Label::kNear);
4477 __ movl(Operand(rsp, 3 * kInt32Size), Immediate(-1));
4478 __ jmp(&done_w, Label::kNear);
4479 __ bind(&load_false_w);
4480 __ movl(Operand(rsp, 3 * kInt32Size), Immediate(0x0));
4481 __ bind(&done_w);
4482
4483 __ movups(result_reg, Operand(rsp, 0));
4484 __ addq(rsp, Immediate(kInt32x4Size));
4485 return;
4486 }
4487 default:
4488 UNREACHABLE();
4489 return;
4490 }
4491 }
4492
4493
3701 void LCodeGen::DoPower(LPower* instr) { 4494 void LCodeGen::DoPower(LPower* instr) {
3702 Representation exponent_type = instr->hydrogen()->right()->representation(); 4495 Representation exponent_type = instr->hydrogen()->right()->representation();
3703 // Having marked this as a call, we can use any registers. 4496 // Having marked this as a call, we can use any registers.
3704 // Just make sure that the input/output registers are the expected ones. 4497 // Just make sure that the input/output registers are the expected ones.
3705 4498
3706 Register exponent = rdx; 4499 Register exponent = rdx;
3707 ASSERT(!instr->right()->IsRegister() || 4500 ASSERT(!instr->right()->IsRegister() ||
3708 ToRegister(instr->right()).is(exponent)); 4501 ToRegister(instr->right()).is(exponent));
3709 ASSERT(!instr->right()->IsDoubleRegister() || 4502 ASSERT(!instr->right()->IsDoubleRegister() ||
3710 ToDoubleRegister(instr->right()).is(xmm1)); 4503 ToDoubleRegister(instr->right()).is(xmm1));
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
4168 // Even though the HLoad/StoreKeyedFastElement instructions force 4961 // Even though the HLoad/StoreKeyedFastElement instructions force
4169 // the input representation for the key to be an integer, the input 4962 // the input representation for the key to be an integer, the input
4170 // gets replaced during bound check elimination with the index 4963 // gets replaced during bound check elimination with the index
4171 // argument to the bounds check, which can be tagged, so that case 4964 // argument to the bounds check, which can be tagged, so that case
4172 // must be handled here, too. 4965 // must be handled here, too.
4173 if (instr->hydrogen()->IsDehoisted()) { 4966 if (instr->hydrogen()->IsDehoisted()) {
4174 // Sign extend key because it could be a 32 bit negative value 4967 // Sign extend key because it could be a 32 bit negative value
4175 // and the dehoisted address computation happens in 64 bits 4968 // and the dehoisted address computation happens in 64 bits
4176 __ movsxlq(key_reg, key_reg); 4969 __ movsxlq(key_reg, key_reg);
4177 } 4970 }
4971
4972 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
4973 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
4974 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16.
4975 __ shl(key_reg, Immediate(0x1));
4976 }
4178 } 4977 }
4179 Operand operand(BuildFastArrayOperand( 4978 Operand operand(BuildFastArrayOperand(
4180 instr->elements(), 4979 instr->elements(),
4181 key, 4980 key,
4182 elements_kind, 4981 elements_kind,
4183 0, 4982 0,
4184 instr->additional_index())); 4983 instr->additional_index()));
4185 4984
4186 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 4985 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
4187 XMMRegister value(ToDoubleRegister(instr->value())); 4986 XMMRegister value(ToDoubleRegister(instr->value()));
4188 __ cvtsd2ss(value, value); 4987 __ cvtsd2ss(value, value);
4189 __ movss(operand, value); 4988 __ movss(operand, value);
4190 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 4989 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
4191 __ movsd(operand, ToDoubleRegister(instr->value())); 4990 __ movsd(operand, ToDoubleRegister(instr->value()));
4991 } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) {
4992 __ movups(operand, ToFloat32x4Register(instr->value()));
4993 if (!key->IsConstantOperand()) {
4994 // Restore the index register.
4995 __ shr(ToRegister(key), Immediate(0x1));
4996 }
4997 } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
4998 __ movups(operand, ToInt32x4Register(instr->value()));
4999 if (!key->IsConstantOperand()) {
5000 // Restore the index register.
5001 __ shr(ToRegister(key), Immediate(0x1));
5002 }
4192 } else { 5003 } else {
4193 Register value(ToRegister(instr->value())); 5004 Register value(ToRegister(instr->value()));
4194 switch (elements_kind) { 5005 switch (elements_kind) {
4195 case EXTERNAL_PIXEL_ELEMENTS: 5006 case EXTERNAL_PIXEL_ELEMENTS:
4196 case EXTERNAL_BYTE_ELEMENTS: 5007 case EXTERNAL_BYTE_ELEMENTS:
4197 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 5008 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4198 __ movb(operand, value); 5009 __ movb(operand, value);
4199 break; 5010 break;
4200 case EXTERNAL_SHORT_ELEMENTS: 5011 case EXTERNAL_SHORT_ELEMENTS:
4201 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 5012 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4202 __ movw(operand, value); 5013 __ movw(operand, value);
4203 break; 5014 break;
4204 case EXTERNAL_INT_ELEMENTS: 5015 case EXTERNAL_INT_ELEMENTS:
4205 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 5016 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4206 __ movl(operand, value); 5017 __ movl(operand, value);
4207 break; 5018 break;
4208 case EXTERNAL_FLOAT_ELEMENTS: 5019 case EXTERNAL_FLOAT_ELEMENTS:
5020 case EXTERNAL_FLOAT32x4_ELEMENTS:
5021 case EXTERNAL_INT32x4_ELEMENTS:
4209 case EXTERNAL_DOUBLE_ELEMENTS: 5022 case EXTERNAL_DOUBLE_ELEMENTS:
4210 case FAST_ELEMENTS: 5023 case FAST_ELEMENTS:
4211 case FAST_SMI_ELEMENTS: 5024 case FAST_SMI_ELEMENTS:
4212 case FAST_DOUBLE_ELEMENTS: 5025 case FAST_DOUBLE_ELEMENTS:
4213 case FAST_HOLEY_ELEMENTS: 5026 case FAST_HOLEY_ELEMENTS:
4214 case FAST_HOLEY_SMI_ELEMENTS: 5027 case FAST_HOLEY_SMI_ELEMENTS:
4215 case FAST_HOLEY_DOUBLE_ELEMENTS: 5028 case FAST_HOLEY_DOUBLE_ELEMENTS:
4216 case DICTIONARY_ELEMENTS: 5029 case DICTIONARY_ELEMENTS:
4217 case NON_STRICT_ARGUMENTS_ELEMENTS: 5030 case NON_STRICT_ARGUMENTS_ELEMENTS:
4218 UNREACHABLE(); 5031 UNREACHABLE();
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
4691 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 5504 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4692 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 5505 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4693 RecordSafepointWithRegisters( 5506 RecordSafepointWithRegisters(
4694 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 5507 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4695 __ movq(kScratchRegister, rax); 5508 __ movq(kScratchRegister, rax);
4696 } 5509 }
4697 __ movq(reg, kScratchRegister); 5510 __ movq(reg, kScratchRegister);
4698 } 5511 }
4699 5512
4700 5513
5514 void LCodeGen::DoFloat32x4ToTagged(LFloat32x4ToTagged* instr) {
5515 class DeferredFloat32x4ToTagged V8_FINAL : public LDeferredCode {
5516 public:
5517 DeferredFloat32x4ToTagged(LCodeGen* codegen, LFloat32x4ToTagged* instr)
5518 : LDeferredCode(codegen), instr_(instr) { }
5519 virtual void Generate() V8_OVERRIDE {
5520 codegen()->DoDeferredFloat32x4ToTagged(instr_);
5521 }
5522 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5523 private:
5524 LFloat32x4ToTagged* instr_;
5525 };
5526
5527 XMMRegister input_reg = ToFloat32x4Register(instr->value());
5528 Register reg = ToRegister(instr->result());
5529 Register tmp = ToRegister(instr->temp());
5530
5531 DeferredFloat32x4ToTagged* deferred =
5532 new(zone()) DeferredFloat32x4ToTagged(this, instr);
5533 if (FLAG_inline_new) {
5534 __ AllocateFloat32x4(reg, tmp, deferred->entry());
5535 } else {
5536 __ jmp(deferred->entry());
5537 }
5538 __ bind(deferred->exit());
5539 __ movups(FieldOperand(reg, Float32x4::kValueOffset), input_reg);
5540 }
5541
5542
5543 void LCodeGen::DoDeferredFloat32x4ToTagged(LFloat32x4ToTagged* instr) {
5544 // TODO(3095996): Get rid of this. For now, we need to make the
5545 // result register contain a valid pointer because it is already
5546 // contained in the register pointer map.
5547 Register reg = ToRegister(instr->result());
5548 __ Move(reg, Smi::FromInt(0));
5549
5550 {
5551 PushSafepointRegistersScope scope(this);
5552 // Float32x4ToTagged uses the context from the frame, rather than
5553 // the environment's HContext or HInlinedContext value.
5554 // They only call Runtime::kAllocateFloat32x4.
5555 // The corresponding HChange instructions are added in a phase that does
5556 // not have easy access to the local context.
5557 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
5558 __ CallRuntimeSaveDoubles(Runtime::kAllocateFloat32x4);
5559 RecordSafepointWithRegisters(
5560 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5561 __ movq(kScratchRegister, rax);
5562 }
5563 __ movq(reg, kScratchRegister);
5564 }
5565
5566
5567 void LCodeGen::DoInt32x4ToTagged(LInt32x4ToTagged* instr) {
5568 class DeferredInt32x4ToTagged V8_FINAL : public LDeferredCode {
5569 public:
5570 DeferredInt32x4ToTagged(LCodeGen* codegen, LInt32x4ToTagged* instr)
5571 : LDeferredCode(codegen), instr_(instr) { }
5572 virtual void Generate() V8_OVERRIDE {
5573 codegen()->DoDeferredInt32x4ToTagged(instr_);
5574 }
5575 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5576 private:
5577 LInt32x4ToTagged* instr_;
5578 };
5579
5580 XMMRegister input_reg = ToInt32x4Register(instr->value());
5581 Register reg = ToRegister(instr->result());
5582 Register tmp = ToRegister(instr->temp());
5583
5584 DeferredInt32x4ToTagged* deferred =
5585 new(zone()) DeferredInt32x4ToTagged(this, instr);
5586 if (FLAG_inline_new) {
5587 __ AllocateInt32x4(reg, tmp, deferred->entry());
5588 } else {
5589 __ jmp(deferred->entry());
5590 }
5591 __ bind(deferred->exit());
5592 __ movups(FieldOperand(reg, Int32x4::kValueOffset), input_reg);
5593 }
5594
5595
5596 void LCodeGen::DoDeferredInt32x4ToTagged(LInt32x4ToTagged* instr) {
5597 // TODO(3095996): Get rid of this. For now, we need to make the
5598 // result register contain a valid pointer because it is already
5599 // contained in the register pointer map.
5600 Register reg = ToRegister(instr->result());
5601 __ Move(reg, Smi::FromInt(0));
5602
5603 {
5604 PushSafepointRegistersScope scope(this);
5605 // Int32x4ToTagged uses the context from the frame, rather than
5606 // the environment's HContext or HInlinedContext value.
5607 // They only call Runtime::kAllocateInt32x4.
5608 // The corresponding HChange instructions are added in a phase that does
5609 // not have easy access to the local context.
5610 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
5611 __ CallRuntimeSaveDoubles(Runtime::kAllocateInt32x4);
5612 RecordSafepointWithRegisters(
5613 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5614 __ movq(kScratchRegister, rax);
5615 }
5616
5617 __ movq(reg, kScratchRegister);
5618 }
5619
5620
4701 void LCodeGen::DoSmiTag(LSmiTag* instr) { 5621 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4702 ASSERT(instr->value()->Equals(instr->result())); 5622 ASSERT(instr->value()->Equals(instr->result()));
4703 Register input = ToRegister(instr->value()); 5623 Register input = ToRegister(instr->value());
4704 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 5624 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
4705 __ Integer32ToSmi(input, input); 5625 __ Integer32ToSmi(input, input);
4706 } 5626 }
4707 5627
4708 5628
4709 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 5629 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4710 ASSERT(instr->value()->Equals(instr->result())); 5630 ASSERT(instr->value()->Equals(instr->result()));
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
4868 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 5788 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
4869 5789
4870 EmitNumberUntagD(input_reg, result_reg, 5790 EmitNumberUntagD(input_reg, result_reg,
4871 instr->hydrogen()->can_convert_undefined_to_nan(), 5791 instr->hydrogen()->can_convert_undefined_to_nan(),
4872 instr->hydrogen()->deoptimize_on_minus_zero(), 5792 instr->hydrogen()->deoptimize_on_minus_zero(),
4873 instr->environment(), 5793 instr->environment(),
4874 mode); 5794 mode);
4875 } 5795 }
4876 5796
4877 5797
5798 void LCodeGen::DoTaggedToFloat32x4(LTaggedToFloat32x4* instr) {
5799 LOperand* input = instr->value();
5800 ASSERT(input->IsRegister());
5801 LOperand* result = instr->result();
5802 ASSERT(result->IsFloat32x4Register());
5803
5804 Register input_reg = ToRegister(input);
5805 XMMRegister result_reg = ToFloat32x4Register(result);
5806
5807 Condition cc = masm()->CheckSmi(input_reg);
5808 DeoptimizeIf(cc, instr->environment());
5809 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
5810 Heap::kFloat32x4MapRootIndex);
5811 DeoptimizeIf(not_equal, instr->environment());
5812 __ movups(result_reg, FieldOperand(input_reg, Float32x4::kValueOffset));
5813 }
5814
5815
5816 void LCodeGen::DoTaggedToInt32x4(LTaggedToInt32x4* instr) {
5817 LOperand* input = instr->value();
5818 ASSERT(input->IsRegister());
5819 LOperand* result = instr->result();
5820 ASSERT(result->IsInt32x4Register());
5821
5822 Register input_reg = ToRegister(input);
5823 XMMRegister result_reg = ToInt32x4Register(result);
5824
5825 Condition cc = masm()->CheckSmi(input_reg);
5826 DeoptimizeIf(cc, instr->environment());
5827 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
5828 Heap::kInt32x4MapRootIndex);
5829 DeoptimizeIf(not_equal, instr->environment());
5830 __ movups(result_reg, FieldOperand(input_reg, Int32x4::kValueOffset));
5831 }
5832
5833
4878 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 5834 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
4879 LOperand* input = instr->value(); 5835 LOperand* input = instr->value();
4880 ASSERT(input->IsDoubleRegister()); 5836 ASSERT(input->IsDoubleRegister());
4881 LOperand* result = instr->result(); 5837 LOperand* result = instr->result();
4882 ASSERT(result->IsRegister()); 5838 ASSERT(result->IsRegister());
4883 5839
4884 XMMRegister input_reg = ToDoubleRegister(input); 5840 XMMRegister input_reg = ToDoubleRegister(input);
4885 Register result_reg = ToRegister(result); 5841 Register result_reg = ToRegister(result);
4886 5842
4887 if (instr->truncating()) { 5843 if (instr->truncating()) {
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
5329 Label::Distance false_distance = right_block == next_block ? Label::kNear 6285 Label::Distance false_distance = right_block == next_block ? Label::kNear
5330 : Label::kFar; 6286 : Label::kFar;
5331 Condition final_branch_condition = no_condition; 6287 Condition final_branch_condition = no_condition;
5332 if (type_name->Equals(heap()->number_string())) { 6288 if (type_name->Equals(heap()->number_string())) {
5333 __ JumpIfSmi(input, true_label, true_distance); 6289 __ JumpIfSmi(input, true_label, true_distance);
5334 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), 6290 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
5335 Heap::kHeapNumberMapRootIndex); 6291 Heap::kHeapNumberMapRootIndex);
5336 6292
5337 final_branch_condition = equal; 6293 final_branch_condition = equal;
5338 6294
6295 } else if (type_name->Equals(heap()->float32x4_string())) {
6296 __ JumpIfSmi(input, false_label, false_distance);
6297 __ CmpObjectType(input, FLOAT32x4_TYPE, input);
6298 final_branch_condition = equal;
6299
6300 } else if (type_name->Equals(heap()->int32x4_string())) {
6301 __ JumpIfSmi(input, false_label, false_distance);
6302 __ CmpObjectType(input, INT32x4_TYPE, input);
6303 final_branch_condition = equal;
6304
5339 } else if (type_name->Equals(heap()->string_string())) { 6305 } else if (type_name->Equals(heap()->string_string())) {
5340 __ JumpIfSmi(input, false_label, false_distance); 6306 __ JumpIfSmi(input, false_label, false_distance);
5341 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 6307 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
5342 __ j(above_equal, false_label, false_distance); 6308 __ j(above_equal, false_label, false_distance);
5343 __ testb(FieldOperand(input, Map::kBitFieldOffset), 6309 __ testb(FieldOperand(input, Map::kBitFieldOffset),
5344 Immediate(1 << Map::kIsUndetectable)); 6310 Immediate(1 << Map::kIsUndetectable));
5345 final_branch_condition = zero; 6311 final_branch_condition = zero;
5346 6312
5347 } else if (type_name->Equals(heap()->symbol_string())) { 6313 } else if (type_name->Equals(heap()->symbol_string())) {
5348 __ JumpIfSmi(input, false_label, false_distance); 6314 __ JumpIfSmi(input, false_label, false_distance);
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
5639 FixedArray::kHeaderSize - kPointerSize)); 6605 FixedArray::kHeaderSize - kPointerSize));
5640 __ bind(&done); 6606 __ bind(&done);
5641 } 6607 }
5642 6608
5643 6609
5644 #undef __ 6610 #undef __
5645 6611
5646 } } // namespace v8::internal 6612 } } // namespace v8::internal
5647 6613
5648 #endif // V8_TARGET_ARCH_X64 6614 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-gap-resolver-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698