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

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
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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 160
161 const bool with_checks = false; 161 const bool with_checks = false;
162 PolymorphicInstanceCallInstr* specialized = 162 PolymorphicInstanceCallInstr* specialized =
163 new PolymorphicInstanceCallInstr(call->instance_call(), 163 new PolymorphicInstanceCallInstr(call->instance_call(),
164 ic_data, 164 ic_data,
165 with_checks); 165 with_checks);
166 call->ReplaceWith(specialized, current_iterator()); 166 call->ReplaceWith(specialized, current_iterator());
167 } 167 }
168 168
169 169
170 static BinarySmiOpInstr* AsSmiLeftShiftInstruction(Value* v) {
171 BinarySmiOpInstr* instr = v->definition()->AsBinarySmiOp();
172 if ((instr != NULL) && (instr->op_kind() == Token::kSHL)) {
173 return instr;
174 }
175 return NULL;
176 }
177
178
179 Value* AsPositiveSmiConstValue(Value* v) {
180 if (v->BindsToConstant() && v->BoundConstant().IsSmi()) {
181 if (Smi::Cast(v->BoundConstant()).Value() >= 0) {
182 return v;
183 }
184 }
185 return NULL;
186 }
187
188
189 void FlowGraphOptimizer::OptimizeLeftShiftBitAndSmiOp(
Kevin Millikin (Google) 2013/02/21 12:44:35 I also think this kind of function is clearer if i
srdjan 2013/02/21 21:55:31 Done.
190 Definition* bit_and_instr,
191 Value* left,
192 Value* right) {
193 // Check for pattern, smi_left_shift value must be single-use.
194 BinarySmiOpInstr* smi_left_shift = NULL;
195 Value* smi_const = AsPositiveSmiConstValue(left);
196 if (smi_const == NULL) {
197 smi_const = AsPositiveSmiConstValue(right);
198 if (left->IsSingleUse() && (smi_const != NULL)) {
199 smi_left_shift = AsSmiLeftShiftInstruction(left);
200 }
201 } else if (right->IsSingleUse()) {
202 smi_left_shift = AsSmiLeftShiftInstruction(right);
203 }
204 if ((smi_left_shift == NULL) || (smi_const == NULL)) {
205 // Not the pattern '(mint,smi)-bit-and with smi-left-shift and smi-const'.
206 return;
207 }
208 // TODO(srdjan): If done post inlining, we must check environment uses.
209 if (bit_and_instr->IsBinarySmiOp()) {
210 smi_left_shift->set_is_truncating(true);
211 } else {
212 ASSERT(bit_and_instr->IsBinaryMintOp());
213 smi_left_shift->set_is_truncating(true);
214 // Replace Mint op with Smi op.
215 BinarySmiOpInstr* smi_op = new BinarySmiOpInstr(
216 Token::kBIT_AND,
217 bit_and_instr->AsBinaryMintOp()->instance_call(),
218 left->Copy(),
219 right->Copy());
220 bit_and_instr->ReplaceWith(smi_op, current_iterator());
221 }
222 }
223
224
225 // Optimize (a << b) & c pattern: if c is a positive smi, then the
226 // shift can be a truncating Smi shift and result is always Smi.
227 void FlowGraphOptimizer::TryOptimizeLeftShiftWithBitAndPattern() {
228 ASSERT(current_iterator_ == NULL);
229 for (intptr_t i = 0; i < block_order_.length(); ++i) {
230 BlockEntryInstr* entry = block_order_[i];
231 ForwardInstructionIterator it(entry);
232 current_iterator_ = &it;
233 for (; !it.Done(); it.Advance()) {
234 if (it.Current()->IsBinarySmiOp()) {
235 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp();
236 if (binop->op_kind() == Token::kBIT_AND) {
237 OptimizeLeftShiftBitAndSmiOp(binop, binop->left(), binop->right());
238 }
239 } else if (it.Current()->IsBinaryMintOp()) {
240 BinaryMintOpInstr* mintop = it.Current()->AsBinaryMintOp();
241 if (mintop->op_kind() == Token::kBIT_AND) {
242 OptimizeLeftShiftBitAndSmiOp(mintop, mintop->left(), mintop->right());
243 }
244 }
245 }
246 current_iterator_ = NULL;
247 }
248 }
249
250
170 static void EnsureSSATempIndex(FlowGraph* graph, 251 static void EnsureSSATempIndex(FlowGraph* graph,
171 Definition* defn, 252 Definition* defn,
172 Definition* replacement) { 253 Definition* replacement) {
173 if ((replacement->ssa_temp_index() == -1) && 254 if ((replacement->ssa_temp_index() == -1) &&
174 (defn->ssa_temp_index() != -1)) { 255 (defn->ssa_temp_index() != -1)) {
175 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index()); 256 replacement->set_ssa_temp_index(graph->alloc_ssa_temp_index());
176 } 257 }
177 } 258 }
178 259
179 260
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 InsertBefore(call, constant, NULL, Definition::kValue); 1028 InsertBefore(call, constant, NULL, Definition::kValue);
948 BinarySmiOpInstr* bin_op = 1029 BinarySmiOpInstr* bin_op =
949 new BinarySmiOpInstr(Token::kBIT_AND, call, 1030 new BinarySmiOpInstr(Token::kBIT_AND, call,
950 new Value(left), 1031 new Value(left),
951 new Value(constant)); 1032 new Value(constant));
952 ReplaceCall(call, bin_op); 1033 ReplaceCall(call, bin_op);
953 } else { 1034 } else {
954 ASSERT(operands_type == kSmiCid); 1035 ASSERT(operands_type == kSmiCid);
955 // Insert two smi checks and attach a copy of the original 1036 // Insert two smi checks and attach a copy of the original
956 // environment because the smi operation can still deoptimize. 1037 // environment because the smi operation can still deoptimize.
957 InsertBefore(call, 1038 if (left->Type()->ToCid() != kSmiCid) {
Vyacheslav Egorov (Google) 2013/02/21 14:45:50 I suggest to create a method that inserts a check:
srdjan 2013/02/21 21:55:31 Done.
958 new CheckSmiInstr(new Value(left), call->deopt_id()), 1039 InsertBefore(call,
959 call->env(), 1040 new CheckSmiInstr(new Value(left), call->deopt_id()),
960 Definition::kEffect); 1041 call->env(),
961 InsertBefore(call, 1042 Definition::kEffect);
962 new CheckSmiInstr(new Value(right), call->deopt_id()), 1043 }
963 call->env(), 1044 if (right->Type()->ToCid() != kSmiCid) {
964 Definition::kEffect); 1045 InsertBefore(call,
1046 new CheckSmiInstr(new Value(right), call->deopt_id()),
1047 call->env(),
1048 Definition::kEffect);
1049 }
965 if (left->IsConstant() && 1050 if (left->IsConstant() &&
966 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) { 1051 ((op_kind == Token::kADD) || (op_kind == Token::kMUL))) {
967 // Constant should be on the right side. 1052 // Constant should be on the right side.
968 Definition* temp = left; 1053 Definition* temp = left;
969 left = right; 1054 left = right;
970 right = temp; 1055 right = temp;
971 } 1056 }
972 BinarySmiOpInstr* bin_op = 1057 BinarySmiOpInstr* bin_op =
973 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right)); 1058 new BinarySmiOpInstr(op_kind, call, new Value(left), new Value(right));
974 ReplaceCall(call, bin_op); 1059 ReplaceCall(call, bin_op);
(...skipping 3211 matching lines...) Expand 10 before | Expand all | Expand 10 after
4186 4271
4187 if (FLAG_trace_constant_propagation) { 4272 if (FLAG_trace_constant_propagation) {
4188 OS::Print("\n==== After constant propagation ====\n"); 4273 OS::Print("\n==== After constant propagation ====\n");
4189 FlowGraphPrinter printer(*graph_); 4274 FlowGraphPrinter printer(*graph_);
4190 printer.PrintBlocks(); 4275 printer.PrintBlocks();
4191 } 4276 }
4192 } 4277 }
4193 4278
4194 4279
4195 } // namespace dart 4280 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698