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 |