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

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

Issue 12218181: Recognize pattern (a << b) & c with c being a positive Smi and allow left shift to truncate the res… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months 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/il_printer.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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 15 matching lines...) Expand all
26 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); 26 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
27 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); 27 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
28 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); 28 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
29 DEFINE_FLAG(bool, trace_constant_propagation, false, 29 DEFINE_FLAG(bool, trace_constant_propagation, false,
30 "Print constant propagation and useless code elimination."); 30 "Print constant propagation and useless code elimination.");
31 DEFINE_FLAG(bool, array_bounds_check_elimination, true, 31 DEFINE_FLAG(bool, array_bounds_check_elimination, true,
32 "Eliminate redundant bounds checks."); 32 "Eliminate redundant bounds checks.");
33 DEFINE_FLAG(int, max_polymorphic_checks, 4, 33 DEFINE_FLAG(int, max_polymorphic_checks, 4,
34 "Maximum number of polymorphic check, otherwise it is megamorphic."); 34 "Maximum number of polymorphic check, otherwise it is megamorphic.");
35 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); 35 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis.");
36 DEFINE_FLAG(bool, truncating_left_shift, true,
37 "Optimize left shift to truncate if possible");
36 38
37 39
38 void FlowGraphOptimizer::ApplyICData() { 40 void FlowGraphOptimizer::ApplyICData() {
39 VisitBlocks(); 41 VisitBlocks();
40 } 42 }
41 43
42 44
43 // Attempts to convert an instance call (IC call) using propagated class-ids, 45 // Attempts to convert an instance call (IC call) using propagated class-ids,
44 // e.g., receiver class id. 46 // e.g., receiver class id.
45 void FlowGraphOptimizer::ApplyClassIds() { 47 void FlowGraphOptimizer::ApplyClassIds() {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 162
161 const bool with_checks = false; 163 const bool with_checks = false;
162 PolymorphicInstanceCallInstr* specialized = 164 PolymorphicInstanceCallInstr* specialized =
163 new PolymorphicInstanceCallInstr(call->instance_call(), 165 new PolymorphicInstanceCallInstr(call->instance_call(),
164 ic_data, 166 ic_data,
165 with_checks); 167 with_checks);
166 call->ReplaceWith(specialized, current_iterator()); 168 call->ReplaceWith(specialized, current_iterator());
167 } 169 }
168 170
169 171
172 static BinarySmiOpInstr* AsSmiShiftLeftInstruction(Definition* d) {
173 BinarySmiOpInstr* instr = d->AsBinarySmiOp();
174 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) {
175 return instr;
176 }
177 return NULL;
178 }
179
180
181 static bool IsPositiveOrZeroSmiConst(Definition* d) {
182 ConstantInstr* const_instr = d->AsConstant();
183 if ((const_instr != NULL) && (const_instr->value().IsSmi())) {
184 return Smi::Cast(const_instr->value()).Value() >= 0;
185 }
186 return false;
187 }
188
189
190 void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp(
191 Definition* bit_and_instr,
192 Definition* left_instr,
193 Definition* right_instr) {
194 ASSERT(bit_and_instr != NULL);
195 ASSERT((left_instr != NULL) && (right_instr != NULL));
196
197 // Check for pattern, smi_shift_left must be single-use.
198 bool is_positive_or_zero = IsPositiveOrZeroSmiConst(left_instr);
199 if (!is_positive_or_zero) {
200 is_positive_or_zero = IsPositiveOrZeroSmiConst(right_instr);
201 }
202 if (!is_positive_or_zero) return;
203
204 BinarySmiOpInstr* smi_shift_left = NULL;
205 if (bit_and_instr->InputAt(0)->IsSingleUse()) {
206 smi_shift_left = AsSmiShiftLeftInstruction(left_instr);
207 }
208 if ((smi_shift_left == NULL) && (bit_and_instr->InputAt(1)->IsSingleUse())) {
209 smi_shift_left = AsSmiShiftLeftInstruction(right_instr);
210 }
211 if (smi_shift_left == NULL) return;
212
213 // Pattern recognized.
214 smi_shift_left->set_is_truncating(true);
215 ASSERT(bit_and_instr->IsBinarySmiOp() || bit_and_instr->IsBinaryMintOp());
216 if (bit_and_instr->IsBinaryMintOp()) {
217 // Replace Mint op with Smi op.
218 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr(
219 Token::kBIT_AND,
220 bit_and_instr->AsBinaryMintOp()->instance_call(),
221 new Value(left_instr),
222 new Value(right_instr));
223 bit_and_instr->ReplaceWith(smi_op, current_iterator());
224 }
225 }
226
227
228 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
229 // shift can be a truncating Smi shift-left and result is always Smi.
230 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() {
231 if (!FLAG_truncating_left_shift) return;
232 ASSERT(current_iterator_ == NULL);
233 for (intptr_t i = 0; i < block_order_.length(); ++i) {
234 BlockEntryInstr* entry = block_order_[i];
235 ForwardInstructionIterator it(entry);
236 current_iterator_ = &it;
237 for (; !it.Done(); it.Advance()) {
238 if (it.Current()->IsBinarySmiOp()) {
239 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
240 if (binop->op_kind() == Token::kBIT_AND) {
241 OptimizeLeftShiftBitAndSmiOp(binop,
242 binop->left()->definition(),
243 binop->right()->definition());
244 }
245 } else if (it.Current()->IsBinaryMintOp()) {
246 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
247 if (mintop->op_kind() == Token::kBIT_AND) {
248 OptimizeLeftShiftBitAndSmiOp(mintop,
249 mintop->left()->definition(),
250 mintop->right()->definition());
251 }
252 }
253 }
254 current_iterator_ = NULL;
255 }
256 }
257
258
170 static void EnsureSSATempIndex(FlowGraph* graph, 259 static void EnsureSSATempIndex(FlowGraph* graph,
171 Definition* defn, 260 Definition* defn,
172 Definition* replacement) { 261 Definition* replacement) {
173 if ((replacement->ssa_temp_index() == -1) && 262 if ((replacement->ssa_temp_index() == -1) &&
174 (defn->ssa_temp_index() != -1)) { 263 (defn->ssa_temp_index() != -1)) {
175 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index()); 264 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index());
176 } 265 }
177 } 266 }
178 267
179 268
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 if (ic_data.NumberOfChecks() != 1) return kIllegalCid; 582 if (ic_data.NumberOfChecks() != 1) return kIllegalCid;
494 ASSERT(ic_data.HasOneTarget()); 583 ASSERT(ic_data.HasOneTarget());
495 584
496 Function& target = Function::Handle(); 585 Function& target = Function::Handle();
497 intptr_t class_id; 586 intptr_t class_id;
498 ic_data.GetOneClassCheckAt(0, &class_id, &target); 587 ic_data.GetOneClassCheckAt(0, &class_id, &target);
499 return class_id; 588 return class_id;
500 } 589 }
501 590
502 591
592 void FlowGraphOptimizer::AddCheckSmi(Definition* to_check,
593 intptr_t deopt_id,
594 Environment* deopt_environment,
595 Instruction* insert_before) {
596 if (to_check->Type()->ToCid() != kSmiCid) {
597 InsertBefore(insert_before,
598 new CheckSmiInstr(new Value(to_check), deopt_id),
599 deopt_environment,
600 Definition::kEffect);
601 }
602 }
603
604
503 void FlowGraphOptimizer::AddCheckClass(Definition* to_check, 605 void FlowGraphOptimizer::AddCheckClass(Definition* to_check,
504 const ICData& unary_checks, 606 const ICData& unary_checks,
505 intptr_t deopt_id, 607 intptr_t deopt_id,
506 Environment* deopt_environment, 608 Environment* deopt_environment,
507 Instruction* insert_before) { 609 Instruction* insert_before) {
508 // Type propagation has not run yet, we cannot eliminate the check. 610 // Type propagation has not run yet, we cannot eliminate the check.
509 Instruction* check = NULL; 611 Instruction* check = NULL;
510 if ((unary_checks.NumberOfChecks() == 1) && 612 if ((unary_checks.NumberOfChecks() == 1) &&
511 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) { 613 (unary_checks.GetReceiverClassIdAt(0) == kSmiCid)) {
512 check = new CheckSmiInstr(new Value(to_check), deopt_id); 614 check = new CheckSmiInstr(new Value(to_check), deopt_id);
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
1004 InsertBefore(call, constant, NULL, Definition::kValue); 1106 InsertBefore(call, constant, NULL, Definition::kValue);
1005 BinarySmiOpInstr* bin_op = 1107 BinarySmiOpInstr* bin_op =
1006 new BinarySmiOpInstr(Token::kBIT_AND, call, 1108 new BinarySmiOpInstr(Token::kBIT_AND, call,
1007 new Value(left), 1109 new Value(left),
1008 new Value(constant)); 1110 new Value(constant));
1009 ReplaceCall(call, bin_op); 1111 ReplaceCall(call, bin_op);
1010 } else { 1112 } else {
1011 ASSERT(operands_type == kSmiCid); 1113 ASSERT(operands_type == kSmiCid);
1012 // Insert two smi checks and attach a copy of the original 1114 // Insert two smi checks and attach a copy of the original
1013 // environment because the smi operation can still deoptimize. 1115 // environment because the smi operation can still deoptimize.
1014 InsertBefore(call, 1116 AddCheckSmi(left, call->deopt_id(), call->env(), call);
1015 new CheckSmiInstr(new Value(left), call->deopt_id()), 1117 AddCheckSmi(right, call->deopt_id(), call->env(), call);
1016 call->env(),
1017 Definition::kEffect);
1018 InsertBefore(call,
1019 new CheckSmiInstr(new Value(right), call->deopt_id()),
1020 call->env(),
1021 Definition::kEffect);
1022 if (left->IsConstant() && 1118 if (left->IsConstant() &&
1023 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { 1119 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
1024 // Constant should be on the right side. 1120 // Constant should be on the right side.
1025 Definition* temp = left; 1121 Definition* temp = left;
1026 left = right; 1122 left = right;
1027 right = temp; 1123 right = temp;
1028 } 1124 }
1029 BinarySmiOpInstr* bin_op = 1125 BinarySmiOpInstr* bin_op =
1030 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right)); 1126 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right));
1031 ReplaceCall(call, bin_op); 1127 ReplaceCall(call, bin_op);
(...skipping 3240 matching lines...) Expand 10 before | Expand all | Expand 10 after
4272 4368
4273 if (FLAG_trace_constant_propagation) { 4369 if (FLAG_trace_constant_propagation) {
4274 OS::Print("\n==== After constant propagation ====\n"); 4370 OS::Print("\n==== After constant propagation ====\n");
4275 FlowGraphPrinter printer(*graph_); 4371 FlowGraphPrinter printer(*graph_);
4276 printer.PrintBlocks(); 4372 printer.PrintBlocks();
4277 } 4373 }
4278 } 4374 }
4279 4375
4280 4376
4281 } // namespace dart 4377 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698