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

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 387733002: Specialize mint shift code on ia32 for a constant shift amount. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 5 months 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 | « runtime/vm/disassembler_ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 5592 matching lines...) Expand 10 before | Expand all | Expand 10 after
5603 Smi::Cast(index_loc.constant()).Value()) || 5603 Smi::Cast(index_loc.constant()).Value()) ||
5604 (Smi::Cast(index_loc.constant()).Value() < 0)); 5604 (Smi::Cast(index_loc.constant()).Value() < 0));
5605 // Unconditionally deoptimize for constant bounds checks because they 5605 // Unconditionally deoptimize for constant bounds checks because they
5606 // only occur only when index is out-of-bounds. 5606 // only occur only when index is out-of-bounds.
5607 __ jmp(deopt); 5607 __ jmp(deopt);
5608 return; 5608 return;
5609 } 5609 }
5610 5610
5611 if (index_loc.IsConstant()) { 5611 if (index_loc.IsConstant()) {
5612 Register length = length_loc.reg(); 5612 Register length = length_loc.reg();
5613 const Object& index = Smi::Cast(index_loc.constant()); 5613 const Smi& index = Smi::Cast(index_loc.constant());
5614 __ cmpl(length, Immediate(reinterpret_cast<int32_t>(index.raw()))); 5614 __ cmpl(length, Immediate(reinterpret_cast<int32_t>(index.raw())));
5615 __ j(BELOW_EQUAL, deopt); 5615 __ j(BELOW_EQUAL, deopt);
5616 } else if (length_loc.IsConstant()) { 5616 } else if (length_loc.IsConstant()) {
5617 const Smi& length = Smi::Cast(length_loc.constant()); 5617 const Smi& length = Smi::Cast(length_loc.constant());
5618 if (index_loc.IsStackSlot()) { 5618 if (index_loc.IsStackSlot()) {
5619 const Address& index = index_loc.ToStackSlotAddress(); 5619 const Address& index = index_loc.ToStackSlotAddress();
5620 __ cmpl(index, Immediate(reinterpret_cast<int32_t>(length.raw()))); 5620 __ cmpl(index, Immediate(reinterpret_cast<int32_t>(length.raw())));
5621 } else { 5621 } else {
5622 Register index = index_loc.reg(); 5622 Register index = index_loc.reg();
5623 __ cmpl(index, Immediate(reinterpret_cast<int32_t>(length.raw()))); 5623 __ cmpl(index, Immediate(reinterpret_cast<int32_t>(length.raw())));
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
5890 5890
5891 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, 5891 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate,
5892 bool opt) const { 5892 bool opt) const {
5893 const intptr_t kNumInputs = 2; 5893 const intptr_t kNumInputs = 2;
5894 const intptr_t kNumTemps = 5894 const intptr_t kNumTemps =
5895 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; 5895 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0;
5896 LocationSummary* summary = new(isolate) LocationSummary( 5896 LocationSummary* summary = new(isolate) LocationSummary(
5897 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5897 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5898 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 5898 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5899 Location::RequiresRegister())); 5899 Location::RequiresRegister()));
5900 summary->set_in(1, Location::RegisterLocation(ECX)); 5900 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
5901 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { 5901 if ((op_kind() == Token::kSHL) && CanDeoptimize()) {
5902 summary->set_temp(0, Location::RequiresRegister()); 5902 summary->set_temp(0, Location::RequiresRegister());
5903 summary->set_temp(1, Location::RequiresRegister()); 5903 summary->set_temp(1, Location::RequiresRegister());
5904 } 5904 }
5905 summary->set_out(0, Location::SameAsFirstInput()); 5905 summary->set_out(0, Location::SameAsFirstInput());
5906 return summary; 5906 return summary;
5907 } 5907 }
5908 5908
5909 5909
5910 static const intptr_t kMintShiftCountLimit = 63; 5910 static const intptr_t kMintShiftCountLimit = 63;
(...skipping 11 matching lines...) Expand all
5922 PairLocation* out_pair = locs()->out(0).AsPairLocation(); 5922 PairLocation* out_pair = locs()->out(0).AsPairLocation();
5923 Register out_lo = out_pair->At(0).reg(); 5923 Register out_lo = out_pair->At(0).reg();
5924 Register out_hi = out_pair->At(1).reg(); 5924 Register out_hi = out_pair->At(1).reg();
5925 ASSERT(out_lo == left_lo); 5925 ASSERT(out_lo == left_lo);
5926 ASSERT(out_hi == left_hi); 5926 ASSERT(out_hi == left_hi);
5927 5927
5928 Label* deopt = NULL; 5928 Label* deopt = NULL;
5929 if (CanDeoptimize()) { 5929 if (CanDeoptimize()) {
5930 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); 5930 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
5931 } 5931 }
5932 // Deoptimize if shift count is > 63. 5932 if (locs()->in(1).IsConstant()) {
5933 // sarl operation masks the count to 5 bits and 5933 // Code for a constant shift amount.
5934 // shrd is undefined with count > operand size (32) 5934 ASSERT(locs()->in(1).constant().IsSmi());
5935 __ SmiUntag(ECX); 5935 const int32_t shift =
5936 if (has_shift_count_check()) { 5936 reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1;
5937 __ cmpl(ECX, Immediate(kMintShiftCountLimit)); 5937 if ((shift < 0) || (shift > kMintShiftCountLimit)) {
srdjan 2014/07/10 23:20:15 For SHR shouldn't 'shift > kMintShiftCountLimit'
regis 2014/07/10 23:59:27 I kept the previous semantics. In the case the shi
5938 __ j(ABOVE, deopt); 5938 __ jmp(deopt);
5939 } 5939 return;
5940 // TODO(regis): Specialize code for constant shift amount. 5940 } else if (shift == 0) {
5941 Label large_shift, done; 5941 // Nothing to do for zero shift amount.
5942 switch (op_kind()) { 5942 return;
5943 case Token::kSHR: {
5944 __ cmpl(ECX, Immediate(31));
5945 __ j(ABOVE, &large_shift);
5946
5947 __ shrd(left_lo, left_hi); // Shift count in CL.
5948 __ sarl(left_hi, ECX); // Shift count in CL.
5949 __ jmp(&done, Assembler::kNearJump);
5950
5951 __ Bind(&large_shift);
5952 __ subl(ECX, Immediate(32));
5953 __ movl(left_lo, left_hi); // Shift by 32.
5954 __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
5955 __ sarl(left_lo, ECX); // Shift count - 32 in CL.
5956 break;
5957 } 5943 }
5958 case Token::kSHL: { 5944 switch (op_kind()) {
5959 if (can_overflow()) { 5945 case Token::kSHR: {
5960 Register temp1 = locs()->temp(0).reg(); 5946 if (shift > 31) {
5961 Register temp2 = locs()->temp(1).reg(); 5947 __ movl(left_lo, left_hi); // Shift by 32.
5962 __ movl(temp1, left_hi); // Preserve high 32 bits. 5948 __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
5949 if (shift > 32) {
5950 __ sarl(left_lo, Immediate(shift - 32));
5951 }
5952 } else {
5953 __ shrd(left_lo, left_hi, Immediate(shift));
5954 __ sarl(left_hi, Immediate(shift));
5955 }
5956 break;
5957 }
5958 case Token::kSHL: {
5959 if (can_overflow()) {
5960 Register temp1 = locs()->temp(0).reg();
5961 Register temp2 = locs()->temp(1).reg();
5962 __ movl(temp1, left_hi); // Preserve high 32 bits.
5963 if (shift > 31) {
5964 __ movl(left_hi, left_lo); // Shift by 32.
5965 __ xorl(left_lo, left_lo); // Zero left_lo.
5966 if (shift > 32) {
5967 __ shll(left_hi, Immediate(shift - 32));
5968 }
5969 // Check for overflow by sign extending the high 32 bits
5970 // and comparing with the input.
5971 __ movl(temp2, left_hi);
5972 __ sarl(temp2, Immediate(31));
5973 __ cmpl(temp1, temp2);
5974 __ j(NOT_EQUAL, deopt);
5975 } else {
5976 __ shld(left_hi, left_lo, Immediate(shift));
5977 __ shll(left_lo, Immediate(shift));
5978 // Check for overflow by shifting back the high 32 bits
5979 // and comparing with the input.
5980 __ movl(temp2, left_hi);
5981 __ sarl(temp2, Immediate(shift));
5982 __ cmpl(temp1, temp2);
5983 __ j(NOT_EQUAL, deopt);
5984 }
5985 } else {
5986 if (shift > 31) {
5987 __ movl(left_hi, left_lo); // Shift by 32.
5988 __ xorl(left_lo, left_lo); // Zero left_lo.
5989 if (shift > 32) {
5990 __ shll(left_hi, Immediate(shift - 32));
5991 }
5992 } else {
5993 __ shld(left_hi, left_lo, Immediate(shift));
5994 __ shll(left_lo, Immediate(shift));
5995 }
5996 }
5997 break;
5998 }
5999 default:
6000 UNREACHABLE();
6001 break;
6002 }
6003 } else {
6004 // Code for a variable shift amount.
6005 // Deoptimize if shift count is > 63.
6006 // sarl operation masks the count to 5 bits and
6007 // shrd is undefined with count > operand size (32)
6008 __ SmiUntag(ECX);
6009 if (has_shift_count_check()) {
6010 __ cmpl(ECX, Immediate(kMintShiftCountLimit));
6011 __ j(ABOVE, deopt);
6012 }
6013 Label done, large_shift;
6014 switch (op_kind()) {
6015 case Token::kSHR: {
5963 __ cmpl(ECX, Immediate(31)); 6016 __ cmpl(ECX, Immediate(31));
5964 __ j(ABOVE, &large_shift); 6017 __ j(ABOVE, &large_shift);
5965 6018
5966 __ shld(left_hi, left_lo); // Shift count in CL. 6019 __ shrd(left_lo, left_hi); // Shift count in CL.
5967 __ shll(left_lo, ECX); // Shift count in CL. 6020 __ sarl(left_hi, ECX); // Shift count in CL.
5968 // Check for overflow by shifting back the high 32 bits
5969 // and comparing with the input.
5970 __ movl(temp2, left_hi);
5971 __ sarl(temp2, ECX);
5972 __ cmpl(temp1, temp2);
5973 __ j(NOT_EQUAL, deopt);
5974 __ jmp(&done, Assembler::kNearJump); 6021 __ jmp(&done, Assembler::kNearJump);
5975 6022
5976 __ Bind(&large_shift); 6023 __ Bind(&large_shift);
5977 __ subl(ECX, Immediate(32)); 6024 __ subl(ECX, Immediate(32));
5978 __ movl(left_hi, left_lo); // Shift by 32. 6025 __ movl(left_lo, left_hi); // Shift by 32.
5979 __ xorl(left_lo, left_lo); // Zero left_lo. 6026 __ sarl(left_hi, Immediate(31)); // Sign extend left hi.
5980 __ shll(left_hi, ECX); // Shift count in CL. 6027 __ sarl(left_lo, ECX); // Shift count - 32 in CL.
5981 // Check for overflow by sign extending the high 32 bits 6028 break;
5982 // and comparing with the input. 6029 }
5983 __ movl(temp2, left_hi); 6030 case Token::kSHL: {
5984 __ sarl(temp2, Immediate(31)); 6031 if (can_overflow()) {
5985 __ cmpl(temp1, temp2); 6032 Register temp1 = locs()->temp(0).reg();
5986 __ j(NOT_EQUAL, deopt); 6033 Register temp2 = locs()->temp(1).reg();
5987 } else { 6034 __ movl(temp1, left_hi); // Preserve high 32 bits.
5988 __ cmpl(ECX, Immediate(31)); 6035 __ cmpl(ECX, Immediate(31));
5989 __ j(ABOVE, &large_shift); 6036 __ j(ABOVE, &large_shift);
5990 6037
5991 __ shld(left_hi, left_lo); // Shift count in CL. 6038 __ shld(left_hi, left_lo); // Shift count in CL.
5992 __ shll(left_lo, ECX); // Shift count in CL. 6039 __ shll(left_lo, ECX); // Shift count in CL.
5993 __ jmp(&done, Assembler::kNearJump); 6040 // Check for overflow by shifting back the high 32 bits
6041 // and comparing with the input.
6042 __ movl(temp2, left_hi);
6043 __ sarl(temp2, ECX);
6044 __ cmpl(temp1, temp2);
6045 __ j(NOT_EQUAL, deopt);
6046 __ jmp(&done, Assembler::kNearJump);
5994 6047
5995 __ Bind(&large_shift); 6048 __ Bind(&large_shift);
5996 __ subl(ECX, Immediate(32)); 6049 __ subl(ECX, Immediate(32));
5997 __ movl(left_hi, left_lo); // Shift by 32. 6050 __ movl(left_hi, left_lo); // Shift by 32.
5998 __ xorl(left_lo, left_lo); // Zero left_lo. 6051 __ xorl(left_lo, left_lo); // Zero left_lo.
5999 __ shll(left_hi, ECX); // Shift count in CL. 6052 __ shll(left_hi, ECX); // Shift count in CL.
6053 // Check for overflow by sign extending the high 32 bits
6054 // and comparing with the input.
6055 __ movl(temp2, left_hi);
6056 __ sarl(temp2, Immediate(31));
6057 __ cmpl(temp1, temp2);
6058 __ j(NOT_EQUAL, deopt);
6059 } else {
6060 __ cmpl(ECX, Immediate(31));
6061 __ j(ABOVE, &large_shift);
6062
6063 __ shld(left_hi, left_lo); // Shift count in CL.
6064 __ shll(left_lo, ECX); // Shift count in CL.
6065 __ jmp(&done, Assembler::kNearJump);
6066
6067 __ Bind(&large_shift);
6068 __ subl(ECX, Immediate(32));
6069 __ movl(left_hi, left_lo); // Shift by 32.
6070 __ xorl(left_lo, left_lo); // Zero left_lo.
6071 __ shll(left_hi, ECX); // Shift count in CL.
6072 }
6073 break;
6000 } 6074 }
6001 break; 6075 default:
6076 UNREACHABLE();
6077 break;
6002 } 6078 }
6003 default: 6079 __ Bind(&done);
6004 UNREACHABLE();
6005 break;
6006 } 6080 }
6007 __ Bind(&done);
6008 if (FLAG_throw_on_javascript_int_overflow) { 6081 if (FLAG_throw_on_javascript_int_overflow) {
6009 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); 6082 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
6010 } 6083 }
6011 } 6084 }
6012 6085
6013 6086
6014 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate, 6087 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate,
6015 bool opt) const { 6088 bool opt) const {
6016 const intptr_t kNumInputs = 1; 6089 const intptr_t kNumInputs = 1;
6017 const intptr_t kNumTemps = 0; 6090 const intptr_t kNumTemps = 0;
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
6406 __ movl(EDX, Immediate(kInvalidObjectPointer)); 6479 __ movl(EDX, Immediate(kInvalidObjectPointer));
6407 __ movl(EDX, Immediate(kInvalidObjectPointer)); 6480 __ movl(EDX, Immediate(kInvalidObjectPointer));
6408 #endif 6481 #endif
6409 } 6482 }
6410 6483
6411 } // namespace dart 6484 } // namespace dart
6412 6485
6413 #undef __ 6486 #undef __
6414 6487
6415 #endif // defined TARGET_ARCH_IA32 6488 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698