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

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

Issue 12091100: Use SAR for positive divident by a power-of two constant divisor. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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/intermediate_language.cc ('k') | runtime/vm/intermediate_language_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 (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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 1933 matching lines...) Expand 10 before | Expand all | Expand 10 after
1944 __ cmpl(ESP, 1944 __ cmpl(ESP,
1945 Address::Absolute(Isolate::Current()->stack_limit_address())); 1945 Address::Absolute(Isolate::Current()->stack_limit_address()));
1946 __ j(BELOW_EQUAL, slow_path->entry_label()); 1946 __ j(BELOW_EQUAL, slow_path->entry_label());
1947 __ Bind(slow_path->exit_label()); 1947 __ Bind(slow_path->exit_label());
1948 } 1948 }
1949 1949
1950 1950
1951 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 1951 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
1952 const intptr_t kNumInputs = 2; 1952 const intptr_t kNumInputs = 2;
1953 if (op_kind() == Token::kTRUNCDIV) { 1953 if (op_kind() == Token::kTRUNCDIV) {
1954 const intptr_t kNumTemps = 1; 1954 const intptr_t kNumTemps = RightIsPowerOfTwoConstant() ? 2 : 1;
1955 LocationSummary* summary = 1955 LocationSummary* summary =
1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1956 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1957 // Both inputs must be writable because they will be untagged. 1957 // Both inputs must be writable because they will be untagged.
1958 summary->set_in(0, Location::RegisterLocation(EAX)); 1958 summary->set_in(0, Location::RegisterLocation(EAX));
1959 summary->set_in(1, Location::WritableRegister()); 1959 if (kNumTemps == 1) {
1960 summary->set_in(1, Location::WritableRegister());
1961 } else {
1962 ConstantInstr* right_constant = right()->definition()->AsConstant();
1963 summary->set_in(1, Location::Constant(right_constant->value()));
1964 // Temporary to hold divisor constant.
1965 summary->set_temp(1, Location::RegisterLocation(EBX));
1966 }
1960 summary->set_out(Location::SameAsFirstInput()); 1967 summary->set_out(Location::SameAsFirstInput());
1961 // Will be used for sign extension and division. 1968 // Will be used for sign extension and division.
1962 summary->set_temp(0, Location::RegisterLocation(EDX)); 1969 summary->set_temp(0, Location::RegisterLocation(EDX));
1963 return summary; 1970 return summary;
1964 } else if (op_kind() == Token::kSHR) { 1971 } else if (op_kind() == Token::kSHR) {
1965 const intptr_t kNumTemps = 0; 1972 const intptr_t kNumTemps = 0;
1966 LocationSummary* summary = 1973 LocationSummary* summary =
1967 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1974 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1968 summary->set_in(0, Location::RequiresRegister()); 1975 summary->set_in(0, Location::RequiresRegister());
1969 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); 1976 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
(...skipping 19 matching lines...) Expand all
1989 } 1996 }
1990 } 1997 }
1991 1998
1992 1999
1993 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2000 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1994 Register left = locs()->in(0).reg(); 2001 Register left = locs()->in(0).reg();
1995 Register result = locs()->out().reg(); 2002 Register result = locs()->out().reg();
1996 ASSERT(left == result); 2003 ASSERT(left == result);
1997 Label* deopt = NULL; 2004 Label* deopt = NULL;
1998 if (CanDeoptimize()) { 2005 if (CanDeoptimize()) {
1999 deopt = compiler->AddDeoptStub(deopt_id(), 2006 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
2000 kDeoptBinarySmiOp);
2001 } 2007 }
2002 2008
2003 if (locs()->in(1).IsConstant()) { 2009 if (locs()->in(1).IsConstant()) {
2004 const Object& constant = locs()->in(1).constant(); 2010 const Object& constant = locs()->in(1).constant();
2005 ASSERT(constant.IsSmi()); 2011 ASSERT(constant.IsSmi());
2006 const int32_t imm = 2012 const int32_t imm =
2007 reinterpret_cast<int32_t>(constant.raw()); 2013 reinterpret_cast<int32_t>(constant.raw());
2008 switch (op_kind()) { 2014 switch (op_kind()) {
2009 case Token::kADD: 2015 case Token::kADD:
2010 __ addl(left, Immediate(imm)); 2016 __ addl(left, Immediate(imm));
2011 if (deopt != NULL) __ j(OVERFLOW, deopt); 2017 if (deopt != NULL) __ j(OVERFLOW, deopt);
2012 break; 2018 break;
2013 case Token::kSUB: { 2019 case Token::kSUB: {
2014 __ subl(left, Immediate(imm)); 2020 __ subl(left, Immediate(imm));
2015 if (deopt != NULL) __ j(OVERFLOW, deopt); 2021 if (deopt != NULL) __ j(OVERFLOW, deopt);
2016 break; 2022 break;
2017 } 2023 }
2018 case Token::kMUL: { 2024 case Token::kMUL: {
2019 // Keep left value tagged and untag right value. 2025 // Keep left value tagged and untag right value.
2020 const intptr_t value = Smi::Cast(constant).Value(); 2026 const intptr_t value = Smi::Cast(constant).Value();
2021 __ imull(left, Immediate(value)); 2027 __ imull(left, Immediate(value));
2022 if (deopt != NULL) __ j(OVERFLOW, deopt); 2028 if (deopt != NULL) __ j(OVERFLOW, deopt);
2023 break; 2029 break;
2024 } 2030 }
2031 case Token::kTRUNCDIV: {
2032 Label use_div, done;
2033 const intptr_t value = Smi::Cast(constant).Value();
2034 ASSERT((value > 0) && Utils::IsPowerOfTwo(value));
2035 __ cmpl(left, Immediate(0));
Florian Schneider 2013/02/01 11:48:33 For checking x < 0, this sequence is 1 byte shorte
2036 __ j(LESS, &use_div, Assembler::kNearJump);
2037 // Positive division by power of two is an arithmetic left shift.
Florian Schneider 2013/02/01 11:48:33 In the comment s/left/right/.
srdjan 2013/02/01 22:57:54 Done.
2038 intptr_t shift_count = Utils::ShiftForPowerOfTwo(value) + kSmiTagSize;
2039 __ sarl(left, Immediate(shift_count));
2040 __ jmp(&done, Assembler::kNearJump);
2041 __ Bind(&use_div);
Florian Schneider 2013/02/01 11:48:33 I think this could be improved for negative number
Florian Schneider 2013/02/04 13:04:02 Yes, my mistake: of course the absolute value of r
2042 Register right = locs()->temp(1).reg();
2043 ASSERT(left == EAX);
2044 ASSERT((right != EDX) && (right != EAX));
2045 ASSERT(locs()->temp(0).reg() == EDX);
2046 ASSERT(result == EAX);
2047 __ movl(right, Immediate(value));
2048 __ SmiUntag(left);
2049 __ cdq(); // Sign extend EAX -> EDX:EAX.
2050 __ idivl(right); // EAX: quotient, EDX: remainder.
2051 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
Florian Schneider 2013/02/01 11:48:33 Since the right side is a known constant, you can
2052 // case we cannot tag the result.
2053 __ cmpl(result, Immediate(0x40000000));
2054 __ j(EQUAL, deopt);
2055 __ Bind(&done);
2056 __ SmiTag(result);
2057 break;
2058 }
2025 case Token::kBIT_AND: { 2059 case Token::kBIT_AND: {
2026 // No overflow check. 2060 // No overflow check.
2027 __ andl(left, Immediate(imm)); 2061 __ andl(left, Immediate(imm));
2028 break; 2062 break;
2029 } 2063 }
2030 case Token::kBIT_OR: { 2064 case Token::kBIT_OR: {
2031 // No overflow check. 2065 // No overflow check.
2032 __ orl(left, Immediate(imm)); 2066 __ orl(left, Immediate(imm));
2033 break; 2067 break;
2034 } 2068 }
(...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after
3366 PcDescriptors::kOther, 3400 PcDescriptors::kOther,
3367 locs()); 3401 locs());
3368 __ Drop(2); // Discard type arguments and receiver. 3402 __ Drop(2); // Discard type arguments and receiver.
3369 } 3403 }
3370 3404
3371 } // namespace dart 3405 } // namespace dart
3372 3406
3373 #undef __ 3407 #undef __
3374 3408
3375 #endif // defined TARGET_ARCH_IA32 3409 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698