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

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

Issue 68663003: Merge TRUNCDIV and MOD into TRUNCDIV_MOD single operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 2169 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 2180
2181 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2181 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
2182 const intptr_t kNumInputs = 2; 2182 const intptr_t kNumInputs = 2;
2183 2183
2184 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2184 ConstantInstr* right_constant = right()->definition()->AsConstant();
2185 if ((right_constant != NULL) && 2185 if ((right_constant != NULL) &&
2186 (op_kind() != Token::kTRUNCDIV) && 2186 (op_kind() != Token::kTRUNCDIV) &&
2187 (op_kind() != Token::kSHL) && 2187 (op_kind() != Token::kSHL) &&
2188 (op_kind() != Token::kMUL) && 2188 (op_kind() != Token::kMUL) &&
2189 (op_kind() != Token::kMOD) && 2189 (op_kind() != Token::kMOD) &&
2190 (op_kind() != Token::kTRUNCDIVMOD) &&
2190 CanBeImmediate(right_constant->value())) { 2191 CanBeImmediate(right_constant->value())) {
2191 const intptr_t kNumTemps = 0; 2192 const intptr_t kNumTemps = 0;
2192 LocationSummary* summary = 2193 LocationSummary* summary =
2193 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2194 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2194 summary->set_in(0, Location::RequiresRegister()); 2195 summary->set_in(0, Location::RequiresRegister());
2195 summary->set_in(1, Location::Constant(right_constant->value())); 2196 summary->set_in(1, Location::Constant(right_constant->value()));
2196 summary->set_out(Location::SameAsFirstInput()); 2197 summary->set_out(Location::SameAsFirstInput());
2197 return summary; 2198 return summary;
2198 } 2199 }
2199 2200
2200 if (op_kind() == Token::kTRUNCDIV) { 2201 if (op_kind() == Token::kTRUNCDIV) {
2201 const intptr_t kNumTemps = 1; 2202 const intptr_t kNumTemps = 1;
2202 LocationSummary* summary = 2203 LocationSummary* summary =
2203 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2204 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2204 if (RightIsPowerOfTwoConstant()) { 2205 if (RightIsPowerOfTwoConstant()) {
2205 summary->set_in(0, Location::RequiresRegister()); 2206 summary->set_in(0, Location::RequiresRegister());
2206 ConstantInstr* right_constant = right()->definition()->AsConstant(); 2207 ConstantInstr* right_constant = right()->definition()->AsConstant();
2207 summary->set_in(1, Location::Constant(right_constant->value())); 2208 summary->set_in(1, Location::Constant(right_constant->value()));
2208 summary->set_temp(0, Location::RequiresRegister()); 2209 summary->set_temp(0, Location::RequiresRegister());
2209 summary->set_out(Location::SameAsFirstInput()); 2210 summary->set_out(Location::SameAsFirstInput());
2210 } else { 2211 } else {
2211 // Both inputs must be writable because they will be untagged. 2212 // Both inputs must be writable because they will be untagged.
2212 summary->set_in(0, Location::RegisterLocation(RAX)); 2213 summary->set_in(0, Location::RegisterLocation(RAX));
2213 summary->set_in(1, Location::WritableRegister()); 2214 summary->set_in(1, Location::WritableRegister());
2214 summary->set_out(Location::SameAsFirstInput()); 2215 summary->set_out(Location::SameAsFirstInput());
2215 // Will be used for sign extension and division. 2216 // Will be used for sign extension and division.
2216 summary->set_temp(0, Location::RegisterLocation(RDX)); 2217 summary->set_temp(0, Location::RegisterLocation(RDX));
2217 } 2218 }
2218 return summary; 2219 return summary;
2220 } else if (op_kind() == Token::kTRUNCDIVMOD) {
2221 const intptr_t kNumTemps = 1;
2222 LocationSummary* summary =
2223 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2224 // Both inputs must be writable because they will be untagged.
2225 summary->set_in(0, Location::RegisterLocation(RAX));
2226 summary->set_in(1, Location::WritableRegister());
2227 summary->set_out(Location::RequiresRegister());
2228 // Will be used for sign extension and division.
2229 summary->set_temp(0, Location::RegisterLocation(RDX));
2230 return summary;
2219 } else if (op_kind() == Token::kMOD) { 2231 } else if (op_kind() == Token::kMOD) {
2220 const intptr_t kNumTemps = 1; 2232 const intptr_t kNumTemps = 1;
2221 LocationSummary* summary = 2233 LocationSummary* summary =
2222 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2234 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2223 // Both inputs must be writable because they will be untagged. 2235 // Both inputs must be writable because they will be untagged.
2224 summary->set_in(0, Location::RegisterLocation(RDX)); 2236 summary->set_in(0, Location::RegisterLocation(RDX));
2225 summary->set_in(1, Location::WritableRegister()); 2237 summary->set_in(1, Location::WritableRegister());
2226 summary->set_out(Location::SameAsFirstInput()); 2238 summary->set_out(Location::SameAsFirstInput());
2227 // Will be used for sign extension and division. 2239 // Will be used for sign extension and division.
2228 summary->set_temp(0, Location::RegisterLocation(RAX)); 2240 summary->set_temp(0, Location::RegisterLocation(RAX));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2264 2276
2265 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2277 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2266 if (op_kind() == Token::kSHL) { 2278 if (op_kind() == Token::kSHL) {
2267 EmitSmiShiftLeft(compiler, this); 2279 EmitSmiShiftLeft(compiler, this);
2268 return; 2280 return;
2269 } 2281 }
2270 2282
2271 ASSERT(!is_truncating()); 2283 ASSERT(!is_truncating());
2272 Register left = locs()->in(0).reg(); 2284 Register left = locs()->in(0).reg();
2273 Register result = locs()->out().reg(); 2285 Register result = locs()->out().reg();
2274 ASSERT(left == result); 2286 // DIVMOD is different.
2287 ASSERT((op_kind() == Token::kTRUNCDIVMOD) || (left == result));
2275 Label* deopt = NULL; 2288 Label* deopt = NULL;
2276 if (CanDeoptimize()) { 2289 if (CanDeoptimize()) {
2277 deopt = compiler->AddDeoptStub(deopt_id(), 2290 deopt = compiler->AddDeoptStub(deopt_id(),
2278 kDeoptBinarySmiOp); 2291 kDeoptBinarySmiOp);
2279 } 2292 }
2280 2293
2281 if (locs()->in(1).IsConstant()) { 2294 if (locs()->in(1).IsConstant()) {
2282 const Object& constant = locs()->in(1).constant(); 2295 const Object& constant = locs()->in(1).constant();
2283 ASSERT(constant.IsSmi()); 2296 ASSERT(constant.IsSmi());
2284 const int64_t imm = 2297 const int64_t imm =
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2565 __ cmpq(right, Immediate(0)); 2578 __ cmpq(right, Immediate(0));
2566 __ j(LESS, &subtract, Assembler::kNearJump); 2579 __ j(LESS, &subtract, Assembler::kNearJump);
2567 __ addq(result, right); 2580 __ addq(result, right);
2568 __ jmp(&all_done, Assembler::kNearJump); 2581 __ jmp(&all_done, Assembler::kNearJump);
2569 __ Bind(&subtract); 2582 __ Bind(&subtract);
2570 __ subq(result, right); 2583 __ subq(result, right);
2571 __ Bind(&all_done); 2584 __ Bind(&all_done);
2572 __ SmiTag(result); 2585 __ SmiTag(result);
2573 break; 2586 break;
2574 } 2587 }
2588 case Token::kTRUNCDIVMOD: {
Florian Schneider 2013/11/14 10:17:44 I'm not sure how much making this operation a Bina
srdjan 2013/11/20 21:41:47 Created new instructions as suggested.
2589 Label not_32bit, done;
2590 Register temp = locs()->temp(0).reg();
2591 ASSERT(left == RAX);
2592 ASSERT((right != RDX) && (right != RAX));
2593 ASSERT(temp == RDX);
2594 ASSERT((result != RDX) && (result != RAX));
2595 // Handle divide by zero in runtime.
2596 __ testq(right, right);
2597 __ j(ZERO, deopt);
2598 // Check if both operands fit into 32bits as idiv with 64bit operands
2599 // requires twice as many cycles and has much higher latency.
2600 // We are checking this before untagging them to avoid corner case
2601 // dividing INT_MAX by -1 that raises exception because quotient is
2602 // too large for 32bit register.
2603 __ movsxd(temp, left);
2604 __ cmpq(temp, left);
2605 __ j(NOT_EQUAL, &not_32bit);
2606 __ movsxd(temp, right);
2607 __ cmpq(temp, right);
2608 __ j(NOT_EQUAL, &not_32bit);
2609
2610 // Both operands are 31bit smis. Divide using 32bit idiv.
2611 __ SmiUntag(left);
2612 __ SmiUntag(right);
2613 __ cdq();
2614 __ idivl(right);
2615 __ movsxd(RAX, RAX);
2616 __ movsxd(RDX, RDX);
2617 __ jmp(&done);
2618
2619 // Divide using 64bit idiv.
2620 __ Bind(&not_32bit);
2621 __ SmiUntag(left);
2622 __ SmiUntag(right);
2623 __ cqo(); // Sign extend RAX -> RDX:RAX.
2624 __ idivq(right); // RAX: quotient, RDX: remainder.
2625 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2626 // case we cannot tag the result.
2627 __ CompareImmediate(RAX, Immediate(0x4000000000000000), PP);
2628 __ j(EQUAL, deopt);
2629 __ Bind(&done);
2630
2631 // Modulo correction (RDX).
2632 // res = left % right;
2633 // if (res < 0) {
2634 // if (right < 0) {
2635 // res = res - right;
2636 // } else {
2637 // res = res + right;
2638 // }
2639 // }
2640 Label subtract, all_done;
2641 __ cmpq(RDX, Immediate(0));
2642 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
2643 // Result is negative, adjust it.
2644 __ cmpq(right, Immediate(0));
2645 __ j(LESS, &subtract, Assembler::kNearJump);
2646 __ addq(RDX, right);
2647 __ jmp(&all_done, Assembler::kNearJump);
2648 __ Bind(&subtract);
2649 __ subq(RDX, right);
2650 __ Bind(&all_done);
2651 __ SmiTag(result);
2652
2653 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP);
2654 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid);
2655 Address trunc_div_address(
2656 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid,
2657 index_scale,
2658 result,
2659 0));
2660 Address mod_address(
2661 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid,
2662 index_scale,
2663 result,
2664 1));
2665 __ SmiTag(RAX);
2666 __ SmiTag(RDX);
2667 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX);
2668 __ StoreIntoObjectNoBarrier(result, mod_address, RDX);
2669 break;
2670 }
2575 case Token::kSHR: { 2671 case Token::kSHR: {
2576 if (CanDeoptimize()) { 2672 if (CanDeoptimize()) {
2577 __ CompareImmediate(right, Immediate(0), PP); 2673 __ CompareImmediate(right, Immediate(0), PP);
2578 __ j(LESS, deopt); 2674 __ j(LESS, deopt);
2579 } 2675 }
2580 __ SmiUntag(right); 2676 __ SmiUntag(right);
2581 // sarq operation masks the count to 6 bits. 2677 // sarq operation masks the count to 6 bits.
2582 const intptr_t kCountLimit = 0x3F; 2678 const intptr_t kCountLimit = 0x3F;
2583 Range* right_range = this->right()->definition()->range(); 2679 Range* right_range = this->right()->definition()->range();
2584 if ((right_range == NULL) || 2680 if ((right_range == NULL) ||
(...skipping 21 matching lines...) Expand all
2606 // Flow graph builder has dissected this operation to guarantee correct 2702 // Flow graph builder has dissected this operation to guarantee correct
2607 // behavior (short-circuit evaluation). 2703 // behavior (short-circuit evaluation).
2608 UNREACHABLE(); 2704 UNREACHABLE();
2609 break; 2705 break;
2610 } 2706 }
2611 default: 2707 default:
2612 UNREACHABLE(); 2708 UNREACHABLE();
2613 break; 2709 break;
2614 } 2710 }
2615 if (FLAG_throw_on_javascript_int_overflow) { 2711 if (FLAG_throw_on_javascript_int_overflow) {
2616 EmitJavascriptOverflowCheck(compiler, range(), deopt, result); 2712 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
Florian Schneider 2013/11/14 10:17:44 DIVMOD won't work with --throw_on_javascript_int_o
srdjan 2013/11/20 21:41:47 Good point, fixing it.
2617 } 2713 }
2618 } 2714 }
2619 2715
2620 2716
2621 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 2717 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
2622 intptr_t left_cid = left()->Type()->ToCid(); 2718 intptr_t left_cid = left()->Type()->ToCid();
2623 intptr_t right_cid = right()->Type()->ToCid(); 2719 intptr_t right_cid = right()->Type()->ToCid();
2624 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 2720 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
2625 const intptr_t kNumInputs = 2; 2721 const intptr_t kNumInputs = 2;
2626 const bool need_temp = (left_cid != kSmiCid) && (right_cid != kSmiCid); 2722 const bool need_temp = (left_cid != kSmiCid) && (right_cid != kSmiCid);
(...skipping 1990 matching lines...) Expand 10 before | Expand all | Expand 10 after
4617 PcDescriptors::kOther, 4713 PcDescriptors::kOther,
4618 locs()); 4714 locs());
4619 __ Drop(2); // Discard type arguments and receiver. 4715 __ Drop(2); // Discard type arguments and receiver.
4620 } 4716 }
4621 4717
4622 } // namespace dart 4718 } // namespace dart
4623 4719
4624 #undef __ 4720 #undef __
4625 4721
4626 #endif // defined TARGET_ARCH_X64 4722 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698