Chromium Code Reviews| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( | 244 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr( |
| 245 Token::kBIT_AND, | 245 Token::kBIT_AND, |
| 246 new Value(left_instr), | 246 new Value(left_instr), |
| 247 new Value(right_instr), | 247 new Value(right_instr), |
| 248 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize. | 248 Isolate::kNoDeoptId); // BIT_AND cannot deoptimize. |
| 249 bit_and_instr->ReplaceWith(smi_op, current_iterator()); | 249 bit_and_instr->ReplaceWith(smi_op, current_iterator()); |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 | 252 |
| 253 | 253 |
| 254 // Used bye TryMergeDivMod. | |
| 255 // Inserts a load-indexed instruction between a TRUNC_DIV or MOD instruction, | |
| 256 // and the usin instruction. This is an intermediate step before merging | |
|
regis
2013/11/14 01:33:20
usin -> using ?
merging period
srdjan
2013/11/20 21:41:47
Done.
| |
| 257 static void DivModAppendLoadIndexed(BinarySmiOpInstr* instr, | |
| 258 FlowGraph* flow_graph) { | |
| 259 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); | |
| 260 const intptr_t ix = (instr->op_kind() == Token::kTRUNCDIV) ? 0 : 1; | |
| 261 ConstantInstr* index_instr = new ConstantInstr(Smi::Handle(Smi::New(ix))); | |
| 262 flow_graph->InsertAfter(instr, index_instr, NULL, Definition::kValue); | |
| 263 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), | |
| 264 new Value(index_instr), | |
| 265 index_scale, | |
| 266 kArrayCid, | |
| 267 Isolate::kNoDeoptId); | |
| 268 instr->ReplaceUsesWith(load); | |
| 269 flow_graph->InsertAfter(index_instr, load, NULL, Definition::kValue); | |
| 270 } | |
| 271 | |
| 272 | |
| 273 // Dart: | |
| 274 // var x = d % 10; | |
| 275 // var y = d ~/ 10; | |
| 276 // var z = x + y; | |
|
Florian Schneider
2013/11/14 10:17:44
Does work correctly for this example where one ope
srdjan
2013/11/20 21:41:47
It does not, you are right. Implemented it differe
| |
| 277 // | |
| 278 // IL: | |
| 279 // v4 <- %(v2, v3) | |
| 280 // v5 <- ~/(v2, v3) | |
| 281 // v6 <- +(v4, v5) | |
| 282 // | |
| 283 // IL optimized: | |
| 284 // v4 <- DIVMOD(v2, v3); | |
| 285 // v5 <- LoadIndexed(v4, 0); // ~/ result | |
| 286 // v6 <- LoadIndexed(v4, 1); // % result | |
| 287 // v7 <- +(v5, v6) | |
| 288 // Because of the environment it is important that DIVMOD replaces first | |
| 289 // instructon (TRUNCDIV or MOD) encountered. | |
|
Florian Schneider
2013/11/14 10:17:44
typo: instruction
srdjan
2013/11/20 21:41:47
Done.
| |
| 290 void FlowGraphOptimizer::TryMergeDivMod(BinarySmiOpInstr* curr_instr) { | |
| 291 ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) || | |
| 292 (curr_instr->op_kind() == Token::kMOD)); | |
| 293 // Check if there is kMOD/kTRUNDIC binop with same inputs. | |
| 294 const intptr_t other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV) ? | |
| 295 Token::kMOD : Token::kTRUNCDIV; | |
| 296 Definition* left_def = curr_instr->left()->definition(); | |
| 297 Definition* right_def = curr_instr->right()->definition(); | |
| 298 GrowableArray<BinarySmiOpInstr*> to_replace; | |
| 299 for (Value::Iterator it(left_def->input_use_list()); | |
| 300 !it.Done(); | |
| 301 it.Advance()) { | |
| 302 Instruction* other_instr = it.Current()->instruction(); | |
| 303 if (other_instr->IsBinarySmiOp() && | |
| 304 (other_instr->AsBinarySmiOp()->op_kind() == other_kind)) { | |
| 305 BinarySmiOpInstr* other_binop = other_instr->AsBinarySmiOp(); | |
| 306 if ((other_binop->left()->definition() == left_def) && | |
| 307 (other_binop->right()->definition() == right_def)) { | |
| 308 // Append a LoadIndexed behind TRUNC_DIV and MOD. | |
| 309 DivModAppendLoadIndexed(curr_instr, flow_graph_); | |
| 310 DivModAppendLoadIndexed(other_binop, flow_graph_); | |
| 311 | |
| 312 // Replace with DivMod. | |
| 313 BinarySmiOpInstr* div_mod = new BinarySmiOpInstr( | |
| 314 Token::kTRUNCDIVMOD, | |
| 315 new Value(curr_instr->left()->definition()), | |
| 316 new Value(curr_instr->right()->definition()), | |
| 317 curr_instr->deopt_id()); | |
| 318 curr_instr->ReplaceWith(div_mod, current_iterator()); | |
| 319 other_binop->ReplaceUsesWith(div_mod); | |
| 320 other_binop->RemoveFromGraph(); | |
| 321 } | |
| 322 } | |
| 323 } | |
| 324 } | |
| 325 | |
| 326 | |
| 254 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the | 327 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the |
| 255 // shift can be a truncating Smi shift-left and result is always Smi. | 328 // shift can be a truncating Smi shift-left and result is always Smi. |
| 256 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() { | 329 void FlowGraphOptimizer::TryOptimizePatterns() { |
| 257 if (!FLAG_truncating_left_shift) return; | 330 if (!FLAG_truncating_left_shift) return; |
| 258 ASSERT(current_iterator_ == NULL); | 331 ASSERT(current_iterator_ == NULL); |
| 259 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 332 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 260 BlockEntryInstr* entry = block_order_[i]; | 333 BlockEntryInstr* entry = block_order_[i]; |
| 261 ForwardInstructionIterator it(entry); | 334 ForwardInstructionIterator it(entry); |
| 262 current_iterator_ = ⁢ | 335 current_iterator_ = ⁢ |
| 263 for (; !it.Done(); it.Advance()) { | 336 for (; !it.Done(); it.Advance()) { |
| 264 if (it.Current()->IsBinarySmiOp()) { | 337 if (it.Current()->IsBinarySmiOp()) { |
| 265 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); | 338 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); |
| 266 if (binop->op_kind() == Token::kBIT_AND) { | 339 if (binop->op_kind() == Token::kBIT_AND) { |
| 267 OptimizeLeftShiftBitAndSmiOp(binop, | 340 OptimizeLeftShiftBitAndSmiOp(binop, |
| 268 binop->left()->definition(), | 341 binop->left()->definition(), |
| 269 binop->right()->definition()); | 342 binop->right()->definition()); |
| 343 } else if ((binop->op_kind() == Token::kTRUNCDIV)|| | |
| 344 (binop->op_kind() == Token::kMOD)) { | |
| 345 TryMergeDivMod(binop); | |
| 270 } | 346 } |
| 271 } else if (it.Current()->IsBinaryMintOp()) { | 347 } else if (it.Current()->IsBinaryMintOp()) { |
| 272 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); | 348 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); |
| 273 if (mintop->op_kind() == Token::kBIT_AND) { | 349 if (mintop->op_kind() == Token::kBIT_AND) { |
| 274 OptimizeLeftShiftBitAndSmiOp(mintop, | 350 OptimizeLeftShiftBitAndSmiOp(mintop, |
| 275 mintop->left()->definition(), | 351 mintop->left()->definition(), |
| 276 mintop->right()->definition()); | 352 mintop->right()->definition()); |
| 277 } | 353 } |
| 278 } | 354 } |
| 279 } | 355 } |
| (...skipping 6439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6719 Instance& result = Integer::ZoneHandle( | 6795 Instance& result = Integer::ZoneHandle( |
| 6720 left_int.BitOp(op_kind, right_int)); | 6796 left_int.BitOp(op_kind, right_int)); |
| 6721 result = result.CheckAndCanonicalize(NULL); | 6797 result = result.CheckAndCanonicalize(NULL); |
| 6722 ASSERT(!result.IsNull()); | 6798 ASSERT(!result.IsNull()); |
| 6723 SetValue(instr, result); | 6799 SetValue(instr, result); |
| 6724 break; | 6800 break; |
| 6725 } | 6801 } |
| 6726 case Token::kDIV: | 6802 case Token::kDIV: |
| 6727 SetValue(instr, non_constant_); | 6803 SetValue(instr, non_constant_); |
| 6728 break; | 6804 break; |
| 6805 case Token::kTRUNCDIVMOD: | |
| 6806 case Token::kTRUNCDIVREM: | |
| 6807 SetValue(instr, non_constant_); | |
| 6808 break; | |
| 6729 default: | 6809 default: |
| 6730 UNREACHABLE(); | 6810 UNREACHABLE(); |
| 6731 } | 6811 } |
| 6732 } else { | 6812 } else { |
| 6733 // TODO(kmillikin): support other types. | 6813 // TODO(kmillikin): support other types. |
| 6734 SetValue(instr, non_constant_); | 6814 SetValue(instr, non_constant_); |
| 6735 } | 6815 } |
| 6736 } | 6816 } |
| 6737 } | 6817 } |
| 6738 | 6818 |
| (...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7912 } | 7992 } |
| 7913 | 7993 |
| 7914 // Insert materializations at environment uses. | 7994 // Insert materializations at environment uses. |
| 7915 for (intptr_t i = 0; i < exits.length(); i++) { | 7995 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7916 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7996 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7917 } | 7997 } |
| 7918 } | 7998 } |
| 7919 | 7999 |
| 7920 | 8000 |
| 7921 } // namespace dart | 8001 } // namespace dart |
| OLD | NEW |