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