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

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

Issue 79653002: Merge TRUNCDIV and MOD into one instruction. Icorporated feedback from CL https://codereview.chromi… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years 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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
255 // Used by TryMergeDivMod.
256 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction,
257 // and the using instruction. This is an intermediate step before merging.
258 static void DivModAppendLoadIndexed(BinarySmiOpInstr* instr,
259 FlowGraph* flow_graph) {
260 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid);
261 const intptr_t ix = (instr->op_kind() == Token::kTRUNCDIV) ? 0 : 1;
262 ConstantInstr* index_instr = new ConstantInstr(Smi::Handle(Smi::New(ix)));
263 flow_graph->InsertAfter(instr, index_instr, NULL, Definition::kValue);
264 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr),
265 new Value(index_instr),
266 index_scale,
267 kArrayCid,
268 Isolate::kNoDeoptId);
269 instr->ReplaceUsesWith(load);
270 flow_graph->InsertAfter(index_instr, load, NULL, Definition::kValue);
271 }
272
273
274 // Dart:
275 // var x = d % 10;
276 // var y = d ~/ 10;
277 // var z = x + y;
278 //
279 // IL:
280 // v4 <- %(v2, v3)
281 // v5 <- ~/(v2, v3)
282 // v6 <- +(v4, v5)
283 //
284 // IL optimized:
285 // v4 <- DIVMOD(v2, v3);
286 // v5 <- LoadIndexed(v4, 0); // ~/ result
287 // v6 <- LoadIndexed(v4, 1); // % result
288 // v7 <- +(v5, v6)
289 // Because of the environment it is important that merged instruction replaces
290 // first original instruction encountered.
291 void FlowGraphOptimizer::TryMergeTruncDivMod(
292 GrowableArray<BinarySmiOpInstr*>* merge_candidates) {
293 if (merge_candidates->length() < 2) {
294 // Need at least a TRUNCDIV and a MOD.
295 return;
296 }
297 for (intptr_t i = 0; i < merge_candidates->length(); i++) {
298 BinarySmiOpInstr* curr_instr = (*merge_candidates)[i];
299 if (curr_instr == NULL) {
300 // Instructions was merged already.
301 continue;
302 }
303 ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) ||
304 (curr_instr->op_kind() == Token::kMOD));
305 // Check if there is kMOD/kTRUNDIV binop with same inputs.
306 const intptr_t other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV) ?
307 Token::kMOD : Token::kTRUNCDIV;
308 Definition* left_def = curr_instr->left()->definition();
309 Definition* right_def = curr_instr->right()->definition();
310 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
311 BinarySmiOpInstr* other_binop = (*merge_candidates)[k];
312 // 'other_binop' can be NULL if it was already merged.
313 if ((other_binop != NULL) &&
314 (other_binop->op_kind() == other_kind) &&
315 (other_binop->left()->definition() == left_def) &&
316 (other_binop->right()->definition() == right_def)) {
317 (*merge_candidates)[k] = NULL; // Clear it.
318 // Append a LoadIndexed behind TRUNC_DIV and MOD.
319 DivModAppendLoadIndexed(curr_instr, flow_graph_);
320 DivModAppendLoadIndexed(other_binop, flow_graph_);
321
322 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(2);
323 args->Add(new Value(curr_instr->left()->definition()));
324 args->Add(new Value(curr_instr->right()->definition()));
325
326 // Replace with TruncDivMod.
327 MergedMathInstr* div_mod = new MergedMathInstr(
328 args,
329 curr_instr->deopt_id(),
330 MergedMathInstr::kTruncDivMod);
331 curr_instr->ReplaceWith(div_mod, current_iterator());
332 other_binop->ReplaceUsesWith(div_mod);
333 other_binop->RemoveFromGraph();
334 }
335 }
336 }
337 }
338
339
254 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the 340 // 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. 341 // shift can be a truncating Smi shift-left and result is always Smi.
256 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() { 342 // Merging occurs only per basic-block.
343 void FlowGraphOptimizer::TryOptimizePatterns() {
257 if (!FLAG_truncating_left_shift) return; 344 if (!FLAG_truncating_left_shift) return;
258 ASSERT(current_iterator_ == NULL); 345 ASSERT(current_iterator_ == NULL);
346 GrowableArray<BinarySmiOpInstr*> for_merge;
259 for (intptr_t i = 0; i < block_order_.length(); ++i) { 347 for (intptr_t i = 0; i < block_order_.length(); ++i) {
348 // Merging only per basic-block.
349 for_merge.Clear();
260 BlockEntryInstr* entry = block_order_[i]; 350 BlockEntryInstr* entry = block_order_[i];
261 ForwardInstructionIterator it(entry); 351 ForwardInstructionIterator it(entry);
262 current_iterator_ = &it; 352 current_iterator_ = &it;
263 for (; !it.Done(); it.Advance()) { 353 for (; !it.Done(); it.Advance()) {
264 if (it.Current()->IsBinarySmiOp()) { 354 if (it.Current()->IsBinarySmiOp()) {
265 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); 355 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
266 if (binop->op_kind() == Token::kBIT_AND) { 356 if (binop->op_kind() == Token::kBIT_AND) {
267 OptimizeLeftShiftBitAndSmiOp(binop, 357 OptimizeLeftShiftBitAndSmiOp(binop,
268 binop->left()->definition(), 358 binop->left()->definition(),
269 binop->right()->definition()); 359 binop->right()->definition());
360 } else if ((binop->op_kind() == Token::kTRUNCDIV) ||
361 (binop->op_kind() == Token::kMOD)) {
362 for_merge.Add(binop);
270 } 363 }
271 } else if (it.Current()->IsBinaryMintOp()) { 364 } else if (it.Current()->IsBinaryMintOp()) {
272 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); 365 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
273 if (mintop->op_kind() == Token::kBIT_AND) { 366 if (mintop->op_kind() == Token::kBIT_AND) {
274 OptimizeLeftShiftBitAndSmiOp(mintop, 367 OptimizeLeftShiftBitAndSmiOp(mintop,
275 mintop->left()->definition(), 368 mintop->left()->definition(),
276 mintop->right()->definition()); 369 mintop->right()->definition());
277 } 370 }
278 } 371 }
279 } 372 }
373 TryMergeTruncDivMod(&for_merge);
280 current_iterator_ = NULL; 374 current_iterator_ = NULL;
281 } 375 }
282 } 376 }
283 377
284 378
285 static void EnsureSSATempIndex(FlowGraph* graph, 379 static void EnsureSSATempIndex(FlowGraph* graph,
286 Definition* defn, 380 Definition* defn,
287 Definition* replacement) { 381 Definition* replacement) {
288 if ((replacement->ssa_temp_index() == -1) && 382 if ((replacement->ssa_temp_index() == -1) &&
289 (defn->ssa_temp_index() != -1)) { 383 (defn->ssa_temp_index() != -1)) {
(...skipping 6533 matching lines...) Expand 10 before | Expand all | Expand 10 after
6823 SetValue(instr, non_constant_); 6917 SetValue(instr, non_constant_);
6824 } 6918 }
6825 6919
6826 6920
6827 void ConstantPropagator::VisitInvokeMathCFunction( 6921 void ConstantPropagator::VisitInvokeMathCFunction(
6828 InvokeMathCFunctionInstr* instr) { 6922 InvokeMathCFunctionInstr* instr) {
6829 // TODO(kmillikin): Handle conversion. 6923 // TODO(kmillikin): Handle conversion.
6830 SetValue(instr, non_constant_); 6924 SetValue(instr, non_constant_);
6831 } 6925 }
6832 6926
6927
6928 void ConstantPropagator::VisitMergedMath(MergedMathInstr* instr) {
6929 // TODO(srdjan): Handle merged instruction.
6930 SetValue(instr, non_constant_);
6931 }
6932
6933
6833 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { 6934 void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
6834 SetValue(instr, instr->value()); 6935 SetValue(instr, instr->value());
6835 } 6936 }
6836 6937
6837 6938
6838 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) { 6939 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) {
6839 // Should not be used outside of range analysis. 6940 // Should not be used outside of range analysis.
6840 UNREACHABLE(); 6941 UNREACHABLE();
6841 } 6942 }
6842 6943
(...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after
7912 } 8013 }
7913 8014
7914 // Insert materializations at environment uses. 8015 // Insert materializations at environment uses.
7915 for (intptr_t i = 0; i < exits.length(); i++) { 8016 for (intptr_t i = 0; i < exits.length(); i++) {
7916 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 8017 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7917 } 8018 }
7918 } 8019 }
7919 8020
7920 8021
7921 } // namespace dart 8022 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698