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

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

Issue 14251023: Merge (x & y) == 0 pattern to emit a single test instruction. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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.h ('k') | runtime/vm/intermediate_language_arm.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/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/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 set_previous(NULL); 600 set_previous(NULL);
601 set_next(NULL); 601 set_next(NULL);
602 } 602 }
603 603
604 604
605 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) 605 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked)
606 : comparison_(comparison), 606 : comparison_(comparison),
607 is_checked_(is_checked), 607 is_checked_(is_checked),
608 constrained_type_(NULL), 608 constrained_type_(NULL),
609 constant_target_(NULL) { 609 constant_target_(NULL) {
610 ASSERT(comparison->env() == NULL);
610 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { 611 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
611 comparison->InputAt(i)->set_instruction(this); 612 comparison->InputAt(i)->set_instruction(this);
612 } 613 }
613 } 614 }
614 615
615 616
616 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { 617 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) {
617 comparison()->RawSetInputAt(i, value); 618 comparison()->RawSetInputAt(i, value);
618 } 619 }
619 620
620 621
621 // A misleadingly named function for use in template functions that replace 622 // A misleadingly named function for use in template functions that replace
622 // both definitions with definitions and branch comparisons with 623 // both definitions with definitions and branch comparisons with
623 // comparisons. In the branch case, leave the branch intact and replace its 624 // comparisons. In the branch case, leave the branch intact and replace its
624 // comparison with a new comparison not currently in the graph. 625 // comparison with a new comparison not currently in the graph.
625 void BranchInstr::ReplaceWith(ComparisonInstr* other, 626 void BranchInstr::ReplaceWith(ComparisonInstr* other,
626 ForwardInstructionIterator* ignored) { 627 ForwardInstructionIterator* ignored) {
627 SetComparison(other); 628 SetComparison(other);
628 } 629 }
629 630
630 631
631 void BranchInstr::SetComparison(ComparisonInstr* comp) { 632 void BranchInstr::SetComparison(ComparisonInstr* new_comparison) {
632 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { 633 for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) {
633 Value* input = comp->InputAt(i); 634 Value* input = new_comparison->InputAt(i);
634 input->definition()->AddInputUse(input); 635 input->definition()->AddInputUse(input);
635 input->set_instruction(this); 636 input->set_instruction(this);
636 } 637 }
637 // There should be no need to copy or unuse an environment. 638 // There should be no need to copy or unuse an environment.
638 ASSERT(comparison()->env() == NULL); 639 ASSERT(comparison()->env() == NULL);
640 ASSERT(new_comparison->env() == NULL);
639 // Remove the current comparison's input uses. 641 // Remove the current comparison's input uses.
640 comparison()->UnuseAllInputs(); 642 comparison()->UnuseAllInputs();
641 ASSERT(!comp->HasUses()); 643 ASSERT(!new_comparison->HasUses());
642 comparison_ = comp; 644 comparison_ = new_comparison;
643 } 645 }
644 646
645 647
646 // ==== Postorder graph traversal. 648 // ==== Postorder graph traversal.
647 static bool IsMarked(BlockEntryInstr* block, 649 static bool IsMarked(BlockEntryInstr* block,
648 GrowableArray<BlockEntryInstr*>* preorder) { 650 GrowableArray<BlockEntryInstr*>* preorder) {
649 // Detect that a block has been visited as part of the current 651 // Detect that a block has been visited as part of the current
650 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block 652 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block
651 // will be 'marked' by (1) having a preorder number in the range of the 653 // will be 'marked' by (1) having a preorder number in the range of the
652 // preorder array and (2) being in the preorder array at that index. 654 // preorder array and (2) being in the preorder array at that index.
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); 1228 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle());
1227 // It is ok to insert instructions before the current during 1229 // It is ok to insert instructions before the current during
1228 // forward iteration. 1230 // forward iteration.
1229 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); 1231 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue);
1230 instantiator_type_arguments()->BindTo(null_constant); 1232 instantiator_type_arguments()->BindTo(null_constant);
1231 } 1233 }
1232 return this; 1234 return this;
1233 } 1235 }
1234 1236
1235 1237
1238 // Recognize the bpattern (a & b) == 0 where left is a bitwise and operation
1239 // and right is a constant 0.
1240 static bool RecognizeTestPattern(Value* left, Value* right) {
1241 if (!right->BindsToConstant()) {
1242 return false;
1243 }
1244
1245 const Object& value = right->BoundConstant();
1246 if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) {
1247 return false;
1248 }
1249
1250 Definition* left_defn = left->definition();
1251 return left_defn->IsBinarySmiOp() &&
1252 (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) &&
1253 left_defn->HasOnlyUse(left);
1254 }
1255
1256
1236 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1257 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
1237 // Only handle strict-compares. 1258 // Only handle strict-compares.
1238 if (comparison()->IsStrictCompare()) { 1259 if (comparison()->IsStrictCompare()) {
1239 Definition* replacement = comparison()->Canonicalize(optimizer); 1260 Definition* replacement = comparison()->Canonicalize(optimizer);
1240 if ((replacement == comparison()) || (replacement == NULL)) { 1261 if ((replacement == comparison()) || (replacement == NULL)) {
1241 return this; 1262 return this;
1242 } 1263 }
1243 ComparisonInstr* comp = replacement->AsComparison(); 1264 ComparisonInstr* comp = replacement->AsComparison();
1244 if ((comp == NULL) || comp->CanDeoptimize()) { 1265 if ((comp == NULL) || comp->CanDeoptimize()) {
1245 return this; 1266 return this;
1246 } 1267 }
1247 1268
1248 // Check that comparison is not serving as a pending deoptimization target 1269 // Check that comparison is not serving as a pending deoptimization target
1249 // for conversions. 1270 // for conversions.
1250 for (intptr_t i = 0; i < comp->InputCount(); i++) { 1271 for (intptr_t i = 0; i < comp->InputCount(); i++) {
1251 if (comp->RequiredInputRepresentation(i) != 1272 if (comp->RequiredInputRepresentation(i) !=
1252 comp->InputAt(i)->definition()->representation()) { 1273 comp->InputAt(i)->definition()->representation()) {
1253 return this; 1274 return this;
1254 } 1275 }
1255 } 1276 }
1256 1277
1257 // Replace the comparison if the replacement is used at this branch, 1278 // Replace the comparison if the replacement is used at this branch,
1258 // and has exactly one use. 1279 // and has exactly one use.
1259 Value* use = comp->input_use_list(); 1280 Value* use = comp->input_use_list();
1260 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { 1281 if ((use->instruction() == this) && comp->HasOnlyUse(use)) {
1261 RemoveEnvironment(); 1282 RemoveEnvironment();
1262 InheritDeoptTarget(comp); 1283 InheritDeoptTarget(comp);
1263 1284
1285 comp->RemoveEnvironment();
1264 comp->RemoveFromGraph(); 1286 comp->RemoveFromGraph();
1265 SetComparison(comp); 1287 SetComparison(comp);
1266 if (FLAG_trace_optimization) { 1288 if (FLAG_trace_optimization) {
1267 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); 1289 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index());
1268 } 1290 }
1269 // Clear the comparison's temp index and ssa temp index since the 1291 // Clear the comparison's temp index and ssa temp index since the
1270 // value of the comparison is not used outside the branch anymore. 1292 // value of the comparison is not used outside the branch anymore.
1271 ASSERT(comp->input_use_list() == NULL); 1293 ASSERT(comp->input_use_list() == NULL);
1272 comp->ClearSSATempIndex(); 1294 comp->ClearSSATempIndex();
1273 comp->ClearTempIndex(); 1295 comp->ClearTempIndex();
1274 } 1296 }
1297 } else if (comparison()->IsSmiEquality()) {
1298 BinarySmiOpInstr* bit_and = NULL;
1299 if (RecognizeTestPattern(comparison()->left(), comparison()->right())) {
1300 bit_and = comparison()->left()->definition()->AsBinarySmiOp();
1301 } else if (RecognizeTestPattern(comparison()->right(),
1302 comparison()->left())) {
1303 bit_and = comparison()->right()->definition()->AsBinarySmiOp();
1304 }
1305
1306 if (bit_and != NULL) {
1307 TestSmiInstr* test = new TestSmiInstr(comparison()->kind(),
1308 bit_and->left()->Copy(),
1309 bit_and->right()->Copy());
1310 ASSERT(!CanDeoptimize());
1311 InheritDeoptTarget(bit_and);
1312 RemoveEnvironment();
1313 SetComparison(test);
1314 bit_and->RemoveFromGraph();
1315 }
1275 } 1316 }
1276 return this; 1317 return this;
1277 } 1318 }
1278 1319
1279 1320
1280 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1321 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
1281 if (!right()->BindsToConstant()) { 1322 if (!right()->BindsToConstant()) {
1282 return this; 1323 return this;
1283 } 1324 }
1284 const Object& right_constant = right()->BoundConstant(); 1325 const Object& right_constant = right()->BoundConstant();
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2388 default: 2429 default:
2389 UNREACHABLE(); 2430 UNREACHABLE();
2390 } 2431 }
2391 return kPowRuntimeEntry; 2432 return kPowRuntimeEntry;
2392 } 2433 }
2393 2434
2394 2435
2395 #undef __ 2436 #undef __
2396 2437
2397 } // namespace dart 2438 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698