| 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 |