Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 68663003: Merge TRUNCDIV and MOD into TRUNCDIV_MOD single operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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_ = &it; 335 current_iterator_ = &it;
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698