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

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

Issue 2466643002: AOT: Enable branch merging for checked smi comparisons (Closed)
Patch Set: ported to all architectures Created 4 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
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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/bootstrap.h" 8 #include "vm/bootstrap.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/constant_propagator.h" 10 #include "vm/constant_propagator.h"
(...skipping 1739 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 case Token::kBIT_OR: 1750 case Token::kBIT_OR:
1751 case Token::kBIT_XOR: 1751 case Token::kBIT_XOR:
1752 replacement = 1752 replacement =
1753 new BinarySmiOpInstr(op_kind(), 1753 new BinarySmiOpInstr(op_kind(),
1754 new Value(left()->definition()), 1754 new Value(left()->definition()),
1755 new Value(right()->definition()), 1755 new Value(right()->definition()),
1756 Thread::kNoDeoptId); 1756 Thread::kNoDeoptId);
1757 default: 1757 default:
1758 break; 1758 break;
1759 } 1759 }
1760 if (Token::IsRelationalOperator(op_kind())) { 1760 }
1761 replacement = new RelationalOpInstr(token_pos(), op_kind(), 1761 return this;
1762 }
1763
1764
1765 ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands(
1766 Value* left, Value* right) {
1767 UNREACHABLE();
1768 return NULL;
1769 }
1770
1771
1772 Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) {
1773 if ((left()->Type()->ToCid() == kSmiCid) &&
1774 (right()->Type()->ToCid() == kSmiCid)) {
1775 Definition* replacement = NULL;
1776 if (Token::IsRelationalOperator(kind())) {
1777 replacement = new RelationalOpInstr(token_pos(), kind(),
1762 new Value(left()->definition()), 1778 new Value(left()->definition()),
1763 new Value(right()->definition()), 1779 new Value(right()->definition()),
1764 kSmiCid, 1780 kSmiCid,
1765 Thread::kNoDeoptId); 1781 Thread::kNoDeoptId);
1766 } else if (Token::IsEqualityOperator(op_kind())) { 1782 } else if (Token::IsEqualityOperator(kind())) {
1767 replacement = new EqualityCompareInstr(token_pos(), op_kind(), 1783 replacement = new EqualityCompareInstr(token_pos(), kind(),
1768 new Value(left()->definition()), 1784 new Value(left()->definition()),
1769 new Value(right()->definition()), 1785 new Value(right()->definition()),
1770 kSmiCid, 1786 kSmiCid,
1771 Thread::kNoDeoptId); 1787 Thread::kNoDeoptId);
1772 } 1788 }
1773 if (replacement != NULL) { 1789 if (replacement != NULL) {
1774 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); 1790 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue);
1775 return replacement; 1791 return replacement;
1776 } 1792 }
1777 } 1793 }
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
2349 FlowGraph::kValue); 2365 FlowGraph::kValue);
2350 return replacement; 2366 return replacement;
2351 } 2367 }
2352 2368
2353 return this; 2369 return this;
2354 } 2370 }
2355 2371
2356 2372
2357 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { 2373 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) {
2358 Definition* defn = value()->definition(); 2374 Definition* defn = value()->definition();
2359 if (defn->IsComparison() && defn->HasOnlyUse(value())) { 2375 if (defn->IsComparison() &&
2360 // Comparisons always have a bool result. 2376 defn->HasOnlyUse(value()) &&
2361 ASSERT(value()->definition()->Type()->ToCid() == kBoolCid); 2377 defn->Type()->ToCid() == kBoolCid) {
2362 defn->AsComparison()->NegateComparison(); 2378 defn->AsComparison()->NegateComparison();
2363 return defn; 2379 return defn;
2364 } 2380 }
2365 return this; 2381 return this;
2366 } 2382 }
2367 2383
2368 2384
2369 static bool MayBeBoxableNumber(intptr_t cid) { 2385 static bool MayBeBoxableNumber(intptr_t cid) {
2370 return (cid == kDynamicCid) || 2386 return (cid == kDynamicCid) ||
2371 (cid == kMintCid) || 2387 (cid == kMintCid) ||
2372 (cid == kBigintCid) || 2388 (cid == kBigintCid) ||
2373 (cid == kDoubleCid); 2389 (cid == kDoubleCid);
2374 } 2390 }
2375 2391
2376 2392
2377 static bool MaybeNumber(CompileType* type) { 2393 static bool MaybeNumber(CompileType* type) {
2378 ASSERT(Type::Handle(Type::Number()).IsMoreSpecificThan( 2394 ASSERT(Type::Handle(Type::Number()).IsMoreSpecificThan(
2379 Type::Handle(Type::Number()), NULL, NULL, Heap::kOld)); 2395 Type::Handle(Type::Number()), NULL, NULL, Heap::kOld));
2380 return type->ToAbstractType()->IsDynamicType() 2396 return type->ToAbstractType()->IsDynamicType()
2381 || type->ToAbstractType()->IsObjectType() 2397 || type->ToAbstractType()->IsObjectType()
2382 || type->ToAbstractType()->IsTypeParameter() 2398 || type->ToAbstractType()->IsTypeParameter()
2383 || type->IsMoreSpecificThan(Type::Handle(Type::Number())); 2399 || type->IsMoreSpecificThan(Type::Handle(Type::Number()));
2384 } 2400 }
2385 2401
2386 2402
2387 // Returns a replacement for a strict comparison and signals if the result has 2403 // Returns a replacement for a strict comparison and signals if the result has
2388 // to be negated. 2404 // to be negated.
2389 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare, 2405 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare,
2390 bool* negated) { 2406 bool* negated,
2407 bool is_branch) {
2391 // Use propagated cid and type information to eliminate number checks. 2408 // Use propagated cid and type information to eliminate number checks.
2392 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or 2409 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or
2393 // is not a subtype of num, no need for number checks. 2410 // is not a subtype of num, no need for number checks.
2394 if (compare->needs_number_check()) { 2411 if (compare->needs_number_check()) {
2395 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) || 2412 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) ||
2396 !MayBeBoxableNumber(compare->right()->Type()->ToCid())) { 2413 !MayBeBoxableNumber(compare->right()->Type()->ToCid())) {
2397 compare->set_needs_number_check(false); 2414 compare->set_needs_number_check(false);
2398 } else if (!MaybeNumber(compare->left()->Type()) || 2415 } else if (!MaybeNumber(compare->left()->Type()) ||
2399 !MaybeNumber(compare->right()->Type())) { 2416 !MaybeNumber(compare->right()->Type())) {
2400 compare->set_needs_number_check(false); 2417 compare->set_needs_number_check(false);
2401 } 2418 }
2402 } 2419 }
2403
2404 *negated = false; 2420 *negated = false;
2405 PassiveObject& constant = PassiveObject::Handle(); 2421 PassiveObject& constant = PassiveObject::Handle();
2406 Value* other = NULL; 2422 Value* other = NULL;
2407 if (compare->right()->BindsToConstant()) { 2423 if (compare->right()->BindsToConstant()) {
2408 constant = compare->right()->BoundConstant().raw(); 2424 constant = compare->right()->BoundConstant().raw();
2409 other = compare->left(); 2425 other = compare->left();
2410 } else if (compare->left()->BindsToConstant()) { 2426 } else if (compare->left()->BindsToConstant()) {
2411 constant = compare->left()->BoundConstant().raw(); 2427 constant = compare->left()->BoundConstant().raw();
2412 other = compare->right(); 2428 other = compare->right();
2413 } else { 2429 } else {
2414 return compare; 2430 return compare;
2415 } 2431 }
2416 2432
2433 const bool can_merge = is_branch || (other->Type()->ToCid() == kBoolCid);
2417 Definition* other_defn = other->definition(); 2434 Definition* other_defn = other->definition();
2418 Token::Kind kind = compare->kind(); 2435 Token::Kind kind = compare->kind();
2419 // Handle e === true. 2436 // Handle e === true.
2420 if ((kind == Token::kEQ_STRICT) && 2437 if ((kind == Token::kEQ_STRICT) &&
2421 (constant.raw() == Bool::True().raw()) && 2438 (constant.raw() == Bool::True().raw()) &&
2422 (other->Type()->ToCid() == kBoolCid)) { 2439 can_merge) {
2423 return other_defn; 2440 return other_defn;
2424 } 2441 }
2425 // Handle e !== false. 2442 // Handle e !== false.
2426 if ((kind == Token::kNE_STRICT) && 2443 if ((kind == Token::kNE_STRICT) &&
2427 (constant.raw() == Bool::False().raw()) && 2444 (constant.raw() == Bool::False().raw()) &&
2428 (other->Type()->ToCid() == kBoolCid)) { 2445 can_merge) {
2429 return other_defn; 2446 return other_defn;
2430 } 2447 }
2431 // Handle e !== true. 2448 // Handle e !== true.
2432 if ((kind == Token::kNE_STRICT) && 2449 if ((kind == Token::kNE_STRICT) &&
2433 (constant.raw() == Bool::True().raw()) && 2450 (constant.raw() == Bool::True().raw()) &&
2434 other_defn->IsComparison() && 2451 other_defn->IsComparison() &&
2435 (other->Type()->ToCid() == kBoolCid) && 2452 can_merge &&
2436 other_defn->HasOnlyUse(other)) { 2453 other_defn->HasOnlyUse(other)) {
2437 *negated = true; 2454 *negated = true;
2438 return other_defn; 2455 return other_defn;
2439 } 2456 }
2440 // Handle e === false. 2457 // Handle e === false.
2441 if ((kind == Token::kEQ_STRICT) && 2458 if ((kind == Token::kEQ_STRICT) &&
2442 (constant.raw() == Bool::False().raw()) && 2459 (constant.raw() == Bool::False().raw()) &&
2443 other_defn->IsComparison() && 2460 other_defn->IsComparison() &&
2444 (other->Type()->ToCid() == kBoolCid) && 2461 can_merge &&
2445 other_defn->HasOnlyUse(other)) { 2462 other_defn->HasOnlyUse(other)) {
2446 *negated = true; 2463 *negated = true;
2447 return other_defn; 2464 return other_defn;
2448 } 2465 }
2449 return compare; 2466 return compare;
2450 } 2467 }
2451 2468
2452 2469
2453 static bool BindsToGivenConstant(Value* v, intptr_t expected) { 2470 static bool BindsToGivenConstant(Value* v, intptr_t expected) {
2454 return v->BindsToConstant() && 2471 return v->BindsToConstant() &&
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2494 return false; 2511 return false;
2495 } 2512 }
2496 2513
2497 2514
2498 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { 2515 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) {
2499 Zone* zone = flow_graph->zone(); 2516 Zone* zone = flow_graph->zone();
2500 // Only handle strict-compares. 2517 // Only handle strict-compares.
2501 if (comparison()->IsStrictCompare()) { 2518 if (comparison()->IsStrictCompare()) {
2502 bool negated = false; 2519 bool negated = false;
2503 Definition* replacement = 2520 Definition* replacement =
2504 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); 2521 CanonicalizeStrictCompare(comparison()->AsStrictCompare(),
2522 &negated, /* is_branch = */ true);
2505 if (replacement == comparison()) { 2523 if (replacement == comparison()) {
2506 return this; 2524 return this;
2507 } 2525 }
2508 ComparisonInstr* comp = replacement->AsComparison(); 2526 ComparisonInstr* comp = replacement->AsComparison();
2509 if ((comp == NULL) || 2527 if ((comp == NULL) ||
2510 comp->CanDeoptimize() || 2528 comp->CanDeoptimize() ||
2511 comp->HasUnmatchedInputRepresentations()) { 2529 comp->HasUnmatchedInputRepresentations()) {
2512 return this; 2530 return this;
2513 } 2531 }
2514 2532
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2566 bit_and->RemoveFromGraph(); 2584 bit_and->RemoveFromGraph();
2567 } 2585 }
2568 } 2586 }
2569 return this; 2587 return this;
2570 } 2588 }
2571 2589
2572 2590
2573 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { 2591 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) {
2574 if (!HasUses()) return NULL; 2592 if (!HasUses()) return NULL;
2575 bool negated = false; 2593 bool negated = false;
2576 Definition* replacement = CanonicalizeStrictCompare(this, &negated); 2594 Definition* replacement = CanonicalizeStrictCompare(this, &negated,
2595 /* is_branch = */ false);
2577 if (negated && replacement->IsComparison()) { 2596 if (negated && replacement->IsComparison()) {
2578 ASSERT(replacement != this); 2597 ASSERT(replacement != this);
2579 replacement->AsComparison()->NegateComparison(); 2598 replacement->AsComparison()->NegateComparison();
2580 } 2599 }
2581 return replacement; 2600 return replacement;
2582 } 2601 }
2583 2602
2584 2603
2585 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { 2604 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) {
2586 const intptr_t value_cid = value()->Type()->ToCid(); 2605 const intptr_t value_cid = value()->Type()->ToCid();
(...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after
3936 set_native_c_function(native_function); 3955 set_native_c_function(native_function);
3937 function().SetIsNativeAutoSetupScope(auto_setup_scope); 3956 function().SetIsNativeAutoSetupScope(auto_setup_scope);
3938 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); 3957 Dart_NativeEntryResolver resolver = library.native_entry_resolver();
3939 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); 3958 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver);
3940 set_is_bootstrap_native(is_bootstrap_native); 3959 set_is_bootstrap_native(is_bootstrap_native);
3941 } 3960 }
3942 3961
3943 #undef __ 3962 #undef __
3944 3963
3945 } // namespace dart 3964 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698