| 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/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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), | 296 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), |
| 297 new Value(index_instr), | 297 new Value(index_instr), |
| 298 index_scale, | 298 index_scale, |
| 299 cid, | 299 cid, |
| 300 Isolate::kNoDeoptId); | 300 Isolate::kNoDeoptId); |
| 301 instr->ReplaceUsesWith(load); | 301 instr->ReplaceUsesWith(load); |
| 302 flow_graph()->InsertAfter(instr, load, NULL, Definition::kValue); | 302 flow_graph()->InsertAfter(instr, load, NULL, Definition::kValue); |
| 303 } | 303 } |
| 304 | 304 |
| 305 | 305 |
| 306 void FlowGraphOptimizer::AppendExtractNthOutputForMerged(Definition* instr, |
| 307 intptr_t index, |
| 308 Representation rep, |
| 309 intptr_t cid) { |
| 310 ExtractNthOutputInstr* extract = new ExtractNthOutputInstr(new Value(instr), |
| 311 index, |
| 312 rep, |
| 313 cid); |
| 314 instr->ReplaceUsesWith(extract); |
| 315 flow_graph()->InsertAfter(instr, extract, NULL, Definition::kValue); |
| 316 } |
| 317 |
| 318 |
| 306 // Dart: | 319 // Dart: |
| 307 // var x = d % 10; | 320 // var x = d % 10; |
| 308 // var y = d ~/ 10; | 321 // var y = d ~/ 10; |
| 309 // var z = x + y; | 322 // var z = x + y; |
| 310 // | 323 // |
| 311 // IL: | 324 // IL: |
| 312 // v4 <- %(v2, v3) | 325 // v4 <- %(v2, v3) |
| 313 // v5 <- ~/(v2, v3) | 326 // v5 <- ~/(v2, v3) |
| 314 // v6 <- +(v4, v5) | 327 // v6 <- +(v4, v5) |
| 315 // | 328 // |
| (...skipping 24 matching lines...) Expand all Loading... |
| 340 Definition* left_def = curr_instr->left()->definition(); | 353 Definition* left_def = curr_instr->left()->definition(); |
| 341 Definition* right_def = curr_instr->right()->definition(); | 354 Definition* right_def = curr_instr->right()->definition(); |
| 342 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { | 355 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { |
| 343 BinarySmiOpInstr* other_binop = (*merge_candidates)[k]; | 356 BinarySmiOpInstr* other_binop = (*merge_candidates)[k]; |
| 344 // 'other_binop' can be NULL if it was already merged. | 357 // 'other_binop' can be NULL if it was already merged. |
| 345 if ((other_binop != NULL) && | 358 if ((other_binop != NULL) && |
| 346 (other_binop->op_kind() == other_kind) && | 359 (other_binop->op_kind() == other_kind) && |
| 347 (other_binop->left()->definition() == left_def) && | 360 (other_binop->left()->definition() == left_def) && |
| 348 (other_binop->right()->definition() == right_def)) { | 361 (other_binop->right()->definition() == right_def)) { |
| 349 (*merge_candidates)[k] = NULL; // Clear it. | 362 (*merge_candidates)[k] = NULL; // Clear it. |
| 350 // Append a LoadIndexed behind TRUNC_DIV and MOD. | |
| 351 ASSERT(curr_instr->HasUses()); | 363 ASSERT(curr_instr->HasUses()); |
| 352 AppendLoadIndexedForMerged( | 364 AppendExtractNthOutputForMerged( |
| 353 curr_instr, | 365 curr_instr, |
| 354 MergedMathInstr::ResultIndexOf(curr_instr->op_kind()), | 366 MergedMathInstr::OutputIndexOf(curr_instr->op_kind()), |
| 355 kArrayCid); | 367 kTagged, kSmiCid); |
| 356 ASSERT(other_binop->HasUses()); | 368 ASSERT(other_binop->HasUses()); |
| 357 AppendLoadIndexedForMerged( | 369 AppendExtractNthOutputForMerged( |
| 358 other_binop, | 370 other_binop, |
| 359 MergedMathInstr::ResultIndexOf(other_binop->op_kind()), | 371 MergedMathInstr::OutputIndexOf(other_binop->op_kind()), |
| 360 kArrayCid); | 372 kTagged, kSmiCid); |
| 361 | 373 |
| 362 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(2); | 374 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(2); |
| 363 args->Add(new Value(curr_instr->left()->definition())); | 375 args->Add(new Value(curr_instr->left()->definition())); |
| 364 args->Add(new Value(curr_instr->right()->definition())); | 376 args->Add(new Value(curr_instr->right()->definition())); |
| 365 | 377 |
| 366 // Replace with TruncDivMod. | 378 // Replace with TruncDivMod. |
| 367 MergedMathInstr* div_mod = new MergedMathInstr( | 379 MergedMathInstr* div_mod = new MergedMathInstr( |
| 368 args, | 380 args, |
| 369 curr_instr->deopt_id(), | 381 curr_instr->deopt_id(), |
| 370 MergedMathInstr::kTruncDivMod); | 382 MergedMathInstr::kTruncDivMod); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 389 if (merge_candidates->length() < 2) { | 401 if (merge_candidates->length() < 2) { |
| 390 // Need at least a SIN and a COS. | 402 // Need at least a SIN and a COS. |
| 391 return; | 403 return; |
| 392 } | 404 } |
| 393 for (intptr_t i = 0; i < merge_candidates->length(); i++) { | 405 for (intptr_t i = 0; i < merge_candidates->length(); i++) { |
| 394 MathUnaryInstr* curr_instr = (*merge_candidates)[i]; | 406 MathUnaryInstr* curr_instr = (*merge_candidates)[i]; |
| 395 if (curr_instr == NULL) { | 407 if (curr_instr == NULL) { |
| 396 // Instruction was merged already. | 408 // Instruction was merged already. |
| 397 continue; | 409 continue; |
| 398 } | 410 } |
| 399 ASSERT((curr_instr->kind() == MethodRecognizer::kMathSin) || | 411 const intptr_t kind = curr_instr->kind(); |
| 400 (curr_instr->kind() == MethodRecognizer::kMathCos)); | 412 ASSERT((kind == MethodRecognizer::kMathSin) || |
| 413 (kind == MethodRecognizer::kMathCos)); |
| 401 // Check if there is sin/cos binop with same inputs. | 414 // Check if there is sin/cos binop with same inputs. |
| 402 const intptr_t other_kind = | 415 const intptr_t other_kind = (kind == MethodRecognizer::kMathSin) ? |
| 403 (curr_instr->kind() == MethodRecognizer::kMathSin) ? | 416 MethodRecognizer::kMathCos : MethodRecognizer::kMathSin; |
| 404 MethodRecognizer::kMathCos : MethodRecognizer::kMathSin; | |
| 405 Definition* def = curr_instr->value()->definition(); | 417 Definition* def = curr_instr->value()->definition(); |
| 406 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { | 418 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { |
| 407 MathUnaryInstr* other_op = (*merge_candidates)[k]; | 419 MathUnaryInstr* other_op = (*merge_candidates)[k]; |
| 408 // 'other_op' can be NULL if it was already merged. | 420 // 'other_op' can be NULL if it was already merged. |
| 409 if ((other_op != NULL) && (other_op->kind() == other_kind) && | 421 if ((other_op != NULL) && (other_op->kind() == other_kind) && |
| 410 (other_op->value()->definition() == def)) { | 422 (other_op->value()->definition() == def)) { |
| 411 (*merge_candidates)[k] = NULL; // Clear it. | 423 (*merge_candidates)[k] = NULL; // Clear it. |
| 412 // Append a LoadIndexed behind SIN and COS. | |
| 413 ASSERT(curr_instr->HasUses()); | 424 ASSERT(curr_instr->HasUses()); |
| 414 AppendLoadIndexedForMerged( | 425 AppendExtractNthOutputForMerged(curr_instr, |
| 415 curr_instr, | 426 MergedMathInstr::OutputIndexOf(kind), |
| 416 MergedMathInstr::ResultIndexOf(curr_instr->kind()), | 427 kUnboxedDouble, kDoubleCid); |
| 417 kTypedDataFloat64ArrayCid); | |
| 418 ASSERT(other_op->HasUses()); | 428 ASSERT(other_op->HasUses()); |
| 419 AppendLoadIndexedForMerged( | 429 AppendExtractNthOutputForMerged( |
| 420 other_op, | 430 other_op, |
| 421 MergedMathInstr::ResultIndexOf(other_op->kind()), | 431 MergedMathInstr::OutputIndexOf(other_kind), |
| 422 kTypedDataFloat64ArrayCid); | 432 kUnboxedDouble, kDoubleCid); |
| 423 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(1); | 433 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(1); |
| 424 args->Add(new Value(curr_instr->value()->definition())); | 434 args->Add(new Value(curr_instr->value()->definition())); |
| 425 | |
| 426 // Replace with SinCos. | 435 // Replace with SinCos. |
| 427 MergedMathInstr* sin_cos = new MergedMathInstr( | 436 MergedMathInstr* sin_cos = |
| 428 args, | 437 new MergedMathInstr(args, curr_instr->DeoptimizationTarget(), |
| 429 curr_instr->DeoptimizationTarget(), | 438 MergedMathInstr::kSinCos); |
| 430 MergedMathInstr::kSinCos); | |
| 431 curr_instr->ReplaceWith(sin_cos, current_iterator()); | 439 curr_instr->ReplaceWith(sin_cos, current_iterator()); |
| 432 other_op->ReplaceUsesWith(sin_cos); | 440 other_op->ReplaceUsesWith(sin_cos); |
| 433 other_op->RemoveFromGraph(); | 441 other_op->RemoveFromGraph(); |
| 434 // Only one merge possible. Because canonicalization happens later, | 442 // Only one merge possible. Because canonicalization happens later, |
| 435 // more candidates are possible. | 443 // more candidates are possible. |
| 436 // TODO(srdjan): Allow merging of sin/cos into sincos. | 444 // TODO(srdjan): Allow merging of sin/cos into sincos. |
| 437 break; | 445 break; |
| 438 } | 446 } |
| 439 } | 447 } |
| 440 } | 448 } |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 if (unboxed != current) { | 756 if (unboxed != current) { |
| 749 phi->set_representation(unboxed); | 757 phi->set_representation(unboxed); |
| 750 return true; | 758 return true; |
| 751 } | 759 } |
| 752 | 760 |
| 753 return false; | 761 return false; |
| 754 } | 762 } |
| 755 | 763 |
| 756 | 764 |
| 757 void FlowGraphOptimizer::SelectRepresentations() { | 765 void FlowGraphOptimizer::SelectRepresentations() { |
| 758 // Convervatively unbox all phis that were proven to be of Double, | 766 // Conservatively unbox all phis that were proven to be of Double, |
| 759 // Float32x4, or Int32x4 type. | 767 // Float32x4, or Int32x4 type. |
| 760 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 768 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 761 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); | 769 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
| 762 if (join_entry != NULL) { | 770 if (join_entry != NULL) { |
| 763 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { | 771 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
| 764 PhiInstr* phi = it.Current(); | 772 PhiInstr* phi = it.Current(); |
| 765 UnboxPhi(phi); | 773 UnboxPhi(phi); |
| 766 } | 774 } |
| 767 } | 775 } |
| 768 } | 776 } |
| (...skipping 7137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7906 SetValue(instr, non_constant_); | 7914 SetValue(instr, non_constant_); |
| 7907 } | 7915 } |
| 7908 | 7916 |
| 7909 | 7917 |
| 7910 void ConstantPropagator::VisitMergedMath(MergedMathInstr* instr) { | 7918 void ConstantPropagator::VisitMergedMath(MergedMathInstr* instr) { |
| 7911 // TODO(srdjan): Handle merged instruction. | 7919 // TODO(srdjan): Handle merged instruction. |
| 7912 SetValue(instr, non_constant_); | 7920 SetValue(instr, non_constant_); |
| 7913 } | 7921 } |
| 7914 | 7922 |
| 7915 | 7923 |
| 7924 void ConstantPropagator::VisitExtractNthOutput(ExtractNthOutputInstr* instr) { |
| 7925 SetValue(instr, non_constant_); |
| 7926 } |
| 7927 |
| 7928 |
| 7916 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { | 7929 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { |
| 7917 SetValue(instr, instr->value()); | 7930 SetValue(instr, instr->value()); |
| 7918 } | 7931 } |
| 7919 | 7932 |
| 7920 | 7933 |
| 7921 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { | 7934 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { |
| 7922 // Should not be used outside of range analysis. | 7935 // Should not be used outside of range analysis. |
| 7923 UNREACHABLE(); | 7936 UNREACHABLE(); |
| 7924 } | 7937 } |
| 7925 | 7938 |
| (...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9040 } | 9053 } |
| 9041 | 9054 |
| 9042 // Insert materializations at environment uses. | 9055 // Insert materializations at environment uses. |
| 9043 for (intptr_t i = 0; i < exits.length(); i++) { | 9056 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9044 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9057 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9045 } | 9058 } |
| 9046 } | 9059 } |
| 9047 | 9060 |
| 9048 | 9061 |
| 9049 } // namespace dart | 9062 } // namespace dart |
| OLD | NEW |