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

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
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* comp) {
632 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { 633 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) {
633 Value* input = comp->InputAt(i); 634 Value* input = comp->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(comp->env() == NULL);
639 // Remove the current comparison's input uses. 641 // Remove the current comparison's input uses.
srdjan 2013/04/15 20:27:27 Would be probable more readable if CompareInstr* w
Vyacheslav Egorov (Google) 2013/04/16 11:51:16 I think instr is somewhat confusing as well. I ren
640 comparison()->UnuseAllInputs(); 642 comparison()->UnuseAllInputs();
641 ASSERT(!comp->HasUses()); 643 ASSERT(!comp->HasUses());
642 comparison_ = comp; 644 comparison_ = comp;
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
(...skipping 576 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 static bool RecognizeTestPattern(Value* left, Value* right) {
srdjan 2013/04/15 20:27:27 Add comment what pattern is being recognized.
Vyacheslav Egorov (Google) 2013/04/16 11:51:16 Done.
1239 if (!right->BindsToConstant()) {
1240 return false;
1241 }
1242
1243 const Object& value = right->BoundConstant();
1244 if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) {
1245 return false;
1246 }
1247
1248 Definition* left_defn = left->definition();
1249 return left_defn->IsBinarySmiOp() &&
1250 (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) &&
1251 left_defn->HasOnlyUse(left);
1252 }
1253
1254
1236 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1255 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
1237 // Only handle strict-compares. 1256 // Only handle strict-compares.
1238 if (comparison()->IsStrictCompare()) { 1257 if (comparison()->IsStrictCompare()) {
1239 Definition* replacement = comparison()->Canonicalize(optimizer); 1258 Definition* replacement = comparison()->Canonicalize(optimizer);
1240 if ((replacement == comparison()) || (replacement == NULL)) { 1259 if ((replacement == comparison()) || (replacement == NULL)) {
1241 return this; 1260 return this;
1242 } 1261 }
1243 ComparisonInstr* comp = replacement->AsComparison(); 1262 ComparisonInstr* comp = replacement->AsComparison();
1244 if ((comp == NULL) || comp->CanDeoptimize()) { 1263 if ((comp == NULL) || comp->CanDeoptimize()) {
1245 return this; 1264 return this;
1246 } 1265 }
1247 1266
1248 // Check that comparison is not serving as a pending deoptimization target 1267 // Check that comparison is not serving as a pending deoptimization target
1249 // for conversions. 1268 // for conversions.
1250 for (intptr_t i = 0; i < comp->InputCount(); i++) { 1269 for (intptr_t i = 0; i < comp->InputCount(); i++) {
1251 if (comp->RequiredInputRepresentation(i) != 1270 if (comp->RequiredInputRepresentation(i) !=
1252 comp->InputAt(i)->definition()->representation()) { 1271 comp->InputAt(i)->definition()->representation()) {
1253 return this; 1272 return this;
1254 } 1273 }
1255 } 1274 }
1256 1275
1257 // Replace the comparison if the replacement is used at this branch, 1276 // Replace the comparison if the replacement is used at this branch,
1258 // and has exactly one use. 1277 // and has exactly one use.
1259 Value* use = comp->input_use_list(); 1278 Value* use = comp->input_use_list();
1260 if ((use->instruction() == this) && comp->HasOnlyUse(use)) { 1279 if ((use->instruction() == this) && comp->HasOnlyUse(use)) {
1261 RemoveEnvironment(); 1280 RemoveEnvironment();
1262 InheritDeoptTarget(comp); 1281 InheritDeoptTarget(comp);
1263 1282
1283 comp->RemoveEnvironment();
1264 comp->RemoveFromGraph(); 1284 comp->RemoveFromGraph();
1265 SetComparison(comp); 1285 SetComparison(comp);
1266 if (FLAG_trace_optimization) { 1286 if (FLAG_trace_optimization) {
1267 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); 1287 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index());
1268 } 1288 }
1269 // Clear the comparison's temp index and ssa temp index since the 1289 // Clear the comparison's temp index and ssa temp index since the
1270 // value of the comparison is not used outside the branch anymore. 1290 // value of the comparison is not used outside the branch anymore.
1271 ASSERT(comp->input_use_list() == NULL); 1291 ASSERT(comp->input_use_list() == NULL);
1272 comp->ClearSSATempIndex(); 1292 comp->ClearSSATempIndex();
1273 comp->ClearTempIndex(); 1293 comp->ClearTempIndex();
1274 } 1294 }
1295 } else if (comparison()->IsSmiEquality()) {
1296 BinarySmiOpInstr* bit_and = NULL;
1297 if (RecognizeTestPattern(comparison()->left(), comparison()->right())) {
1298 bit_and = comparison()->left()->definition()->AsBinarySmiOp();
1299 } else if (RecognizeTestPattern(comparison()->right(),
1300 comparison()->left())) {
1301 bit_and = comparison()->right()->definition()->AsBinarySmiOp();
1302 }
1303
1304 if (bit_and != NULL) {
1305 TestSmiInstr* test = new TestSmiInstr(comparison()->kind(),
1306 bit_and->left()->Copy(),
1307 bit_and->right()->Copy());
1308 ASSERT(!CanDeoptimize());
1309 InheritDeoptTarget(bit_and);
1310 RemoveEnvironment();
1311 SetComparison(test);
1312 bit_and->RemoveFromGraph();
1313 }
1275 } 1314 }
1276 return this; 1315 return this;
1277 } 1316 }
1278 1317
1279 1318
1280 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1319 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
1281 if (!right()->BindsToConstant()) { 1320 if (!right()->BindsToConstant()) {
1282 return this; 1321 return this;
1283 } 1322 }
1284 const Object& right_constant = right()->BoundConstant(); 1323 const Object& right_constant = right()->BoundConstant();
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2388 default: 2427 default:
2389 UNREACHABLE(); 2428 UNREACHABLE();
2390 } 2429 }
2391 return kPowRuntimeEntry; 2430 return kPowRuntimeEntry;
2392 } 2431 }
2393 2432
2394 2433
2395 #undef __ 2434 #undef __
2396 2435
2397 } // namespace dart 2436 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698