| OLD | NEW |
| 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/constant_propagator.h" | 5 #include "vm/constant_propagator.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
| 9 #include "vm/flow_graph_compiler.h" | 9 #include "vm/flow_graph_compiler.h" |
| 10 #include "vm/flow_graph_range_analysis.h" | 10 #include "vm/flow_graph_range_analysis.h" |
| 11 #include "vm/il_printer.h" | 11 #include "vm/il_printer.h" |
| 12 #include "vm/intermediate_language.h" | 12 #include "vm/intermediate_language.h" |
| 13 #include "vm/parser.h" | 13 #include "vm/parser.h" |
| 14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); | 18 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); |
| 19 DEFINE_FLAG(bool, trace_constant_propagation, false, | 19 DEFINE_FLAG(bool, |
| 20 "Print constant propagation and useless code elimination."); | 20 trace_constant_propagation, |
| 21 false, |
| 22 "Print constant propagation and useless code elimination."); |
| 21 | 23 |
| 22 // Quick access to the current zone and isolate. | 24 // Quick access to the current zone and isolate. |
| 23 #define I (isolate()) | 25 #define I (isolate()) |
| 24 #define Z (graph_->zone()) | 26 #define Z (graph_->zone()) |
| 25 | 27 |
| 26 | 28 |
| 27 ConstantPropagator::ConstantPropagator( | 29 ConstantPropagator::ConstantPropagator( |
| 28 FlowGraph* graph, | 30 FlowGraph* graph, |
| 29 const GrowableArray<BlockEntryInstr*>& ignored) | 31 const GrowableArray<BlockEntryInstr*>& ignored) |
| 30 : FlowGraphVisitor(ignored), | 32 : FlowGraphVisitor(ignored), |
| 31 graph_(graph), | 33 graph_(graph), |
| 32 unknown_(Object::unknown_constant()), | 34 unknown_(Object::unknown_constant()), |
| 33 non_constant_(Object::non_constant()), | 35 non_constant_(Object::non_constant()), |
| 34 reachable_(new(Z) BitVector( | 36 reachable_(new (Z) BitVector(Z, graph->preorder().length())), |
| 35 Z, graph->preorder().length())), | 37 marked_phis_(new (Z) BitVector(Z, graph->max_virtual_register_number())), |
| 36 marked_phis_(new(Z) BitVector( | |
| 37 Z, graph->max_virtual_register_number())), | |
| 38 block_worklist_(), | 38 block_worklist_(), |
| 39 definition_worklist_(graph, 10) {} | 39 definition_worklist_(graph, 10) {} |
| 40 | 40 |
| 41 | 41 |
| 42 void ConstantPropagator::Optimize(FlowGraph* graph) { | 42 void ConstantPropagator::Optimize(FlowGraph* graph) { |
| 43 GrowableArray<BlockEntryInstr*> ignored; | 43 GrowableArray<BlockEntryInstr*> ignored; |
| 44 ConstantPropagator cp(graph, ignored); | 44 ConstantPropagator cp(graph, ignored); |
| 45 cp.Analyze(); | 45 cp.Analyze(); |
| 46 cp.Transform(); | 46 cp.Transform(); |
| 47 } | 47 } |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 } | 228 } |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 } | 231 } |
| 232 | 232 |
| 233 | 233 |
| 234 // -------------------------------------------------------------------------- | 234 // -------------------------------------------------------------------------- |
| 235 // Analysis of non-definition instructions. They do not have values so they | 235 // Analysis of non-definition instructions. They do not have values so they |
| 236 // cannot have constant values. | 236 // cannot have constant values. |
| 237 void ConstantPropagator::VisitCheckStackOverflow( | 237 void ConstantPropagator::VisitCheckStackOverflow( |
| 238 CheckStackOverflowInstr* instr) { } | 238 CheckStackOverflowInstr* instr) {} |
| 239 | 239 |
| 240 | 240 |
| 241 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } | 241 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {} |
| 242 | 242 |
| 243 | 243 |
| 244 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { } | 244 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) {} |
| 245 | 245 |
| 246 | 246 |
| 247 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) { } | 247 void ConstantPropagator::VisitGuardFieldClass(GuardFieldClassInstr* instr) {} |
| 248 | 248 |
| 249 | 249 |
| 250 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) { } | 250 void ConstantPropagator::VisitGuardFieldLength(GuardFieldLengthInstr* instr) {} |
| 251 | 251 |
| 252 | 252 |
| 253 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { } | 253 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {} |
| 254 | 254 |
| 255 | 255 |
| 256 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { | 256 void ConstantPropagator::VisitGenericCheckBound(GenericCheckBoundInstr* instr) { |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 void ConstantPropagator::VisitCheckEitherNonSmi( | 260 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { |
| 261 CheckEitherNonSmiInstr* instr) { } | 261 } |
| 262 | 262 |
| 263 | 263 |
| 264 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } | 264 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {} |
| 265 | 265 |
| 266 | 266 |
| 267 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { | 267 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { |
| 268 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. | 268 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. |
| 269 } | 269 } |
| 270 | 270 |
| 271 void ConstantPropagator::VisitGrowRegExpStack(GrowRegExpStackInstr* instr) { } | 271 void ConstantPropagator::VisitGrowRegExpStack(GrowRegExpStackInstr* instr) {} |
| 272 | 272 |
| 273 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { | 273 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) { |
| 274 if (defn->IsPhi()) { | 274 if (defn->IsPhi()) { |
| 275 JoinEntryInstr* block = defn->AsPhi()->block(); | 275 JoinEntryInstr* block = defn->AsPhi()->block(); |
| 276 | 276 |
| 277 Definition* input = NULL; | 277 Definition* input = NULL; |
| 278 for (intptr_t i = 0; i < defn->InputCount(); ++i) { | 278 for (intptr_t i = 0; i < defn->InputCount(); ++i) { |
| 279 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { | 279 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) { |
| 280 if (input == NULL) { | 280 if (input == NULL) { |
| 281 input = defn->InputAt(i)->definition(); | 281 input = defn->InputAt(i)->definition(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 302 // Analysis of definitions. Compute the constant value. If it has changed | 302 // Analysis of definitions. Compute the constant value. If it has changed |
| 303 // and the definition has input uses, add the definition to the definition | 303 // and the definition has input uses, add the definition to the definition |
| 304 // worklist so that the used can be processed. | 304 // worklist so that the used can be processed. |
| 305 void ConstantPropagator::VisitPhi(PhiInstr* instr) { | 305 void ConstantPropagator::VisitPhi(PhiInstr* instr) { |
| 306 // Compute the join over all the reachable predecessor values. | 306 // Compute the join over all the reachable predecessor values. |
| 307 JoinEntryInstr* block = instr->block(); | 307 JoinEntryInstr* block = instr->block(); |
| 308 Object& value = Object::ZoneHandle(Z, Unknown()); | 308 Object& value = Object::ZoneHandle(Z, Unknown()); |
| 309 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { | 309 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { |
| 310 if (reachable_->Contains( | 310 if (reachable_->Contains( |
| 311 block->PredecessorAt(pred_idx)->preorder_number())) { | 311 block->PredecessorAt(pred_idx)->preorder_number())) { |
| 312 Join(&value, | 312 Join(&value, instr->InputAt(pred_idx)->definition()->constant_value()); |
| 313 instr->InputAt(pred_idx)->definition()->constant_value()); | |
| 314 } | 313 } |
| 315 } | 314 } |
| 316 if (!SetValue(instr, value) && | 315 if (!SetValue(instr, value) && |
| 317 marked_phis_->Contains(instr->ssa_temp_index())) { | 316 marked_phis_->Contains(instr->ssa_temp_index())) { |
| 318 marked_phis_->Remove(instr->ssa_temp_index()); | 317 marked_phis_->Remove(instr->ssa_temp_index()); |
| 319 definition_worklist_.Add(instr); | 318 definition_worklist_.Add(instr); |
| 320 } | 319 } |
| 321 } | 320 } |
| 322 | 321 |
| 323 | 322 |
| 324 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { | 323 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { |
| 325 // Ensure that we never remove redefinition of a constant unless we are also | 324 // Ensure that we never remove redefinition of a constant unless we are also |
| 326 // are guaranteed to fold away code paths that correspond to non-matching | 325 // are guaranteed to fold away code paths that correspond to non-matching |
| 327 // class ids. Otherwise LICM might potentially hoist incorrect code. | 326 // class ids. Otherwise LICM might potentially hoist incorrect code. |
| 328 const Object& value = instr->value()->definition()->constant_value(); | 327 const Object& value = instr->value()->definition()->constant_value(); |
| 329 if (IsConstant(value) && | 328 if (IsConstant(value) && !Field::IsExternalizableCid(value.GetClassId())) { |
| 330 !Field::IsExternalizableCid(value.GetClassId())) { | |
| 331 SetValue(instr, value); | 329 SetValue(instr, value); |
| 332 } else { | 330 } else { |
| 333 SetValue(instr, non_constant_); | 331 SetValue(instr, non_constant_); |
| 334 } | 332 } |
| 335 } | 333 } |
| 336 | 334 |
| 337 | 335 |
| 338 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { | 336 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { |
| 339 SetValue(instr, non_constant_); | 337 SetValue(instr, non_constant_); |
| 340 } | 338 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 | 419 |
| 422 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { | 420 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { |
| 423 instr->comparison()->Accept(this); | 421 instr->comparison()->Accept(this); |
| 424 const Object& value = instr->comparison()->constant_value(); | 422 const Object& value = instr->comparison()->constant_value(); |
| 425 if (IsNonConstant(value)) { | 423 if (IsNonConstant(value)) { |
| 426 SetValue(instr, non_constant_); | 424 SetValue(instr, non_constant_); |
| 427 } else if (IsConstant(value)) { | 425 } else if (IsConstant(value)) { |
| 428 ASSERT(!value.IsNull()); | 426 ASSERT(!value.IsNull()); |
| 429 ASSERT(value.IsBool()); | 427 ASSERT(value.IsBool()); |
| 430 bool result = Bool::Cast(value).value(); | 428 bool result = Bool::Cast(value).value(); |
| 431 SetValue(instr, | 429 SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true() |
| 432 Smi::Handle(Z, Smi::New( | 430 : instr->if_false()))); |
| 433 result ? instr->if_true() : instr->if_false()))); | |
| 434 } | 431 } |
| 435 } | 432 } |
| 436 | 433 |
| 437 | 434 |
| 438 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { | 435 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { |
| 439 Definition* left_defn = instr->left()->definition(); | 436 Definition* left_defn = instr->left()->definition(); |
| 440 Definition* right_defn = instr->right()->definition(); | 437 Definition* right_defn = instr->right()->definition(); |
| 441 | 438 |
| 442 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); | 439 Definition* unwrapped_left_defn = UnwrapPhi(left_defn); |
| 443 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); | 440 Definition* unwrapped_right_defn = UnwrapPhi(right_defn); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 SetValue(instr, Bool::Get(result)); | 483 SetValue(instr, Bool::Get(result)); |
| 487 } | 484 } |
| 488 } | 485 } |
| 489 | 486 |
| 490 | 487 |
| 491 static bool CompareIntegers(Token::Kind kind, | 488 static bool CompareIntegers(Token::Kind kind, |
| 492 const Integer& left, | 489 const Integer& left, |
| 493 const Integer& right) { | 490 const Integer& right) { |
| 494 const int result = left.CompareWith(right); | 491 const int result = left.CompareWith(right); |
| 495 switch (kind) { | 492 switch (kind) { |
| 496 case Token::kEQ: return (result == 0); | 493 case Token::kEQ: |
| 497 case Token::kNE: return (result != 0); | 494 return (result == 0); |
| 498 case Token::kLT: return (result < 0); | 495 case Token::kNE: |
| 499 case Token::kGT: return (result > 0); | 496 return (result != 0); |
| 500 case Token::kLTE: return (result <= 0); | 497 case Token::kLT: |
| 501 case Token::kGTE: return (result >= 0); | 498 return (result < 0); |
| 499 case Token::kGT: |
| 500 return (result > 0); |
| 501 case Token::kLTE: |
| 502 return (result <= 0); |
| 503 case Token::kGTE: |
| 504 return (result >= 0); |
| 502 default: | 505 default: |
| 503 UNREACHABLE(); | 506 UNREACHABLE(); |
| 504 return false; | 507 return false; |
| 505 } | 508 } |
| 506 } | 509 } |
| 507 | 510 |
| 508 | 511 |
| 509 // Comparison instruction that is equivalent to the (left & right) == 0 | 512 // Comparison instruction that is equivalent to the (left & right) == 0 |
| 510 // comparison pattern. | 513 // comparison pattern. |
| 511 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { | 514 void ConstantPropagator::VisitTestSmi(TestSmiInstr* instr) { |
| 512 const Object& left = instr->left()->definition()->constant_value(); | 515 const Object& left = instr->left()->definition()->constant_value(); |
| 513 const Object& right = instr->right()->definition()->constant_value(); | 516 const Object& right = instr->right()->definition()->constant_value(); |
| 514 if (IsNonConstant(left) || IsNonConstant(right)) { | 517 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 515 SetValue(instr, non_constant_); | 518 SetValue(instr, non_constant_); |
| 516 } else if (IsConstant(left) && IsConstant(right)) { | 519 } else if (IsConstant(left) && IsConstant(right)) { |
| 517 // BitOp does not work on Bigints. | 520 // BitOp does not work on Bigints. |
| 518 if (left.IsInteger() && right.IsInteger() && | 521 if (left.IsInteger() && right.IsInteger() && !left.IsBigint() && |
| 519 !left.IsBigint() && !right.IsBigint()) { | 522 !right.IsBigint()) { |
| 520 const bool result = CompareIntegers( | 523 const bool result = CompareIntegers( |
| 521 instr->kind(), | 524 instr->kind(), |
| 522 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, | 525 Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND, |
| 523 Integer::Cast(right))), | 526 Integer::Cast(right))), |
| 524 Smi::Handle(Z, Smi::New(0))); | 527 Smi::Handle(Z, Smi::New(0))); |
| 525 SetValue(instr, result ? Bool::True() : Bool::False()); | 528 SetValue(instr, result ? Bool::True() : Bool::False()); |
| 526 } else { | 529 } else { |
| 527 SetValue(instr, non_constant_); | 530 SetValue(instr, non_constant_); |
| 528 } | 531 } |
| 529 } | 532 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 556 return; | 559 return; |
| 557 } | 560 } |
| 558 } | 561 } |
| 559 | 562 |
| 560 const Object& left = left_defn->constant_value(); | 563 const Object& left = left_defn->constant_value(); |
| 561 const Object& right = right_defn->constant_value(); | 564 const Object& right = right_defn->constant_value(); |
| 562 if (IsNonConstant(left) || IsNonConstant(right)) { | 565 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 563 SetValue(instr, non_constant_); | 566 SetValue(instr, non_constant_); |
| 564 } else if (IsConstant(left) && IsConstant(right)) { | 567 } else if (IsConstant(left) && IsConstant(right)) { |
| 565 if (left.IsInteger() && right.IsInteger()) { | 568 if (left.IsInteger() && right.IsInteger()) { |
| 566 const bool result = CompareIntegers(instr->kind(), | 569 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), |
| 567 Integer::Cast(left), | |
| 568 Integer::Cast(right)); | 570 Integer::Cast(right)); |
| 569 SetValue(instr, Bool::Get(result)); | 571 SetValue(instr, Bool::Get(result)); |
| 570 } else if (left.IsString() && right.IsString()) { | 572 } else if (left.IsString() && right.IsString()) { |
| 571 const bool result = String::Cast(left).Equals(String::Cast(right)); | 573 const bool result = String::Cast(left).Equals(String::Cast(right)); |
| 572 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); | 574 SetValue(instr, Bool::Get((instr->kind() == Token::kEQ) == result)); |
| 573 } else { | 575 } else { |
| 574 SetValue(instr, non_constant_); | 576 SetValue(instr, non_constant_); |
| 575 } | 577 } |
| 576 } | 578 } |
| 577 } | 579 } |
| 578 | 580 |
| 579 | 581 |
| 580 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { | 582 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) { |
| 581 const Object& left = instr->left()->definition()->constant_value(); | 583 const Object& left = instr->left()->definition()->constant_value(); |
| 582 const Object& right = instr->right()->definition()->constant_value(); | 584 const Object& right = instr->right()->definition()->constant_value(); |
| 583 if (IsNonConstant(left) || IsNonConstant(right)) { | 585 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 584 SetValue(instr, non_constant_); | 586 SetValue(instr, non_constant_); |
| 585 } else if (IsConstant(left) && IsConstant(right)) { | 587 } else if (IsConstant(left) && IsConstant(right)) { |
| 586 if (left.IsInteger() && right.IsInteger()) { | 588 if (left.IsInteger() && right.IsInteger()) { |
| 587 const bool result = CompareIntegers(instr->kind(), | 589 const bool result = CompareIntegers(instr->kind(), Integer::Cast(left), |
| 588 Integer::Cast(left), | |
| 589 Integer::Cast(right)); | 590 Integer::Cast(right)); |
| 590 SetValue(instr, Bool::Get(result)); | 591 SetValue(instr, Bool::Get(result)); |
| 591 } else if (left.IsDouble() && right.IsDouble()) { | 592 } else if (left.IsDouble() && right.IsDouble()) { |
| 592 // TODO(srdjan): Implement. | 593 // TODO(srdjan): Implement. |
| 593 SetValue(instr, non_constant_); | 594 SetValue(instr, non_constant_); |
| 594 } else { | 595 } else { |
| 595 SetValue(instr, non_constant_); | 596 SetValue(instr, non_constant_); |
| 596 } | 597 } |
| 597 } | 598 } |
| 598 } | 599 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 if (!index_obj.IsSmi()) { | 655 if (!index_obj.IsSmi()) { |
| 655 // Should not occur. | 656 // Should not occur. |
| 656 SetValue(instr, non_constant_); | 657 SetValue(instr, non_constant_); |
| 657 return; | 658 return; |
| 658 } | 659 } |
| 659 const intptr_t index = Smi::Cast(index_obj).Value(); | 660 const intptr_t index = Smi::Cast(index_obj).Value(); |
| 660 if (index >= 0) { | 661 if (index >= 0) { |
| 661 if (array_obj.IsString()) { | 662 if (array_obj.IsString()) { |
| 662 const String& str = String::Cast(array_obj); | 663 const String& str = String::Cast(array_obj); |
| 663 if (str.Length() > index) { | 664 if (str.Length() > index) { |
| 664 SetValue(instr, Smi::Handle(Z, | 665 SetValue(instr, |
| 665 Smi::New(static_cast<intptr_t>(str.CharAt(index))))); | 666 Smi::Handle( |
| 667 Z, Smi::New(static_cast<intptr_t>(str.CharAt(index))))); |
| 666 return; | 668 return; |
| 667 } | 669 } |
| 668 } else if (array_obj.IsArray()) { | 670 } else if (array_obj.IsArray()) { |
| 669 const Array& a = Array::Cast(array_obj); | 671 const Array& a = Array::Cast(array_obj); |
| 670 if ((a.Length() > index) && a.IsImmutable()) { | 672 if ((a.Length() > index) && a.IsImmutable()) { |
| 671 Instance& result = Instance::Handle(Z); | 673 Instance& result = Instance::Handle(Z); |
| 672 result ^= a.At(index); | 674 result ^= a.At(index); |
| 673 SetValue(instr, result); | 675 SetValue(instr, result); |
| 674 return; | 676 return; |
| 675 } | 677 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 } else { | 759 } else { |
| 758 SetValue(instr, non_constant_); | 760 SetValue(instr, non_constant_); |
| 759 } | 761 } |
| 760 } else if (IsConstant(value)) { | 762 } else if (IsConstant(value)) { |
| 761 if (value.IsInstance()) { | 763 if (value.IsInstance()) { |
| 762 const Instance& instance = Instance::Cast(value); | 764 const Instance& instance = Instance::Cast(value); |
| 763 const AbstractType& checked_type = instr->type(); | 765 const AbstractType& checked_type = instr->type(); |
| 764 if (instr->instantiator_type_arguments()->BindsToConstantNull()) { | 766 if (instr->instantiator_type_arguments()->BindsToConstantNull()) { |
| 765 const TypeArguments& checked_type_arguments = TypeArguments::Handle(); | 767 const TypeArguments& checked_type_arguments = TypeArguments::Handle(); |
| 766 Error& bound_error = Error::Handle(); | 768 Error& bound_error = Error::Handle(); |
| 767 bool is_instance = instance.IsInstanceOf(checked_type, | 769 bool is_instance = instance.IsInstanceOf( |
| 768 checked_type_arguments, | 770 checked_type, checked_type_arguments, &bound_error); |
| 769 &bound_error); | |
| 770 // Can only have bound error with generics. | 771 // Can only have bound error with generics. |
| 771 ASSERT(bound_error.IsNull()); | 772 ASSERT(bound_error.IsNull()); |
| 772 SetValue(instr, Bool::Get(instr->negate_result() | 773 SetValue(instr, Bool::Get(instr->negate_result() ? !is_instance |
| 773 ? !is_instance : is_instance)); | 774 : is_instance)); |
| 774 return; | 775 return; |
| 775 } | 776 } |
| 776 } | 777 } |
| 777 SetValue(instr, non_constant_); | 778 SetValue(instr, non_constant_); |
| 778 } | 779 } |
| 779 } | 780 } |
| 780 | 781 |
| 781 | 782 |
| 782 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { | 783 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) { |
| 783 SetValue(instr, non_constant_); | 784 SetValue(instr, non_constant_); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 810 } | 811 } |
| 811 } | 812 } |
| 812 SetValue(instr, non_constant_); | 813 SetValue(instr, non_constant_); |
| 813 } | 814 } |
| 814 | 815 |
| 815 | 816 |
| 816 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { | 817 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) { |
| 817 Value* instance = instr->instance(); | 818 Value* instance = instr->instance(); |
| 818 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && | 819 if ((instr->recognized_kind() == MethodRecognizer::kObjectArrayLength) && |
| 819 instance->definition()->OriginalDefinition()->IsCreateArray()) { | 820 instance->definition()->OriginalDefinition()->IsCreateArray()) { |
| 820 Value* num_elements = instance->definition()->OriginalDefinition() | 821 Value* num_elements = instance->definition() |
| 821 ->AsCreateArray()->num_elements(); | 822 ->OriginalDefinition() |
| 823 ->AsCreateArray() |
| 824 ->num_elements(); |
| 822 if (num_elements->BindsToConstant() && | 825 if (num_elements->BindsToConstant() && |
| 823 num_elements->BoundConstant().IsSmi()) { | 826 num_elements->BoundConstant().IsSmi()) { |
| 824 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); | 827 intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value(); |
| 825 const Object& result = Smi::ZoneHandle(Z, Smi::New(length)); | 828 const Object& result = Smi::ZoneHandle(Z, Smi::New(length)); |
| 826 SetValue(instr, result); | 829 SetValue(instr, result); |
| 827 return; | 830 return; |
| 828 } | 831 } |
| 829 } | 832 } |
| 830 | 833 |
| 831 if (instr->IsImmutableLengthLoad()) { | 834 if (instr->IsImmutableLengthLoad()) { |
| 832 ConstantInstr* constant = | 835 ConstantInstr* constant = |
| 833 instance->definition()->OriginalDefinition()->AsConstant(); | 836 instance->definition()->OriginalDefinition()->AsConstant(); |
| 834 if (constant != NULL) { | 837 if (constant != NULL) { |
| 835 if (constant->value().IsString()) { | 838 if (constant->value().IsString()) { |
| 836 SetValue(instr, Smi::ZoneHandle(Z, | 839 SetValue(instr, |
| 837 Smi::New(String::Cast(constant->value()).Length()))); | 840 Smi::ZoneHandle( |
| 841 Z, Smi::New(String::Cast(constant->value()).Length()))); |
| 838 return; | 842 return; |
| 839 } | 843 } |
| 840 if (constant->value().IsArray()) { | 844 if (constant->value().IsArray()) { |
| 841 SetValue(instr, Smi::ZoneHandle(Z, | 845 SetValue(instr, |
| 842 Smi::New(Array::Cast(constant->value()).Length()))); | 846 Smi::ZoneHandle( |
| 847 Z, Smi::New(Array::Cast(constant->value()).Length()))); |
| 843 return; | 848 return; |
| 844 } | 849 } |
| 845 if (constant->value().IsTypedData()) { | 850 if (constant->value().IsTypedData()) { |
| 846 SetValue(instr, Smi::ZoneHandle(Z, | 851 SetValue(instr, |
| 847 Smi::New(TypedData::Cast(constant->value()).Length()))); | 852 Smi::ZoneHandle( |
| 853 Z, Smi::New(TypedData::Cast(constant->value()).Length()))); |
| 848 return; | 854 return; |
| 849 } | 855 } |
| 850 } | 856 } |
| 851 } | 857 } |
| 852 SetValue(instr, non_constant_); | 858 SetValue(instr, non_constant_); |
| 853 } | 859 } |
| 854 | 860 |
| 855 | 861 |
| 856 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 862 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
| 857 const Object& object = | 863 const Object& object = instr->instantiator()->definition()->constant_value(); |
| 858 instr->instantiator()->definition()->constant_value(); | |
| 859 if (IsNonConstant(object)) { | 864 if (IsNonConstant(object)) { |
| 860 SetValue(instr, non_constant_); | 865 SetValue(instr, non_constant_); |
| 861 return; | 866 return; |
| 862 } | 867 } |
| 863 if (IsConstant(object)) { | 868 if (IsConstant(object)) { |
| 864 if (instr->type().IsTypeParameter()) { | 869 if (instr->type().IsTypeParameter()) { |
| 865 if (object.IsNull()) { | 870 if (object.IsNull()) { |
| 866 SetValue(instr, Object::dynamic_type()); | 871 SetValue(instr, Object::dynamic_type()); |
| 867 return; | 872 return; |
| 868 } | 873 } |
| 869 // We could try to instantiate the type parameter and return it if no | 874 // We could try to instantiate the type parameter and return it if no |
| 870 // malformed error is reported. | 875 // malformed error is reported. |
| 871 } | 876 } |
| 872 SetValue(instr, non_constant_); | 877 SetValue(instr, non_constant_); |
| 873 } | 878 } |
| 874 } | 879 } |
| 875 | 880 |
| 876 | 881 |
| 877 void ConstantPropagator::VisitInstantiateTypeArguments( | 882 void ConstantPropagator::VisitInstantiateTypeArguments( |
| 878 InstantiateTypeArgumentsInstr* instr) { | 883 InstantiateTypeArgumentsInstr* instr) { |
| 879 const Object& object = | 884 const Object& object = instr->instantiator()->definition()->constant_value(); |
| 880 instr->instantiator()->definition()->constant_value(); | |
| 881 if (IsNonConstant(object)) { | 885 if (IsNonConstant(object)) { |
| 882 SetValue(instr, non_constant_); | 886 SetValue(instr, non_constant_); |
| 883 return; | 887 return; |
| 884 } | 888 } |
| 885 if (IsConstant(object)) { | 889 if (IsConstant(object)) { |
| 886 const intptr_t len = instr->type_arguments().Length(); | 890 const intptr_t len = instr->type_arguments().Length(); |
| 887 if (instr->type_arguments().IsRawInstantiatedRaw(len) && | 891 if (instr->type_arguments().IsRawInstantiatedRaw(len) && object.IsNull()) { |
| 888 object.IsNull()) { | |
| 889 SetValue(instr, object); | 892 SetValue(instr, object); |
| 890 return; | 893 return; |
| 891 } | 894 } |
| 892 if (instr->type_arguments().IsUninstantiatedIdentity() || | 895 if (instr->type_arguments().IsUninstantiatedIdentity() || |
| 893 instr->type_arguments().CanShareInstantiatorTypeArguments( | 896 instr->type_arguments().CanShareInstantiatorTypeArguments( |
| 894 instr->instantiator_class())) { | 897 instr->instantiator_class())) { |
| 895 SetValue(instr, object); | 898 SetValue(instr, object); |
| 896 return; | 899 return; |
| 897 } | 900 } |
| 898 SetValue(instr, non_constant_); | 901 SetValue(instr, non_constant_); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { | 989 void ConstantPropagator::VisitUnboxInt64(UnboxInt64Instr* instr) { |
| 987 // TODO(kmillikin): Handle unbox operation. | 990 // TODO(kmillikin): Handle unbox operation. |
| 988 SetValue(instr, non_constant_); | 991 SetValue(instr, non_constant_); |
| 989 } | 992 } |
| 990 | 993 |
| 991 | 994 |
| 992 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { | 995 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) { |
| 993 const Object& value = unary_op->value()->definition()->constant_value(); | 996 const Object& value = unary_op->value()->definition()->constant_value(); |
| 994 if (IsConstant(value) && value.IsInteger()) { | 997 if (IsConstant(value) && value.IsInteger()) { |
| 995 const Integer& value_int = Integer::Cast(value); | 998 const Integer& value_int = Integer::Cast(value); |
| 996 const Integer& result = | 999 const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int)); |
| 997 Integer::Handle(Z, unary_op->Evaluate(value_int)); | |
| 998 if (!result.IsNull()) { | 1000 if (!result.IsNull()) { |
| 999 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); | 1001 SetValue(unary_op, Integer::ZoneHandle(Z, result.raw())); |
| 1000 return; | 1002 return; |
| 1001 } | 1003 } |
| 1002 } | 1004 } |
| 1003 | 1005 |
| 1004 SetValue(unary_op, non_constant_); | 1006 SetValue(unary_op, non_constant_); |
| 1005 } | 1007 } |
| 1006 | 1008 |
| 1007 | 1009 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1022 } else if (IsConstant(value)) { | 1024 } else if (IsConstant(value)) { |
| 1023 // TODO(kmillikin): Handle unary operations. | 1025 // TODO(kmillikin): Handle unary operations. |
| 1024 SetValue(instr, non_constant_); | 1026 SetValue(instr, non_constant_); |
| 1025 } | 1027 } |
| 1026 } | 1028 } |
| 1027 | 1029 |
| 1028 | 1030 |
| 1029 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { | 1031 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) { |
| 1030 const Object& value = instr->value()->definition()->constant_value(); | 1032 const Object& value = instr->value()->definition()->constant_value(); |
| 1031 if (IsConstant(value) && value.IsInteger()) { | 1033 if (IsConstant(value) && value.IsInteger()) { |
| 1032 SetValue(instr, Double::Handle(Z, | 1034 SetValue(instr, |
| 1033 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 1035 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1036 Heap::kOld))); |
| 1034 } else if (!IsUnknown(value)) { | 1037 } else if (!IsUnknown(value)) { |
| 1035 SetValue(instr, non_constant_); | 1038 SetValue(instr, non_constant_); |
| 1036 } | 1039 } |
| 1037 } | 1040 } |
| 1038 | 1041 |
| 1039 | 1042 |
| 1040 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { | 1043 void ConstantPropagator::VisitMintToDouble(MintToDoubleInstr* instr) { |
| 1041 const Object& value = instr->value()->definition()->constant_value(); | 1044 const Object& value = instr->value()->definition()->constant_value(); |
| 1042 if (IsConstant(value) && value.IsInteger()) { | 1045 if (IsConstant(value) && value.IsInteger()) { |
| 1043 SetValue(instr, Double::Handle(Z, | 1046 SetValue(instr, |
| 1044 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 1047 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1048 Heap::kOld))); |
| 1045 } else if (!IsUnknown(value)) { | 1049 } else if (!IsUnknown(value)) { |
| 1046 SetValue(instr, non_constant_); | 1050 SetValue(instr, non_constant_); |
| 1047 } | 1051 } |
| 1048 } | 1052 } |
| 1049 | 1053 |
| 1050 | 1054 |
| 1051 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { | 1055 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) { |
| 1052 const Object& value = instr->value()->definition()->constant_value(); | 1056 const Object& value = instr->value()->definition()->constant_value(); |
| 1053 if (IsConstant(value) && value.IsInteger()) { | 1057 if (IsConstant(value) && value.IsInteger()) { |
| 1054 SetValue(instr, Double::Handle(Z, | 1058 SetValue(instr, |
| 1055 Double::New(Integer::Cast(value).AsDoubleValue(), Heap::kOld))); | 1059 Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(), |
| 1060 Heap::kOld))); |
| 1056 } else if (!IsUnknown(value)) { | 1061 } else if (!IsUnknown(value)) { |
| 1057 SetValue(instr, non_constant_); | 1062 SetValue(instr, non_constant_); |
| 1058 } | 1063 } |
| 1059 } | 1064 } |
| 1060 | 1065 |
| 1061 | 1066 |
| 1062 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { | 1067 void ConstantPropagator::VisitDoubleToInteger(DoubleToIntegerInstr* instr) { |
| 1063 // TODO(kmillikin): Handle conversion. | 1068 // TODO(kmillikin): Handle conversion. |
| 1064 SetValue(instr, non_constant_); | 1069 SetValue(instr, non_constant_); |
| 1065 } | 1070 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 return value.IsInteger() || value.IsDouble(); | 1138 return value.IsInteger() || value.IsDouble(); |
| 1134 } | 1139 } |
| 1135 | 1140 |
| 1136 | 1141 |
| 1137 static double ToDouble(const Object& value) { | 1142 static double ToDouble(const Object& value) { |
| 1138 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() | 1143 return value.IsInteger() ? Integer::Cast(value).AsDoubleValue() |
| 1139 : Double::Cast(value).value(); | 1144 : Double::Cast(value).value(); |
| 1140 } | 1145 } |
| 1141 | 1146 |
| 1142 | 1147 |
| 1143 void ConstantPropagator::VisitBinaryDoubleOp( | 1148 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) { |
| 1144 BinaryDoubleOpInstr* instr) { | |
| 1145 const Object& left = instr->left()->definition()->constant_value(); | 1149 const Object& left = instr->left()->definition()->constant_value(); |
| 1146 const Object& right = instr->right()->definition()->constant_value(); | 1150 const Object& right = instr->right()->definition()->constant_value(); |
| 1147 if (IsNonConstant(left) || IsNonConstant(right)) { | 1151 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 1148 SetValue(instr, non_constant_); | 1152 SetValue(instr, non_constant_); |
| 1149 } else if (left.IsInteger() && right.IsInteger()) { | 1153 } else if (left.IsInteger() && right.IsInteger()) { |
| 1150 SetValue(instr, non_constant_); | 1154 SetValue(instr, non_constant_); |
| 1151 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { | 1155 } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) { |
| 1152 const double left_val = ToDouble(left); | 1156 const double left_val = ToDouble(left); |
| 1153 const double right_val = ToDouble(right); | 1157 const double right_val = ToDouble(right); |
| 1154 double result_val = 0.0; | 1158 double result_val = 0.0; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 } | 1197 } |
| 1194 default: | 1198 default: |
| 1195 UNREACHABLE(); | 1199 UNREACHABLE(); |
| 1196 } | 1200 } |
| 1197 } else { | 1201 } else { |
| 1198 SetValue(instr, non_constant_); | 1202 SetValue(instr, non_constant_); |
| 1199 } | 1203 } |
| 1200 } | 1204 } |
| 1201 | 1205 |
| 1202 | 1206 |
| 1203 void ConstantPropagator::VisitBinaryFloat32x4Op( | 1207 void ConstantPropagator::VisitBinaryFloat32x4Op(BinaryFloat32x4OpInstr* instr) { |
| 1204 BinaryFloat32x4OpInstr* instr) { | |
| 1205 const Object& left = instr->left()->definition()->constant_value(); | 1208 const Object& left = instr->left()->definition()->constant_value(); |
| 1206 const Object& right = instr->right()->definition()->constant_value(); | 1209 const Object& right = instr->right()->definition()->constant_value(); |
| 1207 if (IsNonConstant(left) || IsNonConstant(right)) { | 1210 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 1208 SetValue(instr, non_constant_); | 1211 SetValue(instr, non_constant_); |
| 1209 } else if (IsConstant(left) && IsConstant(right)) { | 1212 } else if (IsConstant(left) && IsConstant(right)) { |
| 1210 // TODO(kmillikin): Handle binary operation. | 1213 // TODO(kmillikin): Handle binary operation. |
| 1211 SetValue(instr, non_constant_); | 1214 SetValue(instr, non_constant_); |
| 1212 } | 1215 } |
| 1213 } | 1216 } |
| 1214 | 1217 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 SetValue(instr, non_constant_); | 1344 SetValue(instr, non_constant_); |
| 1342 } | 1345 } |
| 1343 | 1346 |
| 1344 | 1347 |
| 1345 void ConstantPropagator::VisitFloat64x2ToFloat32x4( | 1348 void ConstantPropagator::VisitFloat64x2ToFloat32x4( |
| 1346 Float64x2ToFloat32x4Instr* instr) { | 1349 Float64x2ToFloat32x4Instr* instr) { |
| 1347 SetValue(instr, non_constant_); | 1350 SetValue(instr, non_constant_); |
| 1348 } | 1351 } |
| 1349 | 1352 |
| 1350 | 1353 |
| 1351 void ConstantPropagator::VisitFloat64x2Zero( | 1354 void ConstantPropagator::VisitFloat64x2Zero(Float64x2ZeroInstr* instr) { |
| 1352 Float64x2ZeroInstr* instr) { | |
| 1353 SetValue(instr, non_constant_); | 1355 SetValue(instr, non_constant_); |
| 1354 } | 1356 } |
| 1355 | 1357 |
| 1356 | 1358 |
| 1357 void ConstantPropagator::VisitFloat64x2Splat( | 1359 void ConstantPropagator::VisitFloat64x2Splat(Float64x2SplatInstr* instr) { |
| 1358 Float64x2SplatInstr* instr) { | |
| 1359 SetValue(instr, non_constant_); | 1360 SetValue(instr, non_constant_); |
| 1360 } | 1361 } |
| 1361 | 1362 |
| 1362 | 1363 |
| 1363 void ConstantPropagator::VisitFloat64x2Constructor( | 1364 void ConstantPropagator::VisitFloat64x2Constructor( |
| 1364 Float64x2ConstructorInstr* instr) { | 1365 Float64x2ConstructorInstr* instr) { |
| 1365 SetValue(instr, non_constant_); | 1366 SetValue(instr, non_constant_); |
| 1366 } | 1367 } |
| 1367 | 1368 |
| 1368 | 1369 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1395 if (IsNonConstant(left) || IsNonConstant(right)) { | 1396 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 1396 SetValue(instr, non_constant_); | 1397 SetValue(instr, non_constant_); |
| 1397 } else if (IsConstant(left) && IsConstant(right)) { | 1398 } else if (IsConstant(left) && IsConstant(right)) { |
| 1398 // TODO(srdjan): Handle min and max. | 1399 // TODO(srdjan): Handle min and max. |
| 1399 SetValue(instr, non_constant_); | 1400 SetValue(instr, non_constant_); |
| 1400 } | 1401 } |
| 1401 } | 1402 } |
| 1402 | 1403 |
| 1403 | 1404 |
| 1404 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | 1405 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
| 1405 CaseInsensitiveCompareUC16Instr *instr) { | 1406 CaseInsensitiveCompareUC16Instr* instr) { |
| 1406 SetValue(instr, non_constant_); | 1407 SetValue(instr, non_constant_); |
| 1407 } | 1408 } |
| 1408 | 1409 |
| 1409 | 1410 |
| 1410 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { | 1411 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) { |
| 1411 const Object& value = instr->value()->definition()->constant_value(); | 1412 const Object& value = instr->value()->definition()->constant_value(); |
| 1412 if (IsNonConstant(value)) { | 1413 if (IsNonConstant(value)) { |
| 1413 SetValue(instr, non_constant_); | 1414 SetValue(instr, non_constant_); |
| 1414 } else if (IsConstant(value)) { | 1415 } else if (IsConstant(value)) { |
| 1415 // TODO(kmillikin): Handle conversion. | 1416 // TODO(kmillikin): Handle conversion. |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 } else { | 1483 } else { |
| 1483 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 1484 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
| 1484 block->Accept(this); | 1485 block->Accept(this); |
| 1485 } | 1486 } |
| 1486 } | 1487 } |
| 1487 } | 1488 } |
| 1488 | 1489 |
| 1489 | 1490 |
| 1490 static bool IsEmptyBlock(BlockEntryInstr* block) { | 1491 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 1491 return block->next()->IsGoto() && | 1492 return block->next()->IsGoto() && |
| 1492 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && | 1493 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
| 1493 !block->IsIndirectEntry(); | 1494 !block->IsIndirectEntry(); |
| 1494 } | 1495 } |
| 1495 | 1496 |
| 1496 | 1497 |
| 1497 // Traverses a chain of empty blocks and returns the first reachable non-empty | 1498 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 1498 // block that is not dominated by the start block. The empty blocks are added | 1499 // block that is not dominated by the start block. The empty blocks are added |
| 1499 // to the supplied bit vector. | 1500 // to the supplied bit vector. |
| 1500 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 1501 static BlockEntryInstr* FindFirstNonEmptySuccessor(TargetEntryInstr* block, |
| 1501 TargetEntryInstr* block, | 1502 BitVector* empty_blocks) { |
| 1502 BitVector* empty_blocks) { | |
| 1503 BlockEntryInstr* current = block; | 1503 BlockEntryInstr* current = block; |
| 1504 while (IsEmptyBlock(current) && block->Dominates(current)) { | 1504 while (IsEmptyBlock(current) && block->Dominates(current)) { |
| 1505 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 1505 ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); |
| 1506 empty_blocks->Add(current->preorder_number()); | 1506 empty_blocks->Add(current->preorder_number()); |
| 1507 current = current->next()->AsGoto()->successor(); | 1507 current = current->next()->AsGoto()->successor(); |
| 1508 } | 1508 } |
| 1509 return current; | 1509 return current; |
| 1510 } | 1510 } |
| 1511 | 1511 |
| 1512 | 1512 |
| 1513 void ConstantPropagator::EliminateRedundantBranches() { | 1513 void ConstantPropagator::EliminateRedundantBranches() { |
| 1514 // Canonicalize branches that have no side-effects and where true- and | 1514 // Canonicalize branches that have no side-effects and where true- and |
| 1515 // false-targets are the same. | 1515 // false-targets are the same. |
| 1516 bool changed = false; | 1516 bool changed = false; |
| 1517 BitVector* empty_blocks = new(Z) BitVector(Z, | 1517 BitVector* empty_blocks = new (Z) BitVector(Z, graph_->preorder().length()); |
| 1518 graph_->preorder().length()); | 1518 for (BlockIterator b = graph_->postorder_iterator(); !b.Done(); b.Advance()) { |
| 1519 for (BlockIterator b = graph_->postorder_iterator(); | |
| 1520 !b.Done(); | |
| 1521 b.Advance()) { | |
| 1522 BlockEntryInstr* block = b.Current(); | 1519 BlockEntryInstr* block = b.Current(); |
| 1523 BranchInstr* branch = block->last_instruction()->AsBranch(); | 1520 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 1524 empty_blocks->Clear(); | 1521 empty_blocks->Clear(); |
| 1525 if ((branch != NULL) && branch->Effects().IsNone()) { | 1522 if ((branch != NULL) && branch->Effects().IsNone()) { |
| 1526 ASSERT(branch->previous() != NULL); // Not already eliminated. | 1523 ASSERT(branch->previous() != NULL); // Not already eliminated. |
| 1527 BlockEntryInstr* if_true = | 1524 BlockEntryInstr* if_true = |
| 1528 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); | 1525 FindFirstNonEmptySuccessor(branch->true_successor(), empty_blocks); |
| 1529 BlockEntryInstr* if_false = | 1526 BlockEntryInstr* if_false = |
| 1530 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); | 1527 FindFirstNonEmptySuccessor(branch->false_successor(), empty_blocks); |
| 1531 if (if_true == if_false) { | 1528 if (if_true == if_false) { |
| 1532 // Replace the branch with a jump to the common successor. | 1529 // Replace the branch with a jump to the common successor. |
| 1533 // Drop the comparison, which does not have side effects | 1530 // Drop the comparison, which does not have side effects |
| 1534 JoinEntryInstr* join = if_true->AsJoinEntry(); | 1531 JoinEntryInstr* join = if_true->AsJoinEntry(); |
| 1535 if (join->phis() == NULL) { | 1532 if (join->phis() == NULL) { |
| 1536 GotoInstr* jump = new(Z) GotoInstr(if_true->AsJoinEntry()); | 1533 GotoInstr* jump = new (Z) GotoInstr(if_true->AsJoinEntry()); |
| 1537 jump->InheritDeoptTarget(Z, branch); | 1534 jump->InheritDeoptTarget(Z, branch); |
| 1538 | 1535 |
| 1539 Instruction* previous = branch->previous(); | 1536 Instruction* previous = branch->previous(); |
| 1540 branch->set_previous(NULL); | 1537 branch->set_previous(NULL); |
| 1541 previous->LinkTo(jump); | 1538 previous->LinkTo(jump); |
| 1542 | 1539 |
| 1543 // Remove uses from branch and all the empty blocks that | 1540 // Remove uses from branch and all the empty blocks that |
| 1544 // are now unreachable. | 1541 // are now unreachable. |
| 1545 branch->UnuseAllInputs(); | 1542 branch->UnuseAllInputs(); |
| 1546 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { | 1543 for (BitVector::Iterator it(empty_blocks); !it.Done(); it.Advance()) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1572 void ConstantPropagator::Transform() { | 1569 void ConstantPropagator::Transform() { |
| 1573 if (FLAG_trace_constant_propagation && | 1570 if (FLAG_trace_constant_propagation && |
| 1574 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1571 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
| 1575 FlowGraphPrinter::PrintGraph("Before CP", graph_); | 1572 FlowGraphPrinter::PrintGraph("Before CP", graph_); |
| 1576 } | 1573 } |
| 1577 | 1574 |
| 1578 // We will recompute dominators, block ordering, block ids, block last | 1575 // We will recompute dominators, block ordering, block ids, block last |
| 1579 // instructions, previous pointers, predecessors, etc. after eliminating | 1576 // instructions, previous pointers, predecessors, etc. after eliminating |
| 1580 // unreachable code. We do not maintain those properties during the | 1577 // unreachable code. We do not maintain those properties during the |
| 1581 // transformation. | 1578 // transformation. |
| 1582 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 1579 for (BlockIterator b = graph_->reverse_postorder_iterator(); !b.Done(); |
| 1583 !b.Done(); | |
| 1584 b.Advance()) { | 1580 b.Advance()) { |
| 1585 BlockEntryInstr* block = b.Current(); | 1581 BlockEntryInstr* block = b.Current(); |
| 1586 if (!reachable_->Contains(block->preorder_number())) { | 1582 if (!reachable_->Contains(block->preorder_number())) { |
| 1587 if (FLAG_trace_constant_propagation && | 1583 if (FLAG_trace_constant_propagation && |
| 1588 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1584 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
| 1589 THR_Print("Unreachable B%" Pd "\n", block->block_id()); | 1585 THR_Print("Unreachable B%" Pd "\n", block->block_id()); |
| 1590 } | 1586 } |
| 1591 // Remove all uses in unreachable blocks. | 1587 // Remove all uses in unreachable blocks. |
| 1592 block->ClearAllInstructions(); | 1588 block->ClearAllInstructions(); |
| 1593 continue; | 1589 continue; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1642 } | 1638 } |
| 1643 } | 1639 } |
| 1644 } | 1640 } |
| 1645 } | 1641 } |
| 1646 | 1642 |
| 1647 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { | 1643 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { |
| 1648 Definition* defn = i.Current()->AsDefinition(); | 1644 Definition* defn = i.Current()->AsDefinition(); |
| 1649 // Replace constant-valued instructions without observable side | 1645 // Replace constant-valued instructions without observable side |
| 1650 // effects. Do this for smis only to avoid having to copy other | 1646 // effects. Do this for smis only to avoid having to copy other |
| 1651 // objects into the heap's old generation. | 1647 // objects into the heap's old generation. |
| 1652 if ((defn != NULL) && | 1648 if ((defn != NULL) && IsConstant(defn->constant_value()) && |
| 1653 IsConstant(defn->constant_value()) && | |
| 1654 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && | 1649 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && |
| 1655 !defn->IsConstant() && | 1650 !defn->IsConstant() && !defn->IsPushArgument() && |
| 1656 !defn->IsPushArgument() && | 1651 !defn->IsStoreIndexed() && !defn->IsStoreInstanceField() && |
| 1657 !defn->IsStoreIndexed() && | |
| 1658 !defn->IsStoreInstanceField() && | |
| 1659 !defn->IsStoreStaticField()) { | 1652 !defn->IsStoreStaticField()) { |
| 1660 if (FLAG_trace_constant_propagation && | 1653 if (FLAG_trace_constant_propagation && |
| 1661 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1654 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
| 1662 THR_Print("Constant v%" Pd " = %s\n", | 1655 THR_Print("Constant v%" Pd " = %s\n", defn->ssa_temp_index(), |
| 1663 defn->ssa_temp_index(), | |
| 1664 defn->constant_value().ToCString()); | 1656 defn->constant_value().ToCString()); |
| 1665 } | 1657 } |
| 1666 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); | 1658 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); |
| 1667 defn->ReplaceUsesWith(constant); | 1659 defn->ReplaceUsesWith(constant); |
| 1668 i.RemoveCurrentFromGraph(); | 1660 i.RemoveCurrentFromGraph(); |
| 1669 } | 1661 } |
| 1670 } | 1662 } |
| 1671 | 1663 |
| 1672 // Replace branches where one target is unreachable with jumps. | 1664 // Replace branches where one target is unreachable with jumps. |
| 1673 BranchInstr* branch = block->last_instruction()->AsBranch(); | 1665 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 1674 if (branch != NULL) { | 1666 if (branch != NULL) { |
| 1675 TargetEntryInstr* if_true = branch->true_successor(); | 1667 TargetEntryInstr* if_true = branch->true_successor(); |
| 1676 TargetEntryInstr* if_false = branch->false_successor(); | 1668 TargetEntryInstr* if_false = branch->false_successor(); |
| 1677 JoinEntryInstr* join = NULL; | 1669 JoinEntryInstr* join = NULL; |
| 1678 Instruction* next = NULL; | 1670 Instruction* next = NULL; |
| 1679 | 1671 |
| 1680 if (!reachable_->Contains(if_true->preorder_number())) { | 1672 if (!reachable_->Contains(if_true->preorder_number())) { |
| 1681 ASSERT(reachable_->Contains(if_false->preorder_number())); | 1673 ASSERT(reachable_->Contains(if_false->preorder_number())); |
| 1682 ASSERT(if_false->parallel_move() == NULL); | 1674 ASSERT(if_false->parallel_move() == NULL); |
| 1683 ASSERT(if_false->loop_info() == NULL); | 1675 ASSERT(if_false->loop_info() == NULL); |
| 1684 join = new(Z) JoinEntryInstr(if_false->block_id(), | 1676 join = |
| 1685 if_false->try_index()); | 1677 new (Z) JoinEntryInstr(if_false->block_id(), if_false->try_index()); |
| 1686 join->InheritDeoptTarget(Z, if_false); | 1678 join->InheritDeoptTarget(Z, if_false); |
| 1687 if_false->UnuseAllInputs(); | 1679 if_false->UnuseAllInputs(); |
| 1688 next = if_false->next(); | 1680 next = if_false->next(); |
| 1689 } else if (!reachable_->Contains(if_false->preorder_number())) { | 1681 } else if (!reachable_->Contains(if_false->preorder_number())) { |
| 1690 ASSERT(if_true->parallel_move() == NULL); | 1682 ASSERT(if_true->parallel_move() == NULL); |
| 1691 ASSERT(if_true->loop_info() == NULL); | 1683 ASSERT(if_true->loop_info() == NULL); |
| 1692 join = new(Z) JoinEntryInstr(if_true->block_id(), | 1684 join = |
| 1693 if_true->try_index()); | 1685 new (Z) JoinEntryInstr(if_true->block_id(), if_true->try_index()); |
| 1694 join->InheritDeoptTarget(Z, if_true); | 1686 join->InheritDeoptTarget(Z, if_true); |
| 1695 if_true->UnuseAllInputs(); | 1687 if_true->UnuseAllInputs(); |
| 1696 next = if_true->next(); | 1688 next = if_true->next(); |
| 1697 } | 1689 } |
| 1698 | 1690 |
| 1699 if (join != NULL) { | 1691 if (join != NULL) { |
| 1700 // Replace the branch with a jump to the reachable successor. | 1692 // Replace the branch with a jump to the reachable successor. |
| 1701 // Drop the comparison, which does not have side effects as long | 1693 // Drop the comparison, which does not have side effects as long |
| 1702 // as it is a strict compare (the only one we can determine is | 1694 // as it is a strict compare (the only one we can determine is |
| 1703 // constant with the current analysis). | 1695 // constant with the current analysis). |
| 1704 GotoInstr* jump = new(Z) GotoInstr(join); | 1696 GotoInstr* jump = new (Z) GotoInstr(join); |
| 1705 jump->InheritDeoptTarget(Z, branch); | 1697 jump->InheritDeoptTarget(Z, branch); |
| 1706 | 1698 |
| 1707 Instruction* previous = branch->previous(); | 1699 Instruction* previous = branch->previous(); |
| 1708 branch->set_previous(NULL); | 1700 branch->set_previous(NULL); |
| 1709 previous->LinkTo(jump); | 1701 previous->LinkTo(jump); |
| 1710 | 1702 |
| 1711 // Replace the false target entry with the new join entry. We will | 1703 // Replace the false target entry with the new join entry. We will |
| 1712 // recompute the dominators after this pass. | 1704 // recompute the dominators after this pass. |
| 1713 join->LinkTo(next); | 1705 join->LinkTo(next); |
| 1714 branch->UnuseAllInputs(); | 1706 branch->UnuseAllInputs(); |
| 1715 } | 1707 } |
| 1716 } | 1708 } |
| 1717 } | 1709 } |
| 1718 | 1710 |
| 1719 graph_->DiscoverBlocks(); | 1711 graph_->DiscoverBlocks(); |
| 1720 graph_->MergeBlocks(); | 1712 graph_->MergeBlocks(); |
| 1721 GrowableArray<BitVector*> dominance_frontier; | 1713 GrowableArray<BitVector*> dominance_frontier; |
| 1722 graph_->ComputeDominators(&dominance_frontier); | 1714 graph_->ComputeDominators(&dominance_frontier); |
| 1723 | 1715 |
| 1724 if (FLAG_trace_constant_propagation && | 1716 if (FLAG_trace_constant_propagation && |
| 1725 FlowGraphPrinter::ShouldPrint(graph_->function())) { | 1717 FlowGraphPrinter::ShouldPrint(graph_->function())) { |
| 1726 FlowGraphPrinter::PrintGraph("After CP", graph_); | 1718 FlowGraphPrinter::PrintGraph("After CP", graph_); |
| 1727 } | 1719 } |
| 1728 } | 1720 } |
| 1729 | 1721 |
| 1730 } // namespace dart | 1722 } // namespace dart |
| OLD | NEW |