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

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

Issue 396733006: Optimize the multiplication of two 32-bit unsigned integers. (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
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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 } 644 }
645 645
646 646
647 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 647 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
648 BranchLabels labels) { 648 BranchLabels labels) {
649 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); 649 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
650 Register val_reg = locs()->in(0).reg(); 650 Register val_reg = locs()->in(0).reg();
651 Register cid_reg = locs()->temp(0).reg(); 651 Register cid_reg = locs()->temp(0).reg();
652 652
653 Label* deopt = CanDeoptimize() ? 653 Label* deopt = CanDeoptimize() ?
654 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; 654 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL;
655 655
656 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; 656 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
657 const ZoneGrowableArray<intptr_t>& data = cid_results(); 657 const ZoneGrowableArray<intptr_t>& data = cid_results();
658 ASSERT(data[0] == kSmiCid); 658 ASSERT(data[0] == kSmiCid);
659 bool result = data[1] == true_result; 659 bool result = data[1] == true_result;
660 __ testl(val_reg, Immediate(kSmiTagMask)); 660 __ testl(val_reg, Immediate(kSmiTagMask));
661 __ j(ZERO, result ? labels.true_label : labels.false_label); 661 __ j(ZERO, result ? labels.true_label : labels.false_label);
662 __ LoadClassId(cid_reg, val_reg); 662 __ LoadClassId(cid_reg, val_reg);
663 for (intptr_t i = 2; i < data.length(); i += 2) { 663 for (intptr_t i = 2; i < data.length(); i += 2) {
664 const intptr_t test_cid = data[i]; 664 const intptr_t test_cid = data[i];
(...skipping 5174 matching lines...) Expand 10 before | Expand all | Expand 10 after
5839 __ Bind(&done); 5839 __ Bind(&done);
5840 } 5840 }
5841 5841
5842 5842
5843 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, 5843 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate,
5844 bool opt) const { 5844 bool opt) const {
5845 const intptr_t kNumInputs = 2; 5845 const intptr_t kNumInputs = 2;
5846 switch (op_kind()) { 5846 switch (op_kind()) {
5847 case Token::kBIT_AND: 5847 case Token::kBIT_AND:
5848 case Token::kBIT_OR: 5848 case Token::kBIT_OR:
5849 case Token::kBIT_XOR: { 5849 case Token::kBIT_XOR:
5850 case Token::kADD:
5851 case Token::kSUB: {
5850 const intptr_t kNumTemps = 0; 5852 const intptr_t kNumTemps = 0;
5851 LocationSummary* summary = new(isolate) LocationSummary( 5853 LocationSummary* summary = new(isolate) LocationSummary(
5852 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5854 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5853 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 5855 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5854 Location::RequiresRegister())); 5856 Location::RequiresRegister()));
5855 summary->set_in(1, Location::Pair(Location::RequiresRegister(), 5857 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5856 Location::RequiresRegister())); 5858 Location::RequiresRegister()));
5857 summary->set_out(0, Location::SameAsFirstInput()); 5859 summary->set_out(0, Location::SameAsFirstInput());
5858 return summary; 5860 return summary;
5859 } 5861 }
5860 case Token::kADD: 5862 case Token::kMUL: {
5861 case Token::kSUB: {
5862 const intptr_t kNumTemps = 0; 5863 const intptr_t kNumTemps = 0;
5863 LocationSummary* summary = new(isolate) LocationSummary( 5864 LocationSummary* summary = new(isolate) LocationSummary(
5864 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 5865 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5865 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 5866 summary->set_in(0, Location::Pair(Location::RegisterLocation(EAX),
5866 Location::RequiresRegister())); 5867 Location::RegisterLocation(EDX)));
5867 summary->set_in(1, Location::Pair(Location::RequiresRegister(), 5868 summary->set_in(1, Location::Pair(Location::RequiresRegister(),
5868 Location::RequiresRegister())); 5869 Location::RequiresRegister()));
5869 summary->set_out(0, Location::SameAsFirstInput()); 5870 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5871 Location::RegisterLocation(EDX)));
5870 return summary; 5872 return summary;
5871 } 5873 }
5872 default: 5874 default:
5873 UNREACHABLE(); 5875 UNREACHABLE();
5874 return NULL; 5876 return NULL;
5875 } 5877 }
5876 } 5878 }
5877 5879
5878 5880
5879 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 5881 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5913 __ adcl(left_hi, right_hi); 5915 __ adcl(left_hi, right_hi);
5914 } else { 5916 } else {
5915 __ subl(left_lo, right_lo); 5917 __ subl(left_lo, right_lo);
5916 __ sbbl(left_hi, right_hi); 5918 __ sbbl(left_hi, right_hi);
5917 } 5919 }
5918 if (can_overflow()) { 5920 if (can_overflow()) {
5919 __ j(OVERFLOW, deopt); 5921 __ j(OVERFLOW, deopt);
5920 } 5922 }
5921 break; 5923 break;
5922 } 5924 }
5925 case Token::kMUL: {
5926 // We only support the multiplication of two positive 32-bit integers
5927 // resulting in a positive 64-bit integer fitting in a mint.
5928 // We deopt in all other cases.
5929 // This guarantees that the multiplication of 16-bit unsigned integers,
5930 // as used in bignum arithmetic, will always succeed.
5931 __ orl(left_hi, right_hi);
5932 __ j(NOT_ZERO, deopt);
5933 ASSERT(left_lo == EAX);
5934 __ mull(right_lo); // Result in EDX:EAX.
5935 ASSERT(out_lo == EAX);
5936 ASSERT(out_hi == EDX);
5937 if (can_overflow()) {
5938 __ testl(out_hi, Immediate(0xc0000000));
5939 __ j(NOT_ZERO, deopt);
Vyacheslav Egorov (Google) 2014/07/16 19:51:22 I am very wary of this kind of optimistic optimiza
regis 2014/07/16 23:12:42 Fair enough. I have added a range check, so that t
5940 }
5941 break;
5942 }
5923 default: UNREACHABLE(); 5943 default: UNREACHABLE();
5924 } 5944 }
5925 if (FLAG_throw_on_javascript_int_overflow) { 5945 if (FLAG_throw_on_javascript_int_overflow) {
5926 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); 5946 EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi);
5927 } 5947 }
5928 } 5948 }
5929 5949
5930 5950
5931 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate, 5951 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate,
5932 bool opt) const { 5952 bool opt) const {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
6186 6206
6187 6207
6188 CompileType UnboxUint32Instr::ComputeType() const { 6208 CompileType UnboxUint32Instr::ComputeType() const {
6189 return CompileType::Int(); 6209 return CompileType::Int();
6190 } 6210 }
6191 6211
6192 6212
6193 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, 6213 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate,
6194 bool opt) const { 6214 bool opt) const {
6195 const intptr_t kNumInputs = 2; 6215 const intptr_t kNumInputs = 2;
6196 const intptr_t kNumTemps = 0; 6216 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0;
6197 LocationSummary* summary = new(isolate) LocationSummary( 6217 LocationSummary* summary = new(isolate) LocationSummary(
6198 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6218 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6199 summary->set_in(0, Location::RequiresRegister()); 6219 if (op_kind() == Token::kMUL) {
6220 summary->set_in(0, Location::RegisterLocation(EAX));
6221 summary->set_temp(0, Location::RegisterLocation(EDX));
6222 } else {
6223 summary->set_in(0, Location::RequiresRegister());
6224 }
6200 summary->set_in(1, Location::RequiresRegister()); 6225 summary->set_in(1, Location::RequiresRegister());
6201 summary->set_out(0, Location::SameAsFirstInput()); 6226 summary->set_out(0, Location::SameAsFirstInput());
6202 return summary; 6227 return summary;
6203 } 6228 }
6204 6229
6205 6230
6206 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6231 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6207 Register left = locs()->in(0).reg(); 6232 Register left = locs()->in(0).reg();
6208 Register right = locs()->in(1).reg(); 6233 Register right = locs()->in(1).reg();
6209 Register out = locs()->out(0).reg(); 6234 Register out = locs()->out(0).reg();
6210 ASSERT(out == left); 6235 ASSERT(out == left);
6236 Label* deopt = CanDeoptimize() ?
6237 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryUint32Op) : NULL;
6211 switch (op_kind()) { 6238 switch (op_kind()) {
6212 case Token::kBIT_AND: 6239 case Token::kBIT_AND:
6213 __ andl(out, right); 6240 __ andl(out, right);
6214 break; 6241 break;
6215 case Token::kBIT_OR: 6242 case Token::kBIT_OR:
6216 __ orl(out, right); 6243 __ orl(out, right);
6217 break; 6244 break;
6218 case Token::kBIT_XOR: 6245 case Token::kBIT_XOR:
6219 __ xorl(out, right); 6246 __ xorl(out, right);
6220 break; 6247 break;
6221 case Token::kADD: 6248 case Token::kADD:
6222 __ addl(out, right); 6249 __ addl(out, right);
6223 break; 6250 break;
6224 case Token::kSUB: 6251 case Token::kSUB:
6225 __ subl(out, right); 6252 __ subl(out, right);
6226 break; 6253 break;
6254 case Token::kMUL:
6255 __ mull(right); // Result in EDX:EAX, CF set if EDX != 0.
Cutch 2014/07/16 18:09:48 Uint32 operations are only used in places where we
regis 2014/07/16 23:12:42 I have removed the overflow check.
6256 __ j(OVERFLOW, deopt);
6257 break;
6227 default: 6258 default:
6228 UNREACHABLE(); 6259 UNREACHABLE();
6229 } 6260 }
6230 } 6261 }
6231 6262
6232 6263
6233 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, 6264 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate,
6234 bool opt) const { 6265 bool opt) const {
6235 const intptr_t kNumInputs = 2; 6266 const intptr_t kNumInputs = 2;
6236 const intptr_t kNumTemps = 0; 6267 const intptr_t kNumTemps = 0;
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
6831 __ movl(EDX, Immediate(kInvalidObjectPointer)); 6862 __ movl(EDX, Immediate(kInvalidObjectPointer));
6832 __ movl(EDX, Immediate(kInvalidObjectPointer)); 6863 __ movl(EDX, Immediate(kInvalidObjectPointer));
6833 #endif 6864 #endif
6834 } 6865 }
6835 6866
6836 } // namespace dart 6867 } // namespace dart
6837 6868
6838 #undef __ 6869 #undef __
6839 6870
6840 #endif // defined TARGET_ARCH_IA32 6871 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698