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

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

Issue 92433002: Merge sin(a), cos(a) into one instruction. TODO: Implement for ARM and MIPS. (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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 254
255 // Used by TryMergeDivMod. 255 // Used by TryMergeDivMod.
256 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, 256 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction,
257 // and the using instruction. This is an intermediate step before merging. 257 // and the using instruction. This is an intermediate step before merging.
258 static void DivModAppendLoadIndexed(BinarySmiOpInstr* instr, 258 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr,
259 FlowGraph* flow_graph) { 259 intptr_t ix,
260 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); 260 intptr_t cid) {
261 const intptr_t ix = (instr->op_kind() == Token::kTRUNCDIV) ? 0 : 1; 261 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid);
262 ConstantInstr* index_instr = new ConstantInstr(Smi::Handle(Smi::New(ix))); 262 ConstantInstr* index_instr = new ConstantInstr(Smi::Handle(Smi::New(ix)));
263 flow_graph->InsertAfter(instr, index_instr, NULL, Definition::kValue); 263 flow_graph()->InsertAfter(instr, index_instr, NULL, Definition::kValue);
264 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), 264 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr),
265 new Value(index_instr), 265 new Value(index_instr),
266 index_scale, 266 index_scale,
267 kArrayCid, 267 cid,
268 Isolate::kNoDeoptId); 268 Isolate::kNoDeoptId);
269 instr->ReplaceUsesWith(load); 269 instr->ReplaceUsesWith(load);
270 flow_graph->InsertAfter(index_instr, load, NULL, Definition::kValue); 270 flow_graph()->InsertAfter(index_instr, load, NULL, Definition::kValue);
271 } 271 }
272 272
273 273
274 // Dart: 274 // Dart:
275 // var x = d % 10; 275 // var x = d % 10;
276 // var y = d ~/ 10; 276 // var y = d ~/ 10;
277 // var z = x + y; 277 // var z = x + y;
278 // 278 //
279 // IL: 279 // IL:
280 // v4 <- %(v2, v3) 280 // v4 <- %(v2, v3)
281 // v5 <- ~/(v2, v3) 281 // v5 <- ~/(v2, v3)
282 // v6 <- +(v4, v5) 282 // v6 <- +(v4, v5)
283 // 283 //
284 // IL optimized: 284 // IL optimized:
285 // v4 <- DIVMOD(v2, v3); 285 // v4 <- DIVMOD(v2, v3);
286 // v5 <- LoadIndexed(v4, 0); // ~/ result 286 // v5 <- LoadIndexed(v4, 0); // ~/ result
287 // v6 <- LoadIndexed(v4, 1); // % result 287 // v6 <- LoadIndexed(v4, 1); // % result
288 // v7 <- +(v5, v6) 288 // v7 <- +(v5, v6)
289 // Because of the environment it is important that merged instruction replaces 289 // Because of the environment it is important that merged instruction replaces
290 // first original instruction encountered. 290 // first original instruction encountered.
291 void FlowGraphOptimizer::TryMergeTruncDivMod( 291 void FlowGraphOptimizer::TryMergeTruncDivMod(
292 GrowableArray<BinarySmiOpInstr*>* merge_candidates) { 292 GrowableArray<BinarySmiOpInstr*>* merge_candidates) {
293 if (merge_candidates->length() < 2) { 293 if (merge_candidates->length() < 2) {
294 // Need at least a TRUNCDIV and a MOD. 294 // Need at least a TRUNCDIV and a MOD.
295 return; 295 return;
296 } 296 }
297 for (intptr_t i = 0; i < merge_candidates->length(); i++) { 297 for (intptr_t i = 0; i < merge_candidates->length(); i++) {
298 BinarySmiOpInstr* curr_instr = (*merge_candidates)[i]; 298 BinarySmiOpInstr* curr_instr = (*merge_candidates)[i];
299 if (curr_instr == NULL) { 299 if (curr_instr == NULL) {
300 // Instructions was merged already. 300 // Instruction was merged already.
301 continue; 301 continue;
302 } 302 }
303 ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) || 303 ASSERT((curr_instr->op_kind() == Token::kTRUNCDIV) ||
304 (curr_instr->op_kind() == Token::kMOD)); 304 (curr_instr->op_kind() == Token::kMOD));
305 // Check if there is kMOD/kTRUNDIV binop with same inputs. 305 // Check if there is kMOD/kTRUNDIV binop with same inputs.
306 const intptr_t other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV) ? 306 const intptr_t other_kind = (curr_instr->op_kind() == Token::kTRUNCDIV) ?
307 Token::kMOD : Token::kTRUNCDIV; 307 Token::kMOD : Token::kTRUNCDIV;
308 Definition* left_def = curr_instr->left()->definition(); 308 Definition* left_def = curr_instr->left()->definition();
309 Definition* right_def = curr_instr->right()->definition(); 309 Definition* right_def = curr_instr->right()->definition();
310 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) { 310 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
311 BinarySmiOpInstr* other_binop = (*merge_candidates)[k]; 311 BinarySmiOpInstr* other_binop = (*merge_candidates)[k];
312 // 'other_binop' can be NULL if it was already merged. 312 // 'other_binop' can be NULL if it was already merged.
313 if ((other_binop != NULL) && 313 if ((other_binop != NULL) &&
314 (other_binop->op_kind() == other_kind) && 314 (other_binop->op_kind() == other_kind) &&
315 (other_binop->left()->definition() == left_def) && 315 (other_binop->left()->definition() == left_def) &&
316 (other_binop->right()->definition() == right_def)) { 316 (other_binop->right()->definition() == right_def)) {
317 (*merge_candidates)[k] = NULL; // Clear it. 317 (*merge_candidates)[k] = NULL; // Clear it.
318 // Append a LoadIndexed behind TRUNC_DIV and MOD. 318 // Append a LoadIndexed behind TRUNC_DIV and MOD.
319 DivModAppendLoadIndexed(curr_instr, flow_graph_); 319 AppendLoadIndexedForMerged(
320 DivModAppendLoadIndexed(other_binop, flow_graph_); 320 curr_instr,
321 MergedMathInstr::ResultIndexOf(curr_instr->op_kind()),
322 kArrayCid);
323 AppendLoadIndexedForMerged(
324 other_binop,
325 MergedMathInstr::ResultIndexOf(other_binop->op_kind()),
326 kArrayCid);
321 327
322 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(2); 328 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(2);
323 args->Add(new Value(curr_instr->left()->definition())); 329 args->Add(new Value(curr_instr->left()->definition()));
324 args->Add(new Value(curr_instr->right()->definition())); 330 args->Add(new Value(curr_instr->right()->definition()));
325 331
326 // Replace with TruncDivMod. 332 // Replace with TruncDivMod.
327 MergedMathInstr* div_mod = new MergedMathInstr( 333 MergedMathInstr* div_mod = new MergedMathInstr(
328 args, 334 args,
329 curr_instr->deopt_id(), 335 curr_instr->deopt_id(),
330 MergedMathInstr::kTruncDivMod); 336 MergedMathInstr::kTruncDivMod);
331 curr_instr->ReplaceWith(div_mod, current_iterator()); 337 curr_instr->ReplaceWith(div_mod, current_iterator());
332 other_binop->ReplaceUsesWith(div_mod); 338 other_binop->ReplaceUsesWith(div_mod);
333 other_binop->RemoveFromGraph(); 339 other_binop->RemoveFromGraph();
334 } 340 }
335 } 341 }
336 } 342 }
337 } 343 }
338 344
339 345
346 void FlowGraphOptimizer::TryMergeMathUnary(
347 GrowableArray<MathUnaryInstr*>* merge_candidates) {
348 if (!FlowGraphCompiler::SupportsSinCos()) {
349 return;
350 }
351 if (merge_candidates->length() < 2) {
352 // Need at least a SIN and a COS.
353 return;
354 }
355 for (intptr_t i = 0; i < merge_candidates->length(); i++) {
356 MathUnaryInstr* curr_instr = (*merge_candidates)[i];
357 if (curr_instr == NULL) {
358 // Instruction was merged already.
359 continue;
360 }
361 ASSERT((curr_instr->kind() == MethodRecognizer::kMathSin) ||
362 (curr_instr->kind() == MethodRecognizer::kMathCos));
363 // Check if there is sin/cos binop with same inputs.
364 const intptr_t other_kind =
365 (curr_instr->kind() == MethodRecognizer::kMathSin) ?
366 MethodRecognizer::kMathCos : MethodRecognizer::kMathSin;
367 Definition* def = curr_instr->value()->definition();
368 for (intptr_t k = i + 1; k < merge_candidates->length(); k++) {
369 MathUnaryInstr* other_op = (*merge_candidates)[k];
370 // 'other_op' can be NULL if it was already merged.
371 if ((other_op != NULL) && (other_op->kind() == other_kind) &&
372 (other_op->value()->definition() == def)) {
373 (*merge_candidates)[k] = NULL; // Clear it.
374 // Append a LoadIndexed behind SIN and COS.
375 AppendLoadIndexedForMerged(
376 curr_instr,
377 MergedMathInstr::ResultIndexOf(curr_instr->kind()),
378 kTypedDataFloat64ArrayCid);
379 AppendLoadIndexedForMerged(
380 other_op,
381 MergedMathInstr::ResultIndexOf(other_op->kind()),
382 kTypedDataFloat64ArrayCid);
383 ZoneGrowableArray<Value*>* args = new ZoneGrowableArray<Value*>(1);
384 args->Add(new Value(curr_instr->value()->definition()));
385
386 // Replace with TruncDivMod.
387 MergedMathInstr* div_mod = new MergedMathInstr(
388 args,
389 curr_instr->DeoptimizationTarget(),
390 MergedMathInstr::kSinCos);
391 curr_instr->ReplaceWith(div_mod, current_iterator());
392 other_op->ReplaceUsesWith(div_mod);
393 other_op->RemoveFromGraph();
394 OS::Print("Merged SINCOS\n");
395 }
396 }
397 }
398 }
399
400
340 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the 401 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
341 // shift can be a truncating Smi shift-left and result is always Smi. 402 // shift can be a truncating Smi shift-left and result is always Smi.
342 // Merging occurs only per basic-block. 403 // Merging occurs only per basic-block.
343 void FlowGraphOptimizer::TryOptimizePatterns() { 404 void FlowGraphOptimizer::TryOptimizePatterns() {
344 if (!FLAG_truncating_left_shift) return; 405 if (!FLAG_truncating_left_shift) return;
345 ASSERT(current_iterator_ == NULL); 406 ASSERT(current_iterator_ == NULL);
346 GrowableArray<BinarySmiOpInstr*> for_merge; 407 GrowableArray<BinarySmiOpInstr*> div_mod_merge;
408 GrowableArray<MathUnaryInstr*> sin_cos_merge;
347 for (intptr_t i = 0; i < block_order_.length(); ++i) { 409 for (intptr_t i = 0; i < block_order_.length(); ++i) {
348 // Merging only per basic-block. 410 // Merging only per basic-block.
349 for_merge.Clear(); 411 div_mod_merge.Clear();
412 sin_cos_merge.Clear();
350 BlockEntryInstr* entry = block_order_[i]; 413 BlockEntryInstr* entry = block_order_[i];
351 ForwardInstructionIterator it(entry); 414 ForwardInstructionIterator it(entry);
352 current_iterator_ = &it; 415 current_iterator_ = &it;
353 for (; !it.Done(); it.Advance()) { 416 for (; !it.Done(); it.Advance()) {
354 if (it.Current()->IsBinarySmiOp()) { 417 if (it.Current()->IsBinarySmiOp()) {
355 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); 418 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
356 if (binop->op_kind() == Token::kBIT_AND) { 419 if (binop->op_kind() == Token::kBIT_AND) {
357 OptimizeLeftShiftBitAndSmiOp(binop, 420 OptimizeLeftShiftBitAndSmiOp(binop,
358 binop->left()->definition(), 421 binop->left()->definition(),
359 binop->right()->definition()); 422 binop->right()->definition());
360 } else if ((binop->op_kind() == Token::kTRUNCDIV) || 423 } else if ((binop->op_kind() == Token::kTRUNCDIV) ||
361 (binop->op_kind() == Token::kMOD)) { 424 (binop->op_kind() == Token::kMOD)) {
362 for_merge.Add(binop); 425 div_mod_merge.Add(binop);
363 } 426 }
364 } else if (it.Current()->IsBinaryMintOp()) { 427 } else if (it.Current()->IsBinaryMintOp()) {
365 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp(); 428 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
366 if (mintop->op_kind() == Token::kBIT_AND) { 429 if (mintop->op_kind() == Token::kBIT_AND) {
367 OptimizeLeftShiftBitAndSmiOp(mintop, 430 OptimizeLeftShiftBitAndSmiOp(mintop,
368 mintop->left()->definition(), 431 mintop->left()->definition(),
369 mintop->right()->definition()); 432 mintop->right()->definition());
370 } 433 }
434 } else if (it.Current()->IsMathUnary()) {
435 MathUnaryInstr* math_unary = it.Current()->AsMathUnary();
436 if ((math_unary->kind() == MethodRecognizer::kMathSin) ||
437 (math_unary->kind() == MethodRecognizer::kMathCos)) {
438 sin_cos_merge.Add(math_unary);
439 }
371 } 440 }
372 } 441 }
373 TryMergeTruncDivMod(&for_merge); 442 TryMergeTruncDivMod(&div_mod_merge);
443 TryMergeMathUnary(&sin_cos_merge);
374 current_iterator_ = NULL; 444 current_iterator_ = NULL;
375 } 445 }
376 } 446 }
377 447
378 448
379 static void EnsureSSATempIndex(FlowGraph* graph, 449 static void EnsureSSATempIndex(FlowGraph* graph,
380 Definition* defn, 450 Definition* defn,
381 Definition* replacement) { 451 Definition* replacement) {
382 if ((replacement->ssa_temp_index() == -1) && 452 if ((replacement->ssa_temp_index() == -1) &&
383 (defn->ssa_temp_index() != -1)) { 453 (defn->ssa_temp_index() != -1)) {
(...skipping 7592 matching lines...) Expand 10 before | Expand all | Expand 10 after
7976 } 8046 }
7977 8047
7978 // Insert materializations at environment uses. 8048 // Insert materializations at environment uses.
7979 for (intptr_t i = 0; i < exits.length(); i++) { 8049 for (intptr_t i = 0; i < exits.length(); i++) {
7980 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 8050 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7981 } 8051 }
7982 } 8052 }
7983 8053
7984 8054
7985 } // namespace dart 8055 } // 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