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

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

Issue 345563007: Add Uint32 representation (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 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/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 260
261 static bool IsPositiveOrZeroSmiConst(Definition* d) { 261 static bool IsPositiveOrZeroSmiConst(Definition* d) {
262 ConstantInstr* const_instr = d->AsConstant(); 262 ConstantInstr* const_instr = d->AsConstant();
263 if ((const_instr != NULL) && (const_instr->value().IsSmi())) { 263 if ((const_instr != NULL) && (const_instr->value().IsSmi())) {
264 return Smi::Cast(const_instr->value()).Value() >= 0; 264 return Smi::Cast(const_instr->value()).Value() >= 0;
265 } 265 }
266 return false; 266 return false;
267 } 267 }
268 268
269 269
270 Definition* FlowGraphOptimizer::OptimizeMint32BitMasks(
271 BinaryMintOpInstr* mask) {
272 ASSERT(mask != NULL);
273 ASSERT(mask->op_kind() == Token::kBIT_AND);
274 Range* range = mask->range();
275 if ((range == NULL) || !range->Is32BitMask()) {
Florian Schneider 2014/06/25 11:36:00 This should work for any positive mask value, not
276 // No range or range is not exactly [0, 0xFFFFFFFF].
277 return NULL;
278 }
279 // Find the mask target by looking for the input that isn't the constant
280 // 0xFFFFFFFF.
281 Value* target = NULL;
282 if (mask->InputAt(0)->BindsTo32BitMaskConstant()) {
283 target = mask->InputAt(1);
284 } else if (mask->InputAt(1)->BindsTo32BitMaskConstant()) {
285 target = mask->InputAt(0);
286 } else {
287 return NULL;
288 }
289 // If the target has multiple uses, we can't assume its range can be safely
290 // constrained by this mask.
291 if (!target->IsSingleUse()) {
Florian Schneider 2014/06/25 11:36:00 That's too strict: It's ok as long as target is ma
292 return NULL;
293 }
294
295 Definition* def = target->definition();
296 if (!def->IsMintDefinition()) {
297 // TODO(johnmccutchan): Should this be an ASSERT?
298 return NULL;
299 }
300 def->range()->Make32BitMask();
301
302 return def;
303 }
304
305
306 bool FlowGraphOptimizer::TryMarkMint32Bit(Definition* mintop) {
307 ASSERT(mintop != NULL);
308 ASSERT(mintop->IsMintDefinition());
309
310 Range* range = mintop->range();
311 if (range == NULL) {
312 return false;
313 }
314 bool is_32_bit = false;
315 if (range->Is32BitMask()) {
316 is_32_bit = true;
317 } else if (range->IsWithin(0, kMaxUint32)) {
318 is_32_bit = true;
319 }
320
321 if (!is_32_bit) {
322 return false;
323 }
324
325 if (mintop->IsBinaryMintOp()) {
326 BinaryMintOpInstr* instr = mintop->AsBinaryMintOp();
327 instr->set_is_32_bit(true);
328 } else if (mintop->IsShiftMintOp()) {
329 ShiftMintOpInstr* instr = mintop->AsShiftMintOp();
330 instr->set_is_32_bit(true);
331 } else if (mintop->IsUnboxInteger()) {
332 UnboxIntegerInstr* instr = mintop->AsUnboxInteger();
333 instr->set_is_32_bit(true);
334 } else if (mintop->IsUnaryMintOp()) {
335 UnaryMintOpInstr* instr = mintop->AsUnaryMintOp();
336 instr->set_is_32_bit(true);
337 } else {
338 return false;
339 }
340
341 return true;
342 }
343
344
270 void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp( 345 void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp(
271 Definition* bit_and_instr, 346 Definition* bit_and_instr,
272 Definition* left_instr, 347 Definition* left_instr,
273 Definition* right_instr) { 348 Definition* right_instr) {
274 ASSERT(bit_and_instr != NULL); 349 ASSERT(bit_and_instr != NULL);
275 ASSERT((left_instr != NULL) && (right_instr != NULL)); 350 ASSERT((left_instr != NULL) && (right_instr != NULL));
276 351
277 // Check for pattern, smi_shift_left must be single-use. 352 // Check for pattern, smi_shift_left must be single-use.
278 bool is_positive_or_zero = IsPositiveOrZeroSmiConst(left_instr); 353 bool is_positive_or_zero = IsPositiveOrZeroSmiConst(left_instr);
279 if (!is_positive_or_zero) { 354 if (!is_positive_or_zero) {
280 is_positive_or_zero = IsPositiveOrZeroSmiConst(right_instr); 355 is_positive_or_zero = IsPositiveOrZeroSmiConst(right_instr);
281 } 356 }
282 if (!is_positive_or_zero) return; 357 if (!is_positive_or_zero) {
358 return;
359 }
283 360
284 BinarySmiOpInstr* smi_shift_left = NULL; 361 BinarySmiOpInstr* smi_shift_left = NULL;
285 if (bit_and_instr->InputAt(0)->IsSingleUse()) { 362 if (bit_and_instr->InputAt(0)->IsSingleUse()) {
286 smi_shift_left = AsSmiShiftLeftInstruction(left_instr); 363 smi_shift_left = AsSmiShiftLeftInstruction(left_instr);
287 } 364 }
288 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) { 365 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) {
289 smi_shift_left = AsSmiShiftLeftInstruction(right_instr); 366 smi_shift_left = AsSmiShiftLeftInstruction(right_instr);
290 } 367 }
291 if (smi_shift_left == NULL) return; 368 if (smi_shift_left == NULL) {
369 return;
370 }
292 371
293 // Pattern recognized. 372 // Pattern recognized.
294 smi_shift_left->set_is_truncating(true); 373 smi_shift_left->set_is_truncating(true);
295 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp()); 374 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp());
296 if (bit_and_instr->IsBinaryMintOp()) { 375 if (bit_and_instr->IsBinaryMintOp()) {
297 // Replace Mint op with Smi op. 376 // Replace Mint op with Smi op.
298 BinarySmiOpInstr* smi_op = new(I) BinarySmiOpInstr( 377 BinarySmiOpInstr* smi_op = new(I) BinarySmiOpInstr(
299 Token::kBIT_AND, 378 Token::kBIT_AND,
300 new(I) Value(left_instr), 379 new(I) Value(left_instr),
301 new(I) Value(right_instr), 380 new(I) Value(right_instr),
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 } 597 }
519 } 598 }
520 } 599 }
521 } 600 }
522 TryMergeTruncDivMod(&div_mod_merge); 601 TryMergeTruncDivMod(&div_mod_merge);
523 TryMergeMathUnary(&sin_cos_merge); 602 TryMergeMathUnary(&sin_cos_merge);
524 current_iterator_ = NULL; 603 current_iterator_ = NULL;
525 } 604 }
526 } 605 }
527 606
528
529 static void EnsureSSATempIndex(FlowGraph* graph, 607 static void EnsureSSATempIndex(FlowGraph* graph,
530 Definition* defn, 608 Definition* defn,
531 Definition* replacement) { 609 Definition* replacement) {
532 if ((replacement->ssa_temp_index() == -1) && 610 if ((replacement->ssa_temp_index() == -1) &&
533 (defn->ssa_temp_index() != -1)) { 611 (defn->ssa_temp_index() != -1)) {
534 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index()); 612 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index());
535 } 613 }
536 } 614 }
537 615
538 616
(...skipping 18 matching lines...) Expand all
557 OS::Print("Removing %s\n", current->DebugName()); 635 OS::Print("Removing %s\n", current->DebugName());
558 } else { 636 } else {
559 ASSERT(!current_defn->HasUses()); 637 ASSERT(!current_defn->HasUses());
560 OS::Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index()); 638 OS::Print("Removing v%" Pd ".\n", current_defn->ssa_temp_index());
561 } 639 }
562 } 640 }
563 iterator->RemoveCurrentFromGraph(); 641 iterator->RemoveCurrentFromGraph();
564 } 642 }
565 643
566 644
645 void FlowGraphOptimizer::TryRangeDerivedOptimizations() {
646 ASSERT(current_iterator_ == NULL);
647
648 for (intptr_t i = 0; i < block_order_.length(); ++i) {
649 BlockEntryInstr* entry = block_order_[i];
650 // First set range information on inputs to a mint mask. The following two
651 // patterns are supported:
652 // v7 & 0xFFFFFFFF;
653 // 0xFFFFFFFF & v7;
654 // Afterwards, if v7 only has a single use, v7 is marked as having
655 // a 32-bit range. Also, the mask operation is removed.
656 {
657 ForwardInstructionIterator it(entry);
658 current_iterator_ = &it;
659 for (; !it.Done(); it.Advance()) {
660 // Constrain ranges of mint operations whose only use is a mint mask op.
661 if (it.Current()->IsBinaryMintOp()) {
662 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
663 if (mintop->op_kind() == Token::kBIT_AND) {
664 Definition* masked = OptimizeMint32BitMasks(mintop);
665 if (masked != NULL) {
666 // Replace mask instruction with masked input.
667 ReplaceCurrentInstruction(current_iterator(),
668 mintop,
669 masked,
670 flow_graph());
671 }
672 }
673 }
674 }
675 current_iterator_ = NULL;
676 }
677 // Mark mint instructions whose range information says they are positive
678 // and fit in 32-bits as 32-bit.
679 {
680 ForwardInstructionIterator it(entry);
681 current_iterator_ = &it;
682 for (; !it.Done(); it.Advance()) {
683 if (!it.Current()->IsDefinition()) {
684 continue;
685 }
686 Definition* def = it.Current()->AsDefinition();
687 if (def->IsMintDefinition()) {
688 TryMarkMint32Bit(def);
689 }
690 }
691 current_iterator_ = NULL;
692 }
693 }
694 }
695
696
567 bool FlowGraphOptimizer::Canonicalize() { 697 bool FlowGraphOptimizer::Canonicalize() {
568 bool changed = false; 698 bool changed = false;
569 for (intptr_t i = 0; i < block_order_.length(); ++i) { 699 for (intptr_t i = 0; i < block_order_.length(); ++i) {
570 BlockEntryInstr* entry = block_order_[i]; 700 BlockEntryInstr* entry = block_order_[i];
571 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 701 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
572 Instruction* current = it.Current(); 702 Instruction* current = it.Current();
573 Instruction* replacement = current->Canonicalize(flow_graph()); 703 Instruction* replacement = current->Canonicalize(flow_graph());
574 if (replacement != current) { 704 if (replacement != current) {
575 // For non-definitions Canonicalize should return either NULL or 705 // For non-definitions Canonicalize should return either NULL or
576 // this. 706 // this.
(...skipping 27 matching lines...) Expand all
604 Definition* converted = NULL; 734 Definition* converted = NULL;
605 if ((from == kTagged) && (to == kUnboxedMint)) { 735 if ((from == kTagged) && (to == kUnboxedMint)) {
606 ASSERT((deopt_target != NULL) || 736 ASSERT((deopt_target != NULL) ||
607 (use->Type()->ToCid() == kUnboxedMint)); 737 (use->Type()->ToCid() == kUnboxedMint));
608 const intptr_t deopt_id = (deopt_target != NULL) ? 738 const intptr_t deopt_id = (deopt_target != NULL) ?
609 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 739 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
610 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id); 740 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id);
611 741
612 } else if ((from == kUnboxedMint) && (to == kTagged)) { 742 } else if ((from == kUnboxedMint) && (to == kTagged)) {
613 converted = new(I) BoxIntegerInstr(use->CopyWithType()); 743 converted = new(I) BoxIntegerInstr(use->CopyWithType());
614 744 } else if ((from == kUnboxedMint) && (to == kUnboxedMint32)) {
745 converted = new(I) MintConverterInstr(MintConverterInstr::kMintToMint32,
746 use->CopyWithType());
747 } else if ((from == kUnboxedMint32) && (to == kUnboxedMint)) {
748 converted = new(I) MintConverterInstr(MintConverterInstr::kMint32ToMint,
749 use->CopyWithType());
615 } else if (from == kUnboxedMint && to == kUnboxedDouble) { 750 } else if (from == kUnboxedMint && to == kUnboxedDouble) {
616 ASSERT(CanUnboxDouble()); 751 ASSERT(CanUnboxDouble());
617 // Convert by boxing/unboxing. 752 // Convert by boxing/unboxing.
618 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. 753 // TODO(fschneider): Implement direct unboxed mint-to-double conversion.
619 BoxIntegerInstr* boxed = 754 BoxIntegerInstr* boxed =
620 new(I) BoxIntegerInstr(use->CopyWithType()); 755 new(I) BoxIntegerInstr(use->CopyWithType());
621 use->BindTo(boxed); 756 use->BindTo(boxed);
622 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); 757 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue);
623 758
624 const intptr_t deopt_id = (deopt_target != NULL) ? 759 const intptr_t deopt_id = (deopt_target != NULL) ?
(...skipping 7870 matching lines...) Expand 10 before | Expand all | Expand 10 after
8495 // TODO(kmillikin): Handle unbox operation. 8630 // TODO(kmillikin): Handle unbox operation.
8496 SetValue(instr, non_constant_); 8631 SetValue(instr, non_constant_);
8497 } 8632 }
8498 8633
8499 8634
8500 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { 8635 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) {
8501 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); 8636 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right());
8502 } 8637 }
8503 8638
8504 8639
8640 void ConstantPropagator::VisitMintConverter(MintConverterInstr* instr) {
8641 SetValue(instr, non_constant_);
8642 }
8643
8644
8505 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) { 8645 void ConstantPropagator::VisitShiftMintOp(ShiftMintOpInstr* instr) {
8506 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); 8646 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right());
8507 } 8647 }
8508 8648
8509 8649
8510 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) { 8650 void ConstantPropagator::VisitUnaryMintOp(UnaryMintOpInstr* instr) {
8511 // TODO(kmillikin): Handle unary operations. 8651 // TODO(kmillikin): Handle unary operations.
8512 SetValue(instr, non_constant_); 8652 SetValue(instr, non_constant_);
8513 } 8653 }
8514 8654
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after
9818 } 9958 }
9819 9959
9820 // Insert materializations at environment uses. 9960 // Insert materializations at environment uses.
9821 for (intptr_t i = 0; i < exits.length(); i++) { 9961 for (intptr_t i = 0; i < exits.length(); i++) {
9822 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); 9962 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots);
9823 } 9963 }
9824 } 9964 }
9825 9965
9826 9966
9827 } // namespace dart 9967 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698