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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 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
« no previous file with comments | « runtime/vm/flow_graph_range_analysis.h ('k') | runtime/vm/flow_graph_range_analysis_test.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_range_analysis.h" 5 #include "vm/flow_graph_range_analysis.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/il_printer.h" 8 #include "vm/il_printer.h"
9 9
10 namespace dart { 10 namespace dart {
(...skipping 22 matching lines...) Expand all
33 MarkUnreachableBlocks(); 33 MarkUnreachableBlocks();
34 34
35 NarrowMintToInt32(); 35 NarrowMintToInt32();
36 36
37 IntegerInstructionSelector iis(flow_graph_); 37 IntegerInstructionSelector iis(flow_graph_);
38 iis.Select(); 38 iis.Select();
39 39
40 RemoveConstraints(); 40 RemoveConstraints();
41 } 41 }
42 42
43
44 static Definition* UnwrapConstraint(Definition* defn) { 43 static Definition* UnwrapConstraint(Definition* defn) {
45 while (defn->IsConstraint()) { 44 while (defn->IsConstraint()) {
46 defn = defn->AsConstraint()->value()->definition(); 45 defn = defn->AsConstraint()->value()->definition();
47 } 46 }
48 return defn; 47 return defn;
49 } 48 }
50 49
51
52 // Simple induction variable is a variable that satisfies the following pattern: 50 // Simple induction variable is a variable that satisfies the following pattern:
53 // 51 //
54 // v1 <- phi(v0, v1 + 1) 52 // v1 <- phi(v0, v1 + 1)
55 // 53 //
56 // If there are two simple induction variables in the same block and one of 54 // If there are two simple induction variables in the same block and one of
57 // them is constrained - then another one is constrained as well, e.g. 55 // them is constrained - then another one is constrained as well, e.g.
58 // from 56 // from
59 // 57 //
60 // B1: 58 // B1:
61 // v3 <- phi(v0, v3 + 1) 59 // v3 <- phi(v0, v3 + 1)
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 99
102 private: 100 private:
103 PhiInstr* phi_; 101 PhiInstr* phi_;
104 Definition* initial_value_; 102 Definition* initial_value_;
105 BinarySmiOpInstr* increment_; 103 BinarySmiOpInstr* increment_;
106 ConstraintInstr* limit_; 104 ConstraintInstr* limit_;
107 105
108 PhiInstr* bound_; 106 PhiInstr* bound_;
109 }; 107 };
110 108
111
112 static ConstraintInstr* FindBoundingConstraint(PhiInstr* phi, 109 static ConstraintInstr* FindBoundingConstraint(PhiInstr* phi,
113 Definition* defn) { 110 Definition* defn) {
114 ConstraintInstr* limit = NULL; 111 ConstraintInstr* limit = NULL;
115 for (ConstraintInstr* constraint = defn->AsConstraint(); constraint != NULL; 112 for (ConstraintInstr* constraint = defn->AsConstraint(); constraint != NULL;
116 constraint = constraint->value()->definition()->AsConstraint()) { 113 constraint = constraint->value()->definition()->AsConstraint()) {
117 if (constraint->target() == NULL) { 114 if (constraint->target() == NULL) {
118 continue; // Only interested in non-artifical constraints. 115 continue; // Only interested in non-artifical constraints.
119 } 116 }
120 117
121 Range* constraining_range = constraint->constraint(); 118 Range* constraining_range = constraint->constraint();
122 if (constraining_range->min().Equals(RangeBoundary::MinSmi()) && 119 if (constraining_range->min().Equals(RangeBoundary::MinSmi()) &&
123 (constraining_range->max().IsSymbol() && 120 (constraining_range->max().IsSymbol() &&
124 phi->IsDominatedBy(constraining_range->max().symbol()))) { 121 phi->IsDominatedBy(constraining_range->max().symbol()))) {
125 limit = constraint; 122 limit = constraint;
126 } 123 }
127 } 124 }
128 125
129 return limit; 126 return limit;
130 } 127 }
131 128
132
133 static InductionVariableInfo* DetectSimpleInductionVariable(PhiInstr* phi) { 129 static InductionVariableInfo* DetectSimpleInductionVariable(PhiInstr* phi) {
134 if (phi->Type()->ToCid() != kSmiCid) { 130 if (phi->Type()->ToCid() != kSmiCid) {
135 return NULL; 131 return NULL;
136 } 132 }
137 133
138 if (phi->InputCount() != 2) { 134 if (phi->InputCount() != 2) {
139 return NULL; 135 return NULL;
140 } 136 }
141 137
142 BitVector* loop_info = phi->block()->loop_info(); 138 BitVector* loop_info = phi->block()->loop_info();
(...skipping 15 matching lines...) Expand all
158 increment->right()->BoundConstant().IsSmi() && 154 increment->right()->BoundConstant().IsSmi() &&
159 (Smi::Cast(increment->right()->BoundConstant()).Value() == 1)) { 155 (Smi::Cast(increment->right()->BoundConstant()).Value() == 1)) {
160 return new InductionVariableInfo( 156 return new InductionVariableInfo(
161 phi, initial_value, increment, 157 phi, initial_value, increment,
162 FindBoundingConstraint(phi, increment->left()->definition())); 158 FindBoundingConstraint(phi, increment->left()->definition()));
163 } 159 }
164 160
165 return NULL; 161 return NULL;
166 } 162 }
167 163
168
169 void RangeAnalysis::DiscoverSimpleInductionVariables() { 164 void RangeAnalysis::DiscoverSimpleInductionVariables() {
170 GrowableArray<InductionVariableInfo*> loop_variables; 165 GrowableArray<InductionVariableInfo*> loop_variables;
171 166
172 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 167 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
173 !block_it.Done(); block_it.Advance()) { 168 !block_it.Done(); block_it.Advance()) {
174 BlockEntryInstr* block = block_it.Current(); 169 BlockEntryInstr* block = block_it.Current();
175 170
176 JoinEntryInstr* join = block->AsJoinEntry(); 171 JoinEntryInstr* join = block->AsJoinEntry();
177 if (join != NULL && join->loop_info() != NULL) { 172 if (join != NULL && join->loop_info() != NULL) {
178 loop_variables.Clear(); 173 loop_variables.Clear();
(...skipping 25 matching lines...) Expand all
204 if (bound != NULL) { 199 if (bound != NULL) {
205 for (intptr_t i = 0; i < loop_variables.length(); i++) { 200 for (intptr_t i = 0; i < loop_variables.length(); i++) {
206 InductionVariableInfo* info = loop_variables[i]; 201 InductionVariableInfo* info = loop_variables[i];
207 info->set_bound(bound->phi()); 202 info->set_bound(bound->phi());
208 info->phi()->set_induction_variable_info(info); 203 info->phi()->set_induction_variable_info(info);
209 } 204 }
210 } 205 }
211 } 206 }
212 } 207 }
213 208
214
215 void RangeAnalysis::CollectValues() { 209 void RangeAnalysis::CollectValues() {
216 const GrowableArray<Definition*>& initial = 210 const GrowableArray<Definition*>& initial =
217 *flow_graph_->graph_entry()->initial_definitions(); 211 *flow_graph_->graph_entry()->initial_definitions();
218 for (intptr_t i = 0; i < initial.length(); ++i) { 212 for (intptr_t i = 0; i < initial.length(); ++i) {
219 Definition* current = initial[i]; 213 Definition* current = initial[i];
220 if (IsIntegerDefinition(current)) { 214 if (IsIntegerDefinition(current)) {
221 values_.Add(current); 215 values_.Add(current);
222 } 216 }
223 } 217 }
224 218
225 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 219 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
226 !block_it.Done(); block_it.Advance()) { 220 !block_it.Done(); block_it.Advance()) {
227 BlockEntryInstr* block = block_it.Current(); 221 BlockEntryInstr* block = block_it.Current();
228 222
229
230 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { 223 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) {
231 const GrowableArray<Definition*>& initial = 224 const GrowableArray<Definition*>& initial =
232 block->IsGraphEntry() 225 block->IsGraphEntry()
233 ? *block->AsGraphEntry()->initial_definitions() 226 ? *block->AsGraphEntry()->initial_definitions()
234 : *block->AsCatchBlockEntry()->initial_definitions(); 227 : *block->AsCatchBlockEntry()->initial_definitions();
235 for (intptr_t i = 0; i < initial.length(); ++i) { 228 for (intptr_t i = 0; i < initial.length(); ++i) {
236 Definition* current = initial[i]; 229 Definition* current = initial[i];
237 if (IsIntegerDefinition(current)) { 230 if (IsIntegerDefinition(current)) {
238 values_.Add(current); 231 values_.Add(current);
239 } 232 }
(...skipping 23 matching lines...) Expand all
263 shift_mint_ops_.Add(defn->AsShiftMintOp()); 256 shift_mint_ops_.Add(defn->AsShiftMintOp());
264 } 257 }
265 } 258 }
266 } else if (current->IsCheckArrayBound()) { 259 } else if (current->IsCheckArrayBound()) {
267 bounds_checks_.Add(current->AsCheckArrayBound()); 260 bounds_checks_.Add(current->AsCheckArrayBound());
268 } 261 }
269 } 262 }
270 } 263 }
271 } 264 }
272 265
273
274 // For a comparison operation return an operation for the equivalent flipped 266 // For a comparison operation return an operation for the equivalent flipped
275 // comparison: a (op) b === b (op') a. 267 // comparison: a (op) b === b (op') a.
276 static Token::Kind FlipComparison(Token::Kind op) { 268 static Token::Kind FlipComparison(Token::Kind op) {
277 switch (op) { 269 switch (op) {
278 case Token::kEQ: 270 case Token::kEQ:
279 return Token::kEQ; 271 return Token::kEQ;
280 case Token::kNE: 272 case Token::kNE:
281 return Token::kNE; 273 return Token::kNE;
282 case Token::kLT: 274 case Token::kLT:
283 return Token::kGT; 275 return Token::kGT;
284 case Token::kGT: 276 case Token::kGT:
285 return Token::kLT; 277 return Token::kLT;
286 case Token::kLTE: 278 case Token::kLTE:
287 return Token::kGTE; 279 return Token::kGTE;
288 case Token::kGTE: 280 case Token::kGTE:
289 return Token::kLTE; 281 return Token::kLTE;
290 default: 282 default:
291 UNREACHABLE(); 283 UNREACHABLE();
292 return Token::kILLEGAL; 284 return Token::kILLEGAL;
293 } 285 }
294 } 286 }
295 287
296
297 // Given a boundary (right operand) and a comparison operation return 288 // Given a boundary (right operand) and a comparison operation return
298 // a symbolic range constraint for the left operand of the comparison assuming 289 // a symbolic range constraint for the left operand of the comparison assuming
299 // that it evaluated to true. 290 // that it evaluated to true.
300 // For example for the comparison a < b symbol a is constrained with range 291 // For example for the comparison a < b symbol a is constrained with range
301 // [Smi::kMinValue, b - 1]. 292 // [Smi::kMinValue, b - 1].
302 Range* RangeAnalysis::ConstraintSmiRange(Token::Kind op, Definition* boundary) { 293 Range* RangeAnalysis::ConstraintSmiRange(Token::Kind op, Definition* boundary) {
303 switch (op) { 294 switch (op) {
304 case Token::kEQ: 295 case Token::kEQ:
305 return new (Z) Range(RangeBoundary::FromDefinition(boundary), 296 return new (Z) Range(RangeBoundary::FromDefinition(boundary),
306 RangeBoundary::FromDefinition(boundary)); 297 RangeBoundary::FromDefinition(boundary));
(...skipping 10 matching lines...) Expand all
317 RangeBoundary::FromDefinition(boundary)); 308 RangeBoundary::FromDefinition(boundary));
318 case Token::kGTE: 309 case Token::kGTE:
319 return new (Z) Range(RangeBoundary::FromDefinition(boundary), 310 return new (Z) Range(RangeBoundary::FromDefinition(boundary),
320 RangeBoundary::MaxSmi()); 311 RangeBoundary::MaxSmi());
321 default: 312 default:
322 UNREACHABLE(); 313 UNREACHABLE();
323 return NULL; 314 return NULL;
324 } 315 }
325 } 316 }
326 317
327
328 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Value* use, 318 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Value* use,
329 Definition* defn, 319 Definition* defn,
330 Range* constraint_range, 320 Range* constraint_range,
331 Instruction* after) { 321 Instruction* after) {
332 // No need to constrain constants. 322 // No need to constrain constants.
333 if (defn->IsConstant()) return NULL; 323 if (defn->IsConstant()) return NULL;
334 324
335 // Check if the value is already constrained to avoid inserting duplicated 325 // Check if the value is already constrained to avoid inserting duplicated
336 // constraints. 326 // constraints.
337 ConstraintInstr* constraint = after->next()->AsConstraint(); 327 ConstraintInstr* constraint = after->next()->AsConstraint();
338 while (constraint != NULL) { 328 while (constraint != NULL) {
339 if ((constraint->value()->definition() == defn) && 329 if ((constraint->value()->definition() == defn) &&
340 constraint->constraint()->Equals(constraint_range)) { 330 constraint->constraint()->Equals(constraint_range)) {
341 return NULL; 331 return NULL;
342 } 332 }
343 constraint = constraint->next()->AsConstraint(); 333 constraint = constraint->next()->AsConstraint();
344 } 334 }
345 335
346 constraint = new (Z) ConstraintInstr(use->CopyWithType(), constraint_range); 336 constraint = new (Z) ConstraintInstr(use->CopyWithType(), constraint_range);
347 337
348 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue); 338 flow_graph_->InsertAfter(after, constraint, NULL, FlowGraph::kValue);
349 FlowGraph::RenameDominatedUses(defn, constraint, constraint); 339 FlowGraph::RenameDominatedUses(defn, constraint, constraint);
350 constraints_.Add(constraint); 340 constraints_.Add(constraint);
351 return constraint; 341 return constraint;
352 } 342 }
353 343
354
355 bool RangeAnalysis::ConstrainValueAfterBranch(Value* use, Definition* defn) { 344 bool RangeAnalysis::ConstrainValueAfterBranch(Value* use, Definition* defn) {
356 BranchInstr* branch = use->instruction()->AsBranch(); 345 BranchInstr* branch = use->instruction()->AsBranch();
357 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp(); 346 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp();
358 if ((rel_op != NULL) && (rel_op->operation_cid() == kSmiCid)) { 347 if ((rel_op != NULL) && (rel_op->operation_cid() == kSmiCid)) {
359 // Found comparison of two smis. Constrain defn at true and false 348 // Found comparison of two smis. Constrain defn at true and false
360 // successors using the other operand as a boundary. 349 // successors using the other operand as a boundary.
361 Definition* boundary; 350 Definition* boundary;
362 Token::Kind op_kind; 351 Token::Kind op_kind;
363 if (use->use_index() == 0) { // Left operand. 352 if (use->use_index() == 0) { // Left operand.
364 boundary = rel_op->InputAt(1)->definition(); 353 boundary = rel_op->InputAt(1)->definition();
(...skipping 22 matching lines...) Expand all
387 if (false_constraint != NULL) { 376 if (false_constraint != NULL) {
388 false_constraint->set_target(branch->false_successor()); 377 false_constraint->set_target(branch->false_successor());
389 } 378 }
390 379
391 return true; 380 return true;
392 } 381 }
393 382
394 return false; 383 return false;
395 } 384 }
396 385
397
398 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { 386 void RangeAnalysis::InsertConstraintsFor(Definition* defn) {
399 for (Value* use = defn->input_use_list(); use != NULL; 387 for (Value* use = defn->input_use_list(); use != NULL;
400 use = use->next_use()) { 388 use = use->next_use()) {
401 if (use->instruction()->IsBranch()) { 389 if (use->instruction()->IsBranch()) {
402 if (ConstrainValueAfterBranch(use, defn)) { 390 if (ConstrainValueAfterBranch(use, defn)) {
403 Value* other_value = use->instruction()->InputAt(1 - use->use_index()); 391 Value* other_value = use->instruction()->InputAt(1 - use->use_index());
404 if (!IsIntegerDefinition(other_value->definition())) { 392 if (!IsIntegerDefinition(other_value->definition())) {
405 ConstrainValueAfterBranch(other_value, other_value->definition()); 393 ConstrainValueAfterBranch(other_value, other_value->definition());
406 } 394 }
407 } 395 }
408 } else if (use->instruction()->IsCheckArrayBound()) { 396 } else if (use->instruction()->IsCheckArrayBound()) {
409 ConstrainValueAfterCheckArrayBound(use, defn); 397 ConstrainValueAfterCheckArrayBound(use, defn);
410 } 398 }
411 } 399 }
412 } 400 }
413 401
414
415 void RangeAnalysis::ConstrainValueAfterCheckArrayBound(Value* use, 402 void RangeAnalysis::ConstrainValueAfterCheckArrayBound(Value* use,
416 Definition* defn) { 403 Definition* defn) {
417 CheckArrayBoundInstr* check = use->instruction()->AsCheckArrayBound(); 404 CheckArrayBoundInstr* check = use->instruction()->AsCheckArrayBound();
418 intptr_t use_index = use->use_index(); 405 intptr_t use_index = use->use_index();
419 406
420 Range* constraint_range = NULL; 407 Range* constraint_range = NULL;
421 if (use_index == CheckArrayBoundInstr::kIndexPos) { 408 if (use_index == CheckArrayBoundInstr::kIndexPos) {
422 Definition* length = check->length()->definition(); 409 Definition* length = check->length()->definition();
423 constraint_range = new (Z) Range(RangeBoundary::FromConstant(0), 410 constraint_range = new (Z) Range(RangeBoundary::FromConstant(0),
424 RangeBoundary::FromDefinition(length, -1)); 411 RangeBoundary::FromDefinition(length, -1));
425 } else { 412 } else {
426 ASSERT(use_index == CheckArrayBoundInstr::kLengthPos); 413 ASSERT(use_index == CheckArrayBoundInstr::kLengthPos);
427 Definition* index = check->index()->definition(); 414 Definition* index = check->index()->definition();
428 constraint_range = new (Z) 415 constraint_range = new (Z)
429 Range(RangeBoundary::FromDefinition(index, 1), RangeBoundary::MaxSmi()); 416 Range(RangeBoundary::FromDefinition(index, 1), RangeBoundary::MaxSmi());
430 } 417 }
431 InsertConstraintFor(use, defn, constraint_range, check); 418 InsertConstraintFor(use, defn, constraint_range, check);
432 } 419 }
433 420
434
435 void RangeAnalysis::InsertConstraints() { 421 void RangeAnalysis::InsertConstraints() {
436 for (intptr_t i = 0; i < values_.length(); i++) { 422 for (intptr_t i = 0; i < values_.length(); i++) {
437 InsertConstraintsFor(values_[i]); 423 InsertConstraintsFor(values_[i]);
438 } 424 }
439 425
440 for (intptr_t i = 0; i < constraints_.length(); i++) { 426 for (intptr_t i = 0; i < constraints_.length(); i++) {
441 InsertConstraintsFor(constraints_[i]); 427 InsertConstraintsFor(constraints_[i]);
442 } 428 }
443 } 429 }
444 430
445
446 const Range* RangeAnalysis::GetSmiRange(Value* value) const { 431 const Range* RangeAnalysis::GetSmiRange(Value* value) const {
447 Definition* defn = value->definition(); 432 Definition* defn = value->definition();
448 const Range* range = defn->range(); 433 const Range* range = defn->range();
449 434
450 if ((range == NULL) && (defn->Type()->ToCid() != kSmiCid)) { 435 if ((range == NULL) && (defn->Type()->ToCid() != kSmiCid)) {
451 // Type propagator determined that reaching type for this use is Smi. 436 // Type propagator determined that reaching type for this use is Smi.
452 // However the definition itself is not a smi-definition and 437 // However the definition itself is not a smi-definition and
453 // thus it will never have range assigned to it. Just return the widest 438 // thus it will never have range assigned to it. Just return the widest
454 // range possible for this value. 439 // range possible for this value.
455 // We don't need to handle kMintCid here because all external mints 440 // We don't need to handle kMintCid here because all external mints
456 // (e.g. results of loads or function call) can be used only after they 441 // (e.g. results of loads or function call) can be used only after they
457 // pass through UnboxInt64Instr which is considered as mint-definition 442 // pass through UnboxInt64Instr which is considered as mint-definition
458 // and will have a range assigned to it. 443 // and will have a range assigned to it.
459 // Note: that we can't return NULL here because it is used as lattice's 444 // Note: that we can't return NULL here because it is used as lattice's
460 // bottom element to indicate that the range was not computed *yet*. 445 // bottom element to indicate that the range was not computed *yet*.
461 return &smi_range_; 446 return &smi_range_;
462 } 447 }
463 448
464 return range; 449 return range;
465 } 450 }
466 451
467
468 const Range* RangeAnalysis::GetIntRange(Value* value) const { 452 const Range* RangeAnalysis::GetIntRange(Value* value) const {
469 Definition* defn = value->definition(); 453 Definition* defn = value->definition();
470 const Range* range = defn->range(); 454 const Range* range = defn->range();
471 455
472 if ((range == NULL) && !defn->Type()->IsInt()) { 456 if ((range == NULL) && !defn->Type()->IsInt()) {
473 // Type propagator determined that reaching type for this use is int. 457 // Type propagator determined that reaching type for this use is int.
474 // However the definition itself is not a int-definition and 458 // However the definition itself is not a int-definition and
475 // thus it will never have range assigned to it. Just return the widest 459 // thus it will never have range assigned to it. Just return the widest
476 // range possible for this value. 460 // range possible for this value.
477 // It is safe to return Int64 range as this is the widest possible range 461 // It is safe to return Int64 range as this is the widest possible range
478 // supported by our unboxing operations - if this definition produces 462 // supported by our unboxing operations - if this definition produces
479 // Bigint outside of Int64 we will deoptimize whenever we actually try 463 // Bigint outside of Int64 we will deoptimize whenever we actually try
480 // to unbox it. 464 // to unbox it.
481 // Note: that we can't return NULL here because it is used as lattice's 465 // Note: that we can't return NULL here because it is used as lattice's
482 // bottom element to indicate that the range was not computed *yet*. 466 // bottom element to indicate that the range was not computed *yet*.
483 return &int64_range_; 467 return &int64_range_;
484 } 468 }
485 469
486 return range; 470 return range;
487 } 471 }
488 472
489
490 static bool AreEqualDefinitions(Definition* a, Definition* b) { 473 static bool AreEqualDefinitions(Definition* a, Definition* b) {
491 a = UnwrapConstraint(a); 474 a = UnwrapConstraint(a);
492 b = UnwrapConstraint(b); 475 b = UnwrapConstraint(b);
493 return (a == b) || 476 return (a == b) ||
494 (a->AllowsCSE() && a->Dependencies().IsNone() && b->AllowsCSE() && 477 (a->AllowsCSE() && a->Dependencies().IsNone() && b->AllowsCSE() &&
495 b->Dependencies().IsNone() && a->Equals(b)); 478 b->Dependencies().IsNone() && a->Equals(b));
496 } 479 }
497 480
498
499 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { 481 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) {
500 return a.IsSymbol() && b.IsSymbol() && 482 return a.IsSymbol() && b.IsSymbol() &&
501 AreEqualDefinitions(a.symbol(), b.symbol()); 483 AreEqualDefinitions(a.symbol(), b.symbol());
502 } 484 }
503 485
504
505 // Given the current range of a phi and a newly computed range check 486 // Given the current range of a phi and a newly computed range check
506 // if it is growing towards negative infinity, if it does widen it to 487 // if it is growing towards negative infinity, if it does widen it to
507 // MinSmi. 488 // MinSmi.
508 static RangeBoundary WidenMin(const Range* range, 489 static RangeBoundary WidenMin(const Range* range,
509 const Range* new_range, 490 const Range* new_range,
510 RangeBoundary::RangeSize size) { 491 RangeBoundary::RangeSize size) {
511 RangeBoundary min = range->min(); 492 RangeBoundary min = range->min();
512 RangeBoundary new_min = new_range->min(); 493 RangeBoundary new_min = new_range->min();
513 494
514 if (min.IsSymbol()) { 495 if (min.IsSymbol()) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 } 534 }
554 535
555 max = Range::ConstantMax(range, size); 536 max = Range::ConstantMax(range, size);
556 new_max = Range::ConstantMax(new_range, size); 537 new_max = Range::ConstantMax(new_range, size);
557 538
558 return (max.ConstantValue() >= new_max.ConstantValue()) 539 return (max.ConstantValue() >= new_max.ConstantValue())
559 ? max 540 ? max
560 : RangeBoundary::MaxConstant(size); 541 : RangeBoundary::MaxConstant(size);
561 } 542 }
562 543
563
564 // Given the current range of a phi and a newly computed range check 544 // Given the current range of a phi and a newly computed range check
565 // if we can perform narrowing: use newly computed minimum to improve precision 545 // if we can perform narrowing: use newly computed minimum to improve precision
566 // of the computed range. We do it only if current minimum was widened and is 546 // of the computed range. We do it only if current minimum was widened and is
567 // equal to MinSmi. 547 // equal to MinSmi.
568 // Newly computed minimum is expected to be greater or equal than old one as 548 // Newly computed minimum is expected to be greater or equal than old one as
569 // we are running after widening phase. 549 // we are running after widening phase.
570 static RangeBoundary NarrowMin(const Range* range, 550 static RangeBoundary NarrowMin(const Range* range,
571 const Range* new_range, 551 const Range* new_range,
572 RangeBoundary::RangeSize size) { 552 RangeBoundary::RangeSize size) {
573 const RangeBoundary min = Range::ConstantMin(range, size); 553 const RangeBoundary min = Range::ConstantMin(range, size);
574 const RangeBoundary new_min = Range::ConstantMin(new_range, size); 554 const RangeBoundary new_min = Range::ConstantMin(new_range, size);
575 if (min.ConstantValue() > new_min.ConstantValue()) return range->min(); 555 if (min.ConstantValue() > new_min.ConstantValue()) return range->min();
576 556
577 // TODO(vegorov): consider using negative infinity to indicate widened bound. 557 // TODO(vegorov): consider using negative infinity to indicate widened bound.
578 return range->min().IsMinimumOrBelow(size) ? new_range->min() : range->min(); 558 return range->min().IsMinimumOrBelow(size) ? new_range->min() : range->min();
579 } 559 }
580 560
581
582 // Given the current range of a phi and a newly computed range check 561 // Given the current range of a phi and a newly computed range check
583 // if we can perform narrowing: use newly computed maximum to improve precision 562 // if we can perform narrowing: use newly computed maximum to improve precision
584 // of the computed range. We do it only if current maximum was widened and is 563 // of the computed range. We do it only if current maximum was widened and is
585 // equal to MaxSmi. 564 // equal to MaxSmi.
586 // Newly computed maximum is expected to be less or equal than old one as 565 // Newly computed maximum is expected to be less or equal than old one as
587 // we are running after widening phase. 566 // we are running after widening phase.
588 static RangeBoundary NarrowMax(const Range* range, 567 static RangeBoundary NarrowMax(const Range* range,
589 const Range* new_range, 568 const Range* new_range,
590 RangeBoundary::RangeSize size) { 569 RangeBoundary::RangeSize size) {
591 const RangeBoundary max = Range::ConstantMax(range, size); 570 const RangeBoundary max = Range::ConstantMax(range, size);
592 const RangeBoundary new_max = Range::ConstantMax(new_range, size); 571 const RangeBoundary new_max = Range::ConstantMax(new_range, size);
593 if (max.ConstantValue() < new_max.ConstantValue()) return range->max(); 572 if (max.ConstantValue() < new_max.ConstantValue()) return range->max();
594 573
595 // TODO(vegorov): consider using positive infinity to indicate widened bound. 574 // TODO(vegorov): consider using positive infinity to indicate widened bound.
596 return range->max().IsMaximumOrAbove(size) ? new_range->max() : range->max(); 575 return range->max().IsMaximumOrAbove(size) ? new_range->max() : range->max();
597 } 576 }
598 577
599
600 char RangeAnalysis::OpPrefix(JoinOperator op) { 578 char RangeAnalysis::OpPrefix(JoinOperator op) {
601 switch (op) { 579 switch (op) {
602 case WIDEN: 580 case WIDEN:
603 return 'W'; 581 return 'W';
604 case NARROW: 582 case NARROW:
605 return 'N'; 583 return 'N';
606 case NONE: 584 case NONE:
607 return 'I'; 585 return 'I';
608 } 586 }
609 UNREACHABLE(); 587 UNREACHABLE();
610 return ' '; 588 return ' ';
611 } 589 }
612 590
613
614 static RangeBoundary::RangeSize RangeSizeForPhi(Definition* phi) { 591 static RangeBoundary::RangeSize RangeSizeForPhi(Definition* phi) {
615 ASSERT(phi->IsPhi()); 592 ASSERT(phi->IsPhi());
616 if (phi->Type()->ToCid() == kSmiCid) { 593 if (phi->Type()->ToCid() == kSmiCid) {
617 return RangeBoundary::kRangeBoundarySmi; 594 return RangeBoundary::kRangeBoundarySmi;
618 } else if (phi->representation() == kUnboxedInt32) { 595 } else if (phi->representation() == kUnboxedInt32) {
619 return RangeBoundary::kRangeBoundaryInt32; 596 return RangeBoundary::kRangeBoundaryInt32;
620 } else if (phi->Type()->IsInt()) { 597 } else if (phi->Type()->IsInt()) {
621 return RangeBoundary::kRangeBoundaryInt64; 598 return RangeBoundary::kRangeBoundaryInt64;
622 } else { 599 } else {
623 UNREACHABLE(); 600 UNREACHABLE();
624 return RangeBoundary::kRangeBoundaryInt64; 601 return RangeBoundary::kRangeBoundaryInt64;
625 } 602 }
626 } 603 }
627 604
628
629 bool RangeAnalysis::InferRange(JoinOperator op, 605 bool RangeAnalysis::InferRange(JoinOperator op,
630 Definition* defn, 606 Definition* defn,
631 intptr_t iteration) { 607 intptr_t iteration) {
632 Range range; 608 Range range;
633 defn->InferRange(this, &range); 609 defn->InferRange(this, &range);
634 610
635 if (!Range::IsUnknown(&range)) { 611 if (!Range::IsUnknown(&range)) {
636 if (!Range::IsUnknown(defn->range()) && defn->IsPhi()) { 612 if (!Range::IsUnknown(defn->range()) && defn->IsPhi()) {
637 const RangeBoundary::RangeSize size = RangeSizeForPhi(defn); 613 const RangeBoundary::RangeSize size = RangeSizeForPhi(defn);
638 if (op == WIDEN) { 614 if (op == WIDEN) {
(...skipping 14 matching lines...) Expand all
653 } 629 }
654 #endif // !PRODUCT 630 #endif // !PRODUCT
655 defn->set_range(range); 631 defn->set_range(range);
656 return true; 632 return true;
657 } 633 }
658 } 634 }
659 635
660 return false; 636 return false;
661 } 637 }
662 638
663
664 void RangeAnalysis::CollectDefinitions(BitVector* set) { 639 void RangeAnalysis::CollectDefinitions(BitVector* set) {
665 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 640 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
666 !block_it.Done(); block_it.Advance()) { 641 !block_it.Done(); block_it.Advance()) {
667 BlockEntryInstr* block = block_it.Current(); 642 BlockEntryInstr* block = block_it.Current();
668 643
669 JoinEntryInstr* join = block->AsJoinEntry(); 644 JoinEntryInstr* join = block->AsJoinEntry();
670 if (join != NULL) { 645 if (join != NULL) {
671 for (PhiIterator it(join); !it.Done(); it.Advance()) { 646 for (PhiIterator it(join); !it.Done(); it.Advance()) {
672 PhiInstr* phi = it.Current(); 647 PhiInstr* phi = it.Current();
673 if (set->Contains(phi->ssa_temp_index())) { 648 if (set->Contains(phi->ssa_temp_index())) {
674 definitions_.Add(phi); 649 definitions_.Add(phi);
675 } 650 }
676 } 651 }
677 } 652 }
678 653
679 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 654 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
680 Definition* defn = it.Current()->AsDefinition(); 655 Definition* defn = it.Current()->AsDefinition();
681 if ((defn != NULL) && defn->HasSSATemp() && 656 if ((defn != NULL) && defn->HasSSATemp() &&
682 set->Contains(defn->ssa_temp_index())) { 657 set->Contains(defn->ssa_temp_index())) {
683 definitions_.Add(defn); 658 definitions_.Add(defn);
684 } 659 }
685 } 660 }
686 } 661 }
687 } 662 }
688 663
689
690 void RangeAnalysis::Iterate(JoinOperator op, intptr_t max_iterations) { 664 void RangeAnalysis::Iterate(JoinOperator op, intptr_t max_iterations) {
691 // TODO(vegorov): switch to worklist if this becomes performance bottleneck. 665 // TODO(vegorov): switch to worklist if this becomes performance bottleneck.
692 intptr_t iteration = 0; 666 intptr_t iteration = 0;
693 bool changed; 667 bool changed;
694 do { 668 do {
695 changed = false; 669 changed = false;
696 for (intptr_t i = 0; i < definitions_.length(); i++) { 670 for (intptr_t i = 0; i < definitions_.length(); i++) {
697 Definition* defn = definitions_[i]; 671 Definition* defn = definitions_[i];
698 if (InferRange(op, defn, iteration)) { 672 if (InferRange(op, defn, iteration)) {
699 changed = true; 673 changed = true;
700 } 674 }
701 } 675 }
702 676
703 iteration++; 677 iteration++;
704 } while (changed && (iteration < max_iterations)); 678 } while (changed && (iteration < max_iterations));
705 } 679 }
706 680
707
708 void RangeAnalysis::InferRanges() { 681 void RangeAnalysis::InferRanges() {
709 if (FLAG_trace_range_analysis) { 682 if (FLAG_trace_range_analysis) {
710 FlowGraphPrinter::PrintGraph("Range Analysis (BEFORE)", flow_graph_); 683 FlowGraphPrinter::PrintGraph("Range Analysis (BEFORE)", flow_graph_);
711 } 684 }
712 Zone* zone = flow_graph_->zone(); 685 Zone* zone = flow_graph_->zone();
713 // Initialize bitvector for quick filtering of int values. 686 // Initialize bitvector for quick filtering of int values.
714 BitVector* set = 687 BitVector* set =
715 new (zone) BitVector(zone, flow_graph_->current_ssa_temp_index()); 688 new (zone) BitVector(zone, flow_graph_->current_ssa_temp_index());
716 for (intptr_t i = 0; i < values_.length(); i++) { 689 for (intptr_t i = 0; i < values_.length(); i++) {
717 set->Add(values_[i]->ssa_temp_index()); 690 set->Add(values_[i]->ssa_temp_index());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 // to phis to compute more accurate range. 727 // to phis to compute more accurate range.
755 // Narrowing only improves those boundaries that were widened up to 728 // Narrowing only improves those boundaries that were widened up to
756 // range boundary and leaves other boundaries intact. 729 // range boundary and leaves other boundaries intact.
757 Iterate(NARROW, kMaxInt32); 730 Iterate(NARROW, kMaxInt32);
758 731
759 if (FLAG_trace_range_analysis) { 732 if (FLAG_trace_range_analysis) {
760 FlowGraphPrinter::PrintGraph("Range Analysis (AFTER)", flow_graph_); 733 FlowGraphPrinter::PrintGraph("Range Analysis (AFTER)", flow_graph_);
761 } 734 }
762 } 735 }
763 736
764
765 void RangeAnalysis::AssignRangesRecursively(Definition* defn) { 737 void RangeAnalysis::AssignRangesRecursively(Definition* defn) {
766 if (!Range::IsUnknown(defn->range())) { 738 if (!Range::IsUnknown(defn->range())) {
767 return; 739 return;
768 } 740 }
769 741
770 if (!IsIntegerDefinition(defn)) { 742 if (!IsIntegerDefinition(defn)) {
771 return; 743 return;
772 } 744 }
773 745
774 for (intptr_t i = 0; i < defn->InputCount(); i++) { 746 for (intptr_t i = 0; i < defn->InputCount(); i++) {
775 Definition* input_defn = defn->InputAt(i)->definition(); 747 Definition* input_defn = defn->InputAt(i)->definition();
776 if (!input_defn->HasSSATemp() || input_defn->IsConstant()) { 748 if (!input_defn->HasSSATemp() || input_defn->IsConstant()) {
777 AssignRangesRecursively(input_defn); 749 AssignRangesRecursively(input_defn);
778 } 750 }
779 } 751 }
780 752
781 Range new_range; 753 Range new_range;
782 defn->InferRange(this, &new_range); 754 defn->InferRange(this, &new_range);
783 if (!Range::IsUnknown(&new_range)) { 755 if (!Range::IsUnknown(&new_range)) {
784 defn->set_range(new_range); 756 defn->set_range(new_range);
785 } 757 }
786 } 758 }
787 759
788
789 // Scheduler is a helper class that inserts floating control-flow less 760 // Scheduler is a helper class that inserts floating control-flow less
790 // subgraphs into the flow graph. 761 // subgraphs into the flow graph.
791 // It always attempts to schedule instructions into the loop preheader in the 762 // It always attempts to schedule instructions into the loop preheader in the
792 // way similar to LICM optimization pass. 763 // way similar to LICM optimization pass.
793 // Scheduler supports rollback - that is it keeps track of instructions it 764 // Scheduler supports rollback - that is it keeps track of instructions it
794 // schedules and can remove all instructions it inserted from the graph. 765 // schedules and can remove all instructions it inserted from the graph.
795 class Scheduler { 766 class Scheduler {
796 public: 767 public:
797 explicit Scheduler(FlowGraph* flow_graph) 768 explicit Scheduler(FlowGraph* flow_graph)
798 : flow_graph_(flow_graph), 769 : flow_graph_(flow_graph),
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 emitted_.Add(instr); 879 emitted_.Add(instr);
909 } 880 }
910 881
911 FlowGraph* flow_graph_; 882 FlowGraph* flow_graph_;
912 Map map_; 883 Map map_;
913 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers_; 884 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers_;
914 GrowableArray<BlockEntryInstr*> pre_headers_; 885 GrowableArray<BlockEntryInstr*> pre_headers_;
915 GrowableArray<Instruction*> emitted_; 886 GrowableArray<Instruction*> emitted_;
916 }; 887 };
917 888
918
919 // If bounds check 0 <= index < length is not redundant we attempt to 889 // If bounds check 0 <= index < length is not redundant we attempt to
920 // replace it with a sequence of checks that guarantee 890 // replace it with a sequence of checks that guarantee
921 // 891 //
922 // 0 <= LowerBound(index) < UpperBound(index) < length 892 // 0 <= LowerBound(index) < UpperBound(index) < length
923 // 893 //
924 // and hoist all of those checks out of the enclosing loop. 894 // and hoist all of those checks out of the enclosing loop.
925 // 895 //
926 // Upper/Lower bounds are symbolic arithmetic expressions with +, -, * 896 // Upper/Lower bounds are symbolic arithmetic expressions with +, -, *
927 // operations. 897 // operations.
928 class BoundsCheckGeneralizer { 898 class BoundsCheckGeneralizer {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 } 1045 }
1076 1046
1077 private: 1047 private:
1078 BinarySmiOpInstr* MakeBinaryOp(Token::Kind op_kind, 1048 BinarySmiOpInstr* MakeBinaryOp(Token::Kind op_kind,
1079 Definition* left, 1049 Definition* left,
1080 Definition* right) { 1050 Definition* right) {
1081 return new BinarySmiOpInstr(op_kind, new Value(left), new Value(right), 1051 return new BinarySmiOpInstr(op_kind, new Value(left), new Value(right),
1082 Thread::kNoDeoptId); 1052 Thread::kNoDeoptId);
1083 } 1053 }
1084 1054
1085
1086 BinarySmiOpInstr* MakeBinaryOp(Token::Kind op_kind, 1055 BinarySmiOpInstr* MakeBinaryOp(Token::Kind op_kind,
1087 Definition* left, 1056 Definition* left,
1088 intptr_t right) { 1057 intptr_t right) {
1089 ConstantInstr* constant_right = 1058 ConstantInstr* constant_right =
1090 flow_graph_->GetConstant(Smi::Handle(Smi::New(right))); 1059 flow_graph_->GetConstant(Smi::Handle(Smi::New(right)));
1091 return MakeBinaryOp(op_kind, left, constant_right); 1060 return MakeBinaryOp(op_kind, left, constant_right);
1092 } 1061 }
1093 1062
1094 Definition* RangeBoundaryToDefinition(const RangeBoundary& bound) { 1063 Definition* RangeBoundaryToDefinition(const RangeBoundary& bound) {
1095 Definition* symbol = UnwrapConstraint(bound.symbol()); 1064 Definition* symbol = UnwrapConstraint(bound.symbol());
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1436 f->Print(")"); 1405 f->Print(")");
1437 } else if (index_bound->IsConstant()) { 1406 } else if (index_bound->IsConstant()) {
1438 f->Print("%" Pd "", 1407 f->Print("%" Pd "",
1439 Smi::Cast(index_bound->AsConstant()->value()).Value()); 1408 Smi::Cast(index_bound->AsConstant()->value()).Value());
1440 } else { 1409 } else {
1441 f->Print("v%" Pd "", index_bound->ssa_temp_index()); 1410 f->Print("v%" Pd "", index_bound->ssa_temp_index());
1442 } 1411 }
1443 f->Print(" {%s}", Range::ToCString(index_bound->range())); 1412 f->Print(" {%s}", Range::ToCString(index_bound->range()));
1444 } 1413 }
1445 1414
1446
1447 static const char* IndexBoundToCString(Definition* index_bound) { 1415 static const char* IndexBoundToCString(Definition* index_bound) {
1448 char buffer[1024]; 1416 char buffer[1024];
1449 BufferFormatter f(buffer, sizeof(buffer)); 1417 BufferFormatter f(buffer, sizeof(buffer));
1450 PrettyPrintIndexBoundRecursively(&f, index_bound); 1418 PrettyPrintIndexBoundRecursively(&f, index_bound);
1451 return Thread::Current()->zone()->MakeCopyOfString(buffer); 1419 return Thread::Current()->zone()->MakeCopyOfString(buffer);
1452 } 1420 }
1453 #endif // !PRODUCT 1421 #endif // !PRODUCT
1454 1422
1455 RangeAnalysis* range_analysis_; 1423 RangeAnalysis* range_analysis_;
1456 FlowGraph* flow_graph_; 1424 FlowGraph* flow_graph_;
1457 Scheduler scheduler_; 1425 Scheduler scheduler_;
1458 }; 1426 };
1459 1427
1460
1461 void RangeAnalysis::EliminateRedundantBoundsChecks() { 1428 void RangeAnalysis::EliminateRedundantBoundsChecks() {
1462 if (FLAG_array_bounds_check_elimination) { 1429 if (FLAG_array_bounds_check_elimination) {
1463 const Function& function = flow_graph_->function(); 1430 const Function& function = flow_graph_->function();
1464 // Generalization only if we have not deoptimized on a generalized 1431 // Generalization only if we have not deoptimized on a generalized
1465 // check earlier, or we're compiling precompiled code (no 1432 // check earlier, or we're compiling precompiled code (no
1466 // optimistic hoisting of checks possible) 1433 // optimistic hoisting of checks possible)
1467 const bool try_generalization = 1434 const bool try_generalization =
1468 function.allows_bounds_check_generalization() && !FLAG_precompiled_mode; 1435 function.allows_bounds_check_generalization() && !FLAG_precompiled_mode;
1469 1436
1470 BoundsCheckGeneralizer generalizer(this, flow_graph_); 1437 BoundsCheckGeneralizer generalizer(this, flow_graph_);
1471 1438
1472 for (intptr_t i = 0; i < bounds_checks_.length(); i++) { 1439 for (intptr_t i = 0; i < bounds_checks_.length(); i++) {
1473 CheckArrayBoundInstr* check = bounds_checks_[i]; 1440 CheckArrayBoundInstr* check = bounds_checks_[i];
1474 RangeBoundary array_length = 1441 RangeBoundary array_length =
1475 RangeBoundary::FromDefinition(check->length()->definition()); 1442 RangeBoundary::FromDefinition(check->length()->definition());
1476 if (check->IsRedundant(array_length)) { 1443 if (check->IsRedundant(array_length)) {
1477 check->RemoveFromGraph(); 1444 check->RemoveFromGraph();
1478 } else if (try_generalization) { 1445 } else if (try_generalization) {
1479 generalizer.TryGeneralize(check, array_length); 1446 generalizer.TryGeneralize(check, array_length);
1480 } 1447 }
1481 } 1448 }
1482 1449
1483 if (FLAG_trace_range_analysis) { 1450 if (FLAG_trace_range_analysis) {
1484 FlowGraphPrinter::PrintGraph("RangeAnalysis (ABCE)", flow_graph_); 1451 FlowGraphPrinter::PrintGraph("RangeAnalysis (ABCE)", flow_graph_);
1485 } 1452 }
1486 } 1453 }
1487 } 1454 }
1488 1455
1489
1490 void RangeAnalysis::MarkUnreachableBlocks() { 1456 void RangeAnalysis::MarkUnreachableBlocks() {
1491 for (intptr_t i = 0; i < constraints_.length(); i++) { 1457 for (intptr_t i = 0; i < constraints_.length(); i++) {
1492 if (Range::IsUnknown(constraints_[i]->range())) { 1458 if (Range::IsUnknown(constraints_[i]->range())) {
1493 TargetEntryInstr* target = constraints_[i]->target(); 1459 TargetEntryInstr* target = constraints_[i]->target();
1494 if (target == NULL) { 1460 if (target == NULL) {
1495 // TODO(vegorov): replace Constraint with an uncoditional 1461 // TODO(vegorov): replace Constraint with an uncoditional
1496 // deoptimization and kill all dominated dead code. 1462 // deoptimization and kill all dominated dead code.
1497 continue; 1463 continue;
1498 } 1464 }
1499 1465
(...skipping 14 matching lines...) Expand all
1514 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) { 1480 FlowGraphPrinter::ShouldPrint(flow_graph_->function())) {
1515 THR_Print("Range analysis: False unreachable (B%" Pd ")\n", 1481 THR_Print("Range analysis: False unreachable (B%" Pd ")\n",
1516 branch->false_successor()->block_id()); 1482 branch->false_successor()->block_id());
1517 } 1483 }
1518 branch->set_constant_target(branch->true_successor()); 1484 branch->set_constant_target(branch->true_successor());
1519 } 1485 }
1520 } 1486 }
1521 } 1487 }
1522 } 1488 }
1523 1489
1524
1525 void RangeAnalysis::RemoveConstraints() { 1490 void RangeAnalysis::RemoveConstraints() {
1526 for (intptr_t i = 0; i < constraints_.length(); i++) { 1491 for (intptr_t i = 0; i < constraints_.length(); i++) {
1527 Definition* def = constraints_[i]->value()->definition(); 1492 Definition* def = constraints_[i]->value()->definition();
1528 // Some constraints might be constraining constraints. Unwind the chain of 1493 // Some constraints might be constraining constraints. Unwind the chain of
1529 // constraints until we reach the actual definition. 1494 // constraints until we reach the actual definition.
1530 while (def->IsConstraint()) { 1495 while (def->IsConstraint()) {
1531 def = def->AsConstraint()->value()->definition(); 1496 def = def->AsConstraint()->value()->definition();
1532 } 1497 }
1533 constraints_[i]->ReplaceUsesWith(def); 1498 constraints_[i]->ReplaceUsesWith(def);
1534 constraints_[i]->RemoveFromGraph(); 1499 constraints_[i]->RemoveFromGraph();
1535 } 1500 }
1536 } 1501 }
1537 1502
1538
1539 static void NarrowBinaryMintOp(BinaryMintOpInstr* mint_op) { 1503 static void NarrowBinaryMintOp(BinaryMintOpInstr* mint_op) {
1540 if (RangeUtils::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) && 1504 if (RangeUtils::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) &&
1541 RangeUtils::Fits(mint_op->left()->definition()->range(), 1505 RangeUtils::Fits(mint_op->left()->definition()->range(),
1542 RangeBoundary::kRangeBoundaryInt32) && 1506 RangeBoundary::kRangeBoundaryInt32) &&
1543 RangeUtils::Fits(mint_op->right()->definition()->range(), 1507 RangeUtils::Fits(mint_op->right()->definition()->range(),
1544 RangeBoundary::kRangeBoundaryInt32) && 1508 RangeBoundary::kRangeBoundaryInt32) &&
1545 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(), mint_op->left(), 1509 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(), mint_op->left(),
1546 mint_op->right())) { 1510 mint_op->right())) {
1547 BinaryInt32OpInstr* int32_op = new BinaryInt32OpInstr( 1511 BinaryInt32OpInstr* int32_op = new BinaryInt32OpInstr(
1548 mint_op->op_kind(), mint_op->left()->CopyWithType(), 1512 mint_op->op_kind(), mint_op->left()->CopyWithType(),
1549 mint_op->right()->CopyWithType(), mint_op->DeoptimizationTarget()); 1513 mint_op->right()->CopyWithType(), mint_op->DeoptimizationTarget());
1550 int32_op->set_range(*mint_op->range()); 1514 int32_op->set_range(*mint_op->range());
1551 int32_op->set_can_overflow(false); 1515 int32_op->set_can_overflow(false);
1552 mint_op->ReplaceWith(int32_op, NULL); 1516 mint_op->ReplaceWith(int32_op, NULL);
1553 } 1517 }
1554 } 1518 }
1555 1519
1556
1557 static void NarrowShiftMintOp(ShiftMintOpInstr* mint_op) { 1520 static void NarrowShiftMintOp(ShiftMintOpInstr* mint_op) {
1558 if (RangeUtils::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) && 1521 if (RangeUtils::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) &&
1559 RangeUtils::Fits(mint_op->left()->definition()->range(), 1522 RangeUtils::Fits(mint_op->left()->definition()->range(),
1560 RangeBoundary::kRangeBoundaryInt32) && 1523 RangeBoundary::kRangeBoundaryInt32) &&
1561 RangeUtils::Fits(mint_op->right()->definition()->range(), 1524 RangeUtils::Fits(mint_op->right()->definition()->range(),
1562 RangeBoundary::kRangeBoundaryInt32) && 1525 RangeBoundary::kRangeBoundaryInt32) &&
1563 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(), mint_op->left(), 1526 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(), mint_op->left(),
1564 mint_op->right())) { 1527 mint_op->right())) {
1565 BinaryInt32OpInstr* int32_op = new BinaryInt32OpInstr( 1528 BinaryInt32OpInstr* int32_op = new BinaryInt32OpInstr(
1566 mint_op->op_kind(), mint_op->left()->CopyWithType(), 1529 mint_op->op_kind(), mint_op->left()->CopyWithType(),
1567 mint_op->right()->CopyWithType(), mint_op->DeoptimizationTarget()); 1530 mint_op->right()->CopyWithType(), mint_op->DeoptimizationTarget());
1568 int32_op->set_range(*mint_op->range()); 1531 int32_op->set_range(*mint_op->range());
1569 int32_op->set_can_overflow(false); 1532 int32_op->set_can_overflow(false);
1570 mint_op->ReplaceWith(int32_op, NULL); 1533 mint_op->ReplaceWith(int32_op, NULL);
1571 } 1534 }
1572 } 1535 }
1573 1536
1574
1575 void RangeAnalysis::NarrowMintToInt32() { 1537 void RangeAnalysis::NarrowMintToInt32() {
1576 for (intptr_t i = 0; i < binary_mint_ops_.length(); i++) { 1538 for (intptr_t i = 0; i < binary_mint_ops_.length(); i++) {
1577 NarrowBinaryMintOp(binary_mint_ops_[i]); 1539 NarrowBinaryMintOp(binary_mint_ops_[i]);
1578 } 1540 }
1579 1541
1580 for (intptr_t i = 0; i < shift_mint_ops_.length(); i++) { 1542 for (intptr_t i = 0; i < shift_mint_ops_.length(); i++) {
1581 NarrowShiftMintOp(shift_mint_ops_[i]); 1543 NarrowShiftMintOp(shift_mint_ops_[i]);
1582 } 1544 }
1583 } 1545 }
1584 1546
1585
1586 IntegerInstructionSelector::IntegerInstructionSelector(FlowGraph* flow_graph) 1547 IntegerInstructionSelector::IntegerInstructionSelector(FlowGraph* flow_graph)
1587 : flow_graph_(flow_graph) { 1548 : flow_graph_(flow_graph) {
1588 ASSERT(flow_graph_ != NULL); 1549 ASSERT(flow_graph_ != NULL);
1589 zone_ = flow_graph_->zone(); 1550 zone_ = flow_graph_->zone();
1590 selected_uint32_defs_ = 1551 selected_uint32_defs_ =
1591 new (zone_) BitVector(zone_, flow_graph_->current_ssa_temp_index()); 1552 new (zone_) BitVector(zone_, flow_graph_->current_ssa_temp_index());
1592 } 1553 }
1593 1554
1594
1595 void IntegerInstructionSelector::Select() { 1555 void IntegerInstructionSelector::Select() {
1596 if (FLAG_trace_integer_ir_selection) { 1556 if (FLAG_trace_integer_ir_selection) {
1597 THR_Print("---- starting integer ir selection -------\n"); 1557 THR_Print("---- starting integer ir selection -------\n");
1598 } 1558 }
1599 FindPotentialUint32Definitions(); 1559 FindPotentialUint32Definitions();
1600 FindUint32NarrowingDefinitions(); 1560 FindUint32NarrowingDefinitions();
1601 Propagate(); 1561 Propagate();
1602 ReplaceInstructions(); 1562 ReplaceInstructions();
1603 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) { 1563 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) {
1604 THR_Print("---- after integer ir selection -------\n"); 1564 THR_Print("---- after integer ir selection -------\n");
1605 FlowGraphPrinter printer(*flow_graph_); 1565 FlowGraphPrinter printer(*flow_graph_);
1606 printer.PrintBlocks(); 1566 printer.PrintBlocks();
1607 } 1567 }
1608 } 1568 }
1609 1569
1610
1611 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) { 1570 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) {
1612 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging 1571 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging
1613 // & untagged of intermediate results. 1572 // & untagged of intermediate results.
1614 // TODO(johnmccutchan): Consider phis. 1573 // TODO(johnmccutchan): Consider phis.
1615 return def->IsBoxInt64() || def->IsUnboxInt64() || def->IsBinaryMintOp() || 1574 return def->IsBoxInt64() || def->IsUnboxInt64() || def->IsBinaryMintOp() ||
1616 def->IsShiftMintOp() || def->IsUnaryMintOp(); 1575 def->IsShiftMintOp() || def->IsUnaryMintOp();
1617 } 1576 }
1618 1577
1619
1620 void IntegerInstructionSelector::FindPotentialUint32Definitions() { 1578 void IntegerInstructionSelector::FindPotentialUint32Definitions() {
1621 if (FLAG_trace_integer_ir_selection) { 1579 if (FLAG_trace_integer_ir_selection) {
1622 THR_Print("++++ Finding potential Uint32 definitions:\n"); 1580 THR_Print("++++ Finding potential Uint32 definitions:\n");
1623 } 1581 }
1624 1582
1625 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 1583 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
1626 !block_it.Done(); block_it.Advance()) { 1584 !block_it.Done(); block_it.Advance()) {
1627 BlockEntryInstr* block = block_it.Current(); 1585 BlockEntryInstr* block = block_it.Current();
1628 1586
1629 for (ForwardInstructionIterator instr_it(block); !instr_it.Done(); 1587 for (ForwardInstructionIterator instr_it(block); !instr_it.Done();
1630 instr_it.Advance()) { 1588 instr_it.Advance()) {
1631 Instruction* current = instr_it.Current(); 1589 Instruction* current = instr_it.Current();
1632 Definition* defn = current->AsDefinition(); 1590 Definition* defn = current->AsDefinition();
1633 if ((defn != NULL) && defn->HasSSATemp()) { 1591 if ((defn != NULL) && defn->HasSSATemp()) {
1634 if (IsPotentialUint32Definition(defn)) { 1592 if (IsPotentialUint32Definition(defn)) {
1635 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) { 1593 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) {
1636 THR_Print("Adding %s\n", current->ToCString()); 1594 THR_Print("Adding %s\n", current->ToCString());
1637 } 1595 }
1638 potential_uint32_defs_.Add(defn); 1596 potential_uint32_defs_.Add(defn);
1639 } 1597 }
1640 } 1598 }
1641 } 1599 }
1642 } 1600 }
1643 } 1601 }
1644 1602
1645
1646 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the 1603 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the
1647 // value into a Uint32 range. 1604 // value into a Uint32 range.
1648 bool IntegerInstructionSelector::IsUint32NarrowingDefinition(Definition* def) { 1605 bool IntegerInstructionSelector::IsUint32NarrowingDefinition(Definition* def) {
1649 if (def->IsBinaryMintOp()) { 1606 if (def->IsBinaryMintOp()) {
1650 BinaryMintOpInstr* op = def->AsBinaryMintOp(); 1607 BinaryMintOpInstr* op = def->AsBinaryMintOp();
1651 // Must be a mask operation. 1608 // Must be a mask operation.
1652 if (op->op_kind() != Token::kBIT_AND) { 1609 if (op->op_kind() != Token::kBIT_AND) {
1653 return false; 1610 return false;
1654 } 1611 }
1655 Range* range = op->range(); 1612 Range* range = op->range();
1656 if ((range == NULL) || 1613 if ((range == NULL) ||
1657 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { 1614 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) {
1658 return false; 1615 return false;
1659 } 1616 }
1660 return true; 1617 return true;
1661 } 1618 }
1662 // TODO(johnmccutchan): Add typed array stores. 1619 // TODO(johnmccutchan): Add typed array stores.
1663 return false; 1620 return false;
1664 } 1621 }
1665 1622
1666
1667 void IntegerInstructionSelector::FindUint32NarrowingDefinitions() { 1623 void IntegerInstructionSelector::FindUint32NarrowingDefinitions() {
1668 ASSERT(selected_uint32_defs_ != NULL); 1624 ASSERT(selected_uint32_defs_ != NULL);
1669 if (FLAG_trace_integer_ir_selection) { 1625 if (FLAG_trace_integer_ir_selection) {
1670 THR_Print("++++ Selecting Uint32 definitions:\n"); 1626 THR_Print("++++ Selecting Uint32 definitions:\n");
1671 THR_Print("++++ Initial set:\n"); 1627 THR_Print("++++ Initial set:\n");
1672 } 1628 }
1673 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { 1629 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
1674 Definition* defn = potential_uint32_defs_[i]; 1630 Definition* defn = potential_uint32_defs_[i];
1675 if (IsUint32NarrowingDefinition(defn)) { 1631 if (IsUint32NarrowingDefinition(defn)) {
1676 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) { 1632 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) {
1677 THR_Print("Adding %s\n", defn->ToCString()); 1633 THR_Print("Adding %s\n", defn->ToCString());
1678 } 1634 }
1679 selected_uint32_defs_->Add(defn->ssa_temp_index()); 1635 selected_uint32_defs_->Add(defn->ssa_temp_index());
1680 } 1636 }
1681 } 1637 }
1682 } 1638 }
1683 1639
1684
1685 bool IntegerInstructionSelector::AllUsesAreUint32Narrowing(Value* list_head) { 1640 bool IntegerInstructionSelector::AllUsesAreUint32Narrowing(Value* list_head) {
1686 for (Value::Iterator it(list_head); !it.Done(); it.Advance()) { 1641 for (Value::Iterator it(list_head); !it.Done(); it.Advance()) {
1687 Value* use = it.Current(); 1642 Value* use = it.Current();
1688 Definition* defn = use->instruction()->AsDefinition(); 1643 Definition* defn = use->instruction()->AsDefinition();
1689 if ((defn == NULL) || !defn->HasSSATemp() || 1644 if ((defn == NULL) || !defn->HasSSATemp() ||
1690 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) { 1645 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
1691 return false; 1646 return false;
1692 } 1647 }
1693 } 1648 }
1694 return true; 1649 return true;
1695 } 1650 }
1696 1651
1697
1698 bool IntegerInstructionSelector::CanBecomeUint32(Definition* def) { 1652 bool IntegerInstructionSelector::CanBecomeUint32(Definition* def) {
1699 ASSERT(IsPotentialUint32Definition(def)); 1653 ASSERT(IsPotentialUint32Definition(def));
1700 if (def->IsBoxInt64()) { 1654 if (def->IsBoxInt64()) {
1701 // If a BoxInt64's input is a candidate, the box is a candidate. 1655 // If a BoxInt64's input is a candidate, the box is a candidate.
1702 Definition* box_input = def->AsBoxInt64()->value()->definition(); 1656 Definition* box_input = def->AsBoxInt64()->value()->definition();
1703 return selected_uint32_defs_->Contains(box_input->ssa_temp_index()); 1657 return selected_uint32_defs_->Contains(box_input->ssa_temp_index());
1704 } 1658 }
1705 // A right shift with an input outside of Uint32 range cannot be converted 1659 // A right shift with an input outside of Uint32 range cannot be converted
1706 // because we need the high bits. 1660 // because we need the high bits.
1707 if (def->IsShiftMintOp()) { 1661 if (def->IsShiftMintOp()) {
1708 ShiftMintOpInstr* op = def->AsShiftMintOp(); 1662 ShiftMintOpInstr* op = def->AsShiftMintOp();
1709 if (op->op_kind() == Token::kSHR) { 1663 if (op->op_kind() == Token::kSHR) {
1710 Definition* shift_input = op->left()->definition(); 1664 Definition* shift_input = op->left()->definition();
1711 ASSERT(shift_input != NULL); 1665 ASSERT(shift_input != NULL);
1712 Range* range = shift_input->range(); 1666 Range* range = shift_input->range();
1713 if ((range == NULL) || 1667 if ((range == NULL) ||
1714 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { 1668 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) {
1715 return false; 1669 return false;
1716 } 1670 }
1717 } 1671 }
1718 } 1672 }
1719 if (!def->HasUses()) { 1673 if (!def->HasUses()) {
1720 // No uses, skip. 1674 // No uses, skip.
1721 return false; 1675 return false;
1722 } 1676 }
1723 return AllUsesAreUint32Narrowing(def->input_use_list()) && 1677 return AllUsesAreUint32Narrowing(def->input_use_list()) &&
1724 AllUsesAreUint32Narrowing(def->env_use_list()); 1678 AllUsesAreUint32Narrowing(def->env_use_list());
1725 } 1679 }
1726 1680
1727
1728 void IntegerInstructionSelector::Propagate() { 1681 void IntegerInstructionSelector::Propagate() {
1729 ASSERT(selected_uint32_defs_ != NULL); 1682 ASSERT(selected_uint32_defs_ != NULL);
1730 bool changed = true; 1683 bool changed = true;
1731 intptr_t iteration = 0; 1684 intptr_t iteration = 0;
1732 while (changed) { 1685 while (changed) {
1733 if (FLAG_trace_integer_ir_selection) { 1686 if (FLAG_trace_integer_ir_selection) {
1734 THR_Print("+++ Iteration: %" Pd "\n", iteration++); 1687 THR_Print("+++ Iteration: %" Pd "\n", iteration++);
1735 } 1688 }
1736 changed = false; 1689 changed = false;
1737 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { 1690 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
(...skipping 15 matching lines...) Expand all
1753 // Haven't reached fixed point yet. 1706 // Haven't reached fixed point yet.
1754 changed = true; 1707 changed = true;
1755 } 1708 }
1756 } 1709 }
1757 } 1710 }
1758 if (FLAG_trace_integer_ir_selection) { 1711 if (FLAG_trace_integer_ir_selection) {
1759 THR_Print("Reached fixed point\n"); 1712 THR_Print("Reached fixed point\n");
1760 } 1713 }
1761 } 1714 }
1762 1715
1763
1764 Definition* IntegerInstructionSelector::ConstructReplacementFor( 1716 Definition* IntegerInstructionSelector::ConstructReplacementFor(
1765 Definition* def) { 1717 Definition* def) {
1766 // Should only see mint definitions. 1718 // Should only see mint definitions.
1767 ASSERT(IsPotentialUint32Definition(def)); 1719 ASSERT(IsPotentialUint32Definition(def));
1768 // Should not see constant instructions. 1720 // Should not see constant instructions.
1769 ASSERT(!def->IsConstant()); 1721 ASSERT(!def->IsConstant());
1770 if (def->IsBinaryMintOp()) { 1722 if (def->IsBinaryMintOp()) {
1771 BinaryMintOpInstr* op = def->AsBinaryMintOp(); 1723 BinaryMintOpInstr* op = def->AsBinaryMintOp();
1772 Token::Kind op_kind = op->op_kind(); 1724 Token::Kind op_kind = op->op_kind();
1773 Value* left = op->left()->CopyWithType(); 1725 Value* left = op->left()->CopyWithType();
(...skipping 19 matching lines...) Expand all
1793 Token::Kind op_kind = op->op_kind(); 1745 Token::Kind op_kind = op->op_kind();
1794 Value* left = op->left()->CopyWithType(); 1746 Value* left = op->left()->CopyWithType();
1795 Value* right = op->right()->CopyWithType(); 1747 Value* right = op->right()->CopyWithType();
1796 intptr_t deopt_id = op->DeoptimizationTarget(); 1748 intptr_t deopt_id = op->DeoptimizationTarget();
1797 return new (Z) ShiftUint32OpInstr(op_kind, left, right, deopt_id); 1749 return new (Z) ShiftUint32OpInstr(op_kind, left, right, deopt_id);
1798 } 1750 }
1799 UNREACHABLE(); 1751 UNREACHABLE();
1800 return NULL; 1752 return NULL;
1801 } 1753 }
1802 1754
1803
1804 void IntegerInstructionSelector::ReplaceInstructions() { 1755 void IntegerInstructionSelector::ReplaceInstructions() {
1805 if (FLAG_trace_integer_ir_selection) { 1756 if (FLAG_trace_integer_ir_selection) {
1806 THR_Print("++++ Replacing instructions:\n"); 1757 THR_Print("++++ Replacing instructions:\n");
1807 } 1758 }
1808 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { 1759 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) {
1809 Definition* defn = potential_uint32_defs_[i]; 1760 Definition* defn = potential_uint32_defs_[i];
1810 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { 1761 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
1811 // Not a candidate. 1762 // Not a candidate.
1812 continue; 1763 continue;
1813 } 1764 }
1814 Definition* replacement = ConstructReplacementFor(defn); 1765 Definition* replacement = ConstructReplacementFor(defn);
1815 ASSERT(replacement != NULL); 1766 ASSERT(replacement != NULL);
1816 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) { 1767 if (FLAG_support_il_printer && FLAG_trace_integer_ir_selection) {
1817 THR_Print("Replacing %s with %s\n", defn->ToCString(), 1768 THR_Print("Replacing %s with %s\n", defn->ToCString(),
1818 replacement->ToCString()); 1769 replacement->ToCString());
1819 } 1770 }
1820 if (!Range::IsUnknown(defn->range())) { 1771 if (!Range::IsUnknown(defn->range())) {
1821 replacement->set_range(*defn->range()); 1772 replacement->set_range(*defn->range());
1822 } 1773 }
1823 defn->ReplaceWith(replacement, NULL); 1774 defn->ReplaceWith(replacement, NULL);
1824 ASSERT(flow_graph_->VerifyUseLists()); 1775 ASSERT(flow_graph_->VerifyUseLists());
1825 } 1776 }
1826 } 1777 }
1827 1778
1828
1829 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) { 1779 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) {
1830 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { 1780 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) {
1831 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); 1781 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs);
1832 } 1782 }
1833 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); 1783 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs);
1834 } 1784 }
1835 1785
1836
1837 RangeBoundary RangeBoundary::LowerBound() const { 1786 RangeBoundary RangeBoundary::LowerBound() const {
1838 if (IsInfinity()) { 1787 if (IsInfinity()) {
1839 return NegativeInfinity(); 1788 return NegativeInfinity();
1840 } 1789 }
1841 if (IsConstant()) return *this; 1790 if (IsConstant()) return *this;
1842 return Add(Range::ConstantMinSmi(symbol()->range()), 1791 return Add(Range::ConstantMinSmi(symbol()->range()),
1843 RangeBoundary::FromConstant(offset_), NegativeInfinity()); 1792 RangeBoundary::FromConstant(offset_), NegativeInfinity());
1844 } 1793 }
1845 1794
1846
1847 RangeBoundary RangeBoundary::UpperBound() const { 1795 RangeBoundary RangeBoundary::UpperBound() const {
1848 if (IsInfinity()) { 1796 if (IsInfinity()) {
1849 return PositiveInfinity(); 1797 return PositiveInfinity();
1850 } 1798 }
1851 if (IsConstant()) return *this; 1799 if (IsConstant()) return *this;
1852 1800
1853 return Add(Range::ConstantMaxSmi(symbol()->range()), 1801 return Add(Range::ConstantMaxSmi(symbol()->range()),
1854 RangeBoundary::FromConstant(offset_), PositiveInfinity()); 1802 RangeBoundary::FromConstant(offset_), PositiveInfinity());
1855 } 1803 }
1856 1804
1857
1858 RangeBoundary RangeBoundary::Add(const RangeBoundary& a, 1805 RangeBoundary RangeBoundary::Add(const RangeBoundary& a,
1859 const RangeBoundary& b, 1806 const RangeBoundary& b,
1860 const RangeBoundary& overflow) { 1807 const RangeBoundary& overflow) {
1861 if (a.IsInfinity() || b.IsInfinity()) return overflow; 1808 if (a.IsInfinity() || b.IsInfinity()) return overflow;
1862 1809
1863 ASSERT(a.IsConstant() && b.IsConstant()); 1810 ASSERT(a.IsConstant() && b.IsConstant());
1864 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) { 1811 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) {
1865 return overflow; 1812 return overflow;
1866 } 1813 }
1867 1814
1868 int64_t result = a.ConstantValue() + b.ConstantValue(); 1815 int64_t result = a.ConstantValue() + b.ConstantValue();
1869 1816
1870 return RangeBoundary::FromConstant(result); 1817 return RangeBoundary::FromConstant(result);
1871 } 1818 }
1872 1819
1873
1874 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a, 1820 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a,
1875 const RangeBoundary& b, 1821 const RangeBoundary& b,
1876 const RangeBoundary& overflow) { 1822 const RangeBoundary& overflow) {
1877 if (a.IsInfinity() || b.IsInfinity()) return overflow; 1823 if (a.IsInfinity() || b.IsInfinity()) return overflow;
1878 ASSERT(a.IsConstant() && b.IsConstant()); 1824 ASSERT(a.IsConstant() && b.IsConstant());
1879 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) { 1825 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) {
1880 return overflow; 1826 return overflow;
1881 } 1827 }
1882 1828
1883 int64_t result = a.ConstantValue() - b.ConstantValue(); 1829 int64_t result = a.ConstantValue() - b.ConstantValue();
1884 1830
1885 return RangeBoundary::FromConstant(result); 1831 return RangeBoundary::FromConstant(result);
1886 } 1832 }
1887 1833
1888
1889 bool RangeBoundary::SymbolicAdd(const RangeBoundary& a, 1834 bool RangeBoundary::SymbolicAdd(const RangeBoundary& a,
1890 const RangeBoundary& b, 1835 const RangeBoundary& b,
1891 RangeBoundary* result) { 1836 RangeBoundary* result) {
1892 if (a.IsSymbol() && b.IsConstant()) { 1837 if (a.IsSymbol() && b.IsConstant()) {
1893 if (Utils::WillAddOverflow(a.offset(), b.ConstantValue())) { 1838 if (Utils::WillAddOverflow(a.offset(), b.ConstantValue())) {
1894 return false; 1839 return false;
1895 } 1840 }
1896 1841
1897 const int64_t offset = a.offset() + b.ConstantValue(); 1842 const int64_t offset = a.offset() + b.ConstantValue();
1898 1843
1899 *result = RangeBoundary::FromDefinition(a.symbol(), offset); 1844 *result = RangeBoundary::FromDefinition(a.symbol(), offset);
1900 return true; 1845 return true;
1901 } else if (b.IsSymbol() && a.IsConstant()) { 1846 } else if (b.IsSymbol() && a.IsConstant()) {
1902 return SymbolicAdd(b, a, result); 1847 return SymbolicAdd(b, a, result);
1903 } 1848 }
1904 return false; 1849 return false;
1905 } 1850 }
1906 1851
1907
1908 bool RangeBoundary::SymbolicSub(const RangeBoundary& a, 1852 bool RangeBoundary::SymbolicSub(const RangeBoundary& a,
1909 const RangeBoundary& b, 1853 const RangeBoundary& b,
1910 RangeBoundary* result) { 1854 RangeBoundary* result) {
1911 if (a.IsSymbol() && b.IsConstant()) { 1855 if (a.IsSymbol() && b.IsConstant()) {
1912 if (Utils::WillSubOverflow(a.offset(), b.ConstantValue())) { 1856 if (Utils::WillSubOverflow(a.offset(), b.ConstantValue())) {
1913 return false; 1857 return false;
1914 } 1858 }
1915 1859
1916 const int64_t offset = a.offset() - b.ConstantValue(); 1860 const int64_t offset = a.offset() - b.ConstantValue();
1917 1861
1918 *result = RangeBoundary::FromDefinition(a.symbol(), offset); 1862 *result = RangeBoundary::FromDefinition(a.symbol(), offset);
1919 return true; 1863 return true;
1920 } 1864 }
1921 return false; 1865 return false;
1922 } 1866 }
1923 1867
1924
1925 bool RangeBoundary::Equals(const RangeBoundary& other) const { 1868 bool RangeBoundary::Equals(const RangeBoundary& other) const {
1926 if (IsConstant() && other.IsConstant()) { 1869 if (IsConstant() && other.IsConstant()) {
1927 return ConstantValue() == other.ConstantValue(); 1870 return ConstantValue() == other.ConstantValue();
1928 } else if (IsInfinity() && other.IsInfinity()) { 1871 } else if (IsInfinity() && other.IsInfinity()) {
1929 return kind() == other.kind(); 1872 return kind() == other.kind();
1930 } else if (IsSymbol() && other.IsSymbol()) { 1873 } else if (IsSymbol() && other.IsSymbol()) {
1931 return (offset() == other.offset()) && DependOnSameSymbol(*this, other); 1874 return (offset() == other.offset()) && DependOnSameSymbol(*this, other);
1932 } else if (IsUnknown() && other.IsUnknown()) { 1875 } else if (IsUnknown() && other.IsUnknown()) {
1933 return true; 1876 return true;
1934 } 1877 }
1935 return false; 1878 return false;
1936 } 1879 }
1937 1880
1938
1939 RangeBoundary RangeBoundary::Shl(const RangeBoundary& value_boundary, 1881 RangeBoundary RangeBoundary::Shl(const RangeBoundary& value_boundary,
1940 int64_t shift_count, 1882 int64_t shift_count,
1941 const RangeBoundary& overflow) { 1883 const RangeBoundary& overflow) {
1942 ASSERT(value_boundary.IsConstant()); 1884 ASSERT(value_boundary.IsConstant());
1943 ASSERT(shift_count >= 0); 1885 ASSERT(shift_count >= 0);
1944 int64_t limit = 64 - shift_count; 1886 int64_t limit = 64 - shift_count;
1945 int64_t value = value_boundary.ConstantValue(); 1887 int64_t value = value_boundary.ConstantValue();
1946 1888
1947 if ((value == 0) || (shift_count == 0) || 1889 if ((value == 0) || (shift_count == 0) ||
1948 ((limit > 0) && Utils::IsInt(static_cast<int>(limit), value))) { 1890 ((limit > 0) && Utils::IsInt(static_cast<int>(limit), value))) {
1949 // Result stays in 64 bit range. 1891 // Result stays in 64 bit range.
1950 int64_t result = value << shift_count; 1892 int64_t result = value << shift_count;
1951 return RangeBoundary(result); 1893 return RangeBoundary(result);
1952 } 1894 }
1953 1895
1954 return overflow; 1896 return overflow;
1955 } 1897 }
1956 1898
1957
1958 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, 1899 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a,
1959 const RangeBoundary& overflow) { 1900 const RangeBoundary& overflow) {
1960 if (a.IsConstant() || a.IsInfinity()) { 1901 if (a.IsConstant() || a.IsInfinity()) {
1961 return a; 1902 return a;
1962 } 1903 }
1963 1904
1964 int64_t offset = a.offset(); 1905 int64_t offset = a.offset();
1965 Definition* symbol = a.symbol(); 1906 Definition* symbol = a.symbol();
1966 1907
1967 bool changed; 1908 bool changed;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 1950
2010 default: 1951 default:
2011 break; 1952 break;
2012 } 1953 }
2013 } 1954 }
2014 } while (changed); 1955 } while (changed);
2015 1956
2016 return RangeBoundary::FromDefinition(symbol, offset); 1957 return RangeBoundary::FromDefinition(symbol, offset);
2017 } 1958 }
2018 1959
2019
2020 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { 1960 static bool CanonicalizeMaxBoundary(RangeBoundary* a) {
2021 if (!a->IsSymbol()) return false; 1961 if (!a->IsSymbol()) return false;
2022 1962
2023 Range* range = a->symbol()->range(); 1963 Range* range = a->symbol()->range();
2024 if ((range == NULL) || !range->max().IsSymbol()) return false; 1964 if ((range == NULL) || !range->max().IsSymbol()) return false;
2025 1965
2026
2027 if (Utils::WillAddOverflow(range->max().offset(), a->offset())) { 1966 if (Utils::WillAddOverflow(range->max().offset(), a->offset())) {
2028 *a = RangeBoundary::PositiveInfinity(); 1967 *a = RangeBoundary::PositiveInfinity();
2029 return true; 1968 return true;
2030 } 1969 }
2031 1970
2032 const int64_t offset = range->max().offset() + a->offset(); 1971 const int64_t offset = range->max().offset() + a->offset();
2033 1972
2034 *a = CanonicalizeBoundary( 1973 *a = CanonicalizeBoundary(
2035 RangeBoundary::FromDefinition(range->max().symbol(), offset), 1974 RangeBoundary::FromDefinition(range->max().symbol(), offset),
2036 RangeBoundary::PositiveInfinity()); 1975 RangeBoundary::PositiveInfinity());
2037 1976
2038 return true; 1977 return true;
2039 } 1978 }
2040 1979
2041
2042 static bool CanonicalizeMinBoundary(RangeBoundary* a) { 1980 static bool CanonicalizeMinBoundary(RangeBoundary* a) {
2043 if (!a->IsSymbol()) return false; 1981 if (!a->IsSymbol()) return false;
2044 1982
2045 Range* range = a->symbol()->range(); 1983 Range* range = a->symbol()->range();
2046 if ((range == NULL) || !range->min().IsSymbol()) return false; 1984 if ((range == NULL) || !range->min().IsSymbol()) return false;
2047 1985
2048 if (Utils::WillAddOverflow(range->min().offset(), a->offset())) { 1986 if (Utils::WillAddOverflow(range->min().offset(), a->offset())) {
2049 *a = RangeBoundary::NegativeInfinity(); 1987 *a = RangeBoundary::NegativeInfinity();
2050 return true; 1988 return true;
2051 } 1989 }
(...skipping 24 matching lines...) Expand all
2076 if (DependOnSameSymbol(canonical_a, canonical_b)) { 2014 if (DependOnSameSymbol(canonical_a, canonical_b)) {
2077 *a = canonical_a; 2015 *a = canonical_a;
2078 *b = canonical_b; 2016 *b = canonical_b;
2079 return true; 2017 return true;
2080 } 2018 }
2081 } while (op(&canonical_a) || op(&canonical_b)); 2019 } while (op(&canonical_a) || op(&canonical_b));
2082 2020
2083 return false; 2021 return false;
2084 } 2022 }
2085 2023
2086
2087 RangeBoundary RangeBoundary::JoinMin(RangeBoundary a, 2024 RangeBoundary RangeBoundary::JoinMin(RangeBoundary a,
2088 RangeBoundary b, 2025 RangeBoundary b,
2089 RangeBoundary::RangeSize size) { 2026 RangeBoundary::RangeSize size) {
2090 if (a.Equals(b)) { 2027 if (a.Equals(b)) {
2091 return b; 2028 return b;
2092 } 2029 }
2093 2030
2094 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMinBoundary, 2031 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMinBoundary,
2095 RangeBoundary::NegativeInfinity())) { 2032 RangeBoundary::NegativeInfinity())) {
2096 return (a.offset() <= b.offset()) ? a : b; 2033 return (a.offset() <= b.offset()) ? a : b;
2097 } 2034 }
2098 2035
2099 const int64_t inf_a = a.LowerBound(size); 2036 const int64_t inf_a = a.LowerBound(size);
2100 const int64_t inf_b = b.LowerBound(size); 2037 const int64_t inf_b = b.LowerBound(size);
2101 const int64_t sup_a = a.UpperBound(size); 2038 const int64_t sup_a = a.UpperBound(size);
2102 const int64_t sup_b = b.UpperBound(size); 2039 const int64_t sup_b = b.UpperBound(size);
2103 2040
2104 if ((sup_a <= inf_b) && !a.LowerBound().Overflowed(size)) { 2041 if ((sup_a <= inf_b) && !a.LowerBound().Overflowed(size)) {
2105 return a; 2042 return a;
2106 } else if ((sup_b <= inf_a) && !b.LowerBound().Overflowed(size)) { 2043 } else if ((sup_b <= inf_a) && !b.LowerBound().Overflowed(size)) {
2107 return b; 2044 return b;
2108 } else { 2045 } else {
2109 return RangeBoundary::FromConstant(Utils::Minimum(inf_a, inf_b)); 2046 return RangeBoundary::FromConstant(Utils::Minimum(inf_a, inf_b));
2110 } 2047 }
2111 } 2048 }
2112 2049
2113
2114 RangeBoundary RangeBoundary::JoinMax(RangeBoundary a, 2050 RangeBoundary RangeBoundary::JoinMax(RangeBoundary a,
2115 RangeBoundary b, 2051 RangeBoundary b,
2116 RangeBoundary::RangeSize size) { 2052 RangeBoundary::RangeSize size) {
2117 if (a.Equals(b)) { 2053 if (a.Equals(b)) {
2118 return b; 2054 return b;
2119 } 2055 }
2120 2056
2121 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMaxBoundary, 2057 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMaxBoundary,
2122 RangeBoundary::PositiveInfinity())) { 2058 RangeBoundary::PositiveInfinity())) {
2123 return (a.offset() >= b.offset()) ? a : b; 2059 return (a.offset() >= b.offset()) ? a : b;
2124 } 2060 }
2125 2061
2126 const int64_t inf_a = a.LowerBound(size); 2062 const int64_t inf_a = a.LowerBound(size);
2127 const int64_t inf_b = b.LowerBound(size); 2063 const int64_t inf_b = b.LowerBound(size);
2128 const int64_t sup_a = a.UpperBound(size); 2064 const int64_t sup_a = a.UpperBound(size);
2129 const int64_t sup_b = b.UpperBound(size); 2065 const int64_t sup_b = b.UpperBound(size);
2130 2066
2131 if ((sup_a <= inf_b) && !b.UpperBound().Overflowed(size)) { 2067 if ((sup_a <= inf_b) && !b.UpperBound().Overflowed(size)) {
2132 return b; 2068 return b;
2133 } else if ((sup_b <= inf_a) && !a.UpperBound().Overflowed(size)) { 2069 } else if ((sup_b <= inf_a) && !a.UpperBound().Overflowed(size)) {
2134 return a; 2070 return a;
2135 } else { 2071 } else {
2136 return RangeBoundary::FromConstant(Utils::Maximum(sup_a, sup_b)); 2072 return RangeBoundary::FromConstant(Utils::Maximum(sup_a, sup_b));
2137 } 2073 }
2138 } 2074 }
2139 2075
2140
2141 RangeBoundary RangeBoundary::IntersectionMin(RangeBoundary a, RangeBoundary b) { 2076 RangeBoundary RangeBoundary::IntersectionMin(RangeBoundary a, RangeBoundary b) {
2142 ASSERT(!a.IsPositiveInfinity() && !b.IsPositiveInfinity()); 2077 ASSERT(!a.IsPositiveInfinity() && !b.IsPositiveInfinity());
2143 ASSERT(!a.IsUnknown() && !b.IsUnknown()); 2078 ASSERT(!a.IsUnknown() && !b.IsUnknown());
2144 2079
2145 if (a.Equals(b)) { 2080 if (a.Equals(b)) {
2146 return a; 2081 return a;
2147 } 2082 }
2148 2083
2149 if (a.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) { 2084 if (a.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) {
2150 return b; 2085 return b;
2151 } else if (b.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) { 2086 } else if (b.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) {
2152 return a; 2087 return a;
2153 } 2088 }
2154 2089
2155 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMinBoundary, 2090 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMinBoundary,
2156 RangeBoundary::NegativeInfinity())) { 2091 RangeBoundary::NegativeInfinity())) {
2157 return (a.offset() >= b.offset()) ? a : b; 2092 return (a.offset() >= b.offset()) ? a : b;
2158 } 2093 }
2159 2094
2160 const int64_t inf_a = a.SmiLowerBound(); 2095 const int64_t inf_a = a.SmiLowerBound();
2161 const int64_t inf_b = b.SmiLowerBound(); 2096 const int64_t inf_b = b.SmiLowerBound();
2162 2097
2163 return (inf_a >= inf_b) ? a : b; 2098 return (inf_a >= inf_b) ? a : b;
2164 } 2099 }
2165 2100
2166
2167 RangeBoundary RangeBoundary::IntersectionMax(RangeBoundary a, RangeBoundary b) { 2101 RangeBoundary RangeBoundary::IntersectionMax(RangeBoundary a, RangeBoundary b) {
2168 ASSERT(!a.IsNegativeInfinity() && !b.IsNegativeInfinity()); 2102 ASSERT(!a.IsNegativeInfinity() && !b.IsNegativeInfinity());
2169 ASSERT(!a.IsUnknown() && !b.IsUnknown()); 2103 ASSERT(!a.IsUnknown() && !b.IsUnknown());
2170 2104
2171 if (a.Equals(b)) { 2105 if (a.Equals(b)) {
2172 return a; 2106 return a;
2173 } 2107 }
2174 2108
2175 if (a.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) { 2109 if (a.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) {
2176 return b; 2110 return b;
2177 } else if (b.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) { 2111 } else if (b.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) {
2178 return a; 2112 return a;
2179 } 2113 }
2180 2114
2181 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMaxBoundary, 2115 if (CanonicalizeForComparison(&a, &b, &CanonicalizeMaxBoundary,
2182 RangeBoundary::PositiveInfinity())) { 2116 RangeBoundary::PositiveInfinity())) {
2183 return (a.offset() <= b.offset()) ? a : b; 2117 return (a.offset() <= b.offset()) ? a : b;
2184 } 2118 }
2185 2119
2186 const int64_t sup_a = a.SmiUpperBound(); 2120 const int64_t sup_a = a.SmiUpperBound();
2187 const int64_t sup_b = b.SmiUpperBound(); 2121 const int64_t sup_b = b.SmiUpperBound();
2188 2122
2189 return (sup_a <= sup_b) ? a : b; 2123 return (sup_a <= sup_b) ? a : b;
2190 } 2124 }
2191 2125
2192
2193 int64_t RangeBoundary::ConstantValue() const { 2126 int64_t RangeBoundary::ConstantValue() const {
2194 ASSERT(IsConstant()); 2127 ASSERT(IsConstant());
2195 return value_; 2128 return value_;
2196 } 2129 }
2197 2130
2198
2199 bool Range::IsPositive() const { 2131 bool Range::IsPositive() const {
2200 return OnlyGreaterThanOrEqualTo(0); 2132 return OnlyGreaterThanOrEqualTo(0);
2201 } 2133 }
2202 2134
2203
2204 bool Range::OnlyLessThanOrEqualTo(int64_t val) const { 2135 bool Range::OnlyLessThanOrEqualTo(int64_t val) const {
2205 const RangeBoundary upper_bound = max().UpperBound(); 2136 const RangeBoundary upper_bound = max().UpperBound();
2206 return !upper_bound.IsPositiveInfinity() && 2137 return !upper_bound.IsPositiveInfinity() &&
2207 (upper_bound.ConstantValue() <= val); 2138 (upper_bound.ConstantValue() <= val);
2208 } 2139 }
2209 2140
2210
2211 bool Range::OnlyGreaterThanOrEqualTo(int64_t val) const { 2141 bool Range::OnlyGreaterThanOrEqualTo(int64_t val) const {
2212 const RangeBoundary lower_bound = min().LowerBound(); 2142 const RangeBoundary lower_bound = min().LowerBound();
2213 return !lower_bound.IsNegativeInfinity() && 2143 return !lower_bound.IsNegativeInfinity() &&
2214 (lower_bound.ConstantValue() >= val); 2144 (lower_bound.ConstantValue() >= val);
2215 } 2145 }
2216 2146
2217
2218 // Inclusive. 2147 // Inclusive.
2219 bool Range::IsWithin(int64_t min_int, int64_t max_int) const { 2148 bool Range::IsWithin(int64_t min_int, int64_t max_int) const {
2220 return OnlyGreaterThanOrEqualTo(min_int) && OnlyLessThanOrEqualTo(max_int); 2149 return OnlyGreaterThanOrEqualTo(min_int) && OnlyLessThanOrEqualTo(max_int);
2221 } 2150 }
2222 2151
2223
2224 bool Range::Overlaps(int64_t min_int, int64_t max_int) const { 2152 bool Range::Overlaps(int64_t min_int, int64_t max_int) const {
2225 RangeBoundary lower = min().LowerBound(); 2153 RangeBoundary lower = min().LowerBound();
2226 RangeBoundary upper = max().UpperBound(); 2154 RangeBoundary upper = max().UpperBound();
2227 const int64_t this_min = 2155 const int64_t this_min =
2228 lower.IsNegativeInfinity() ? RangeBoundary::kMin : lower.ConstantValue(); 2156 lower.IsNegativeInfinity() ? RangeBoundary::kMin : lower.ConstantValue();
2229 const int64_t this_max = 2157 const int64_t this_max =
2230 upper.IsPositiveInfinity() ? RangeBoundary::kMax : upper.ConstantValue(); 2158 upper.IsPositiveInfinity() ? RangeBoundary::kMax : upper.ConstantValue();
2231 if ((this_min <= min_int) && (min_int <= this_max)) return true; 2159 if ((this_min <= min_int) && (min_int <= this_max)) return true;
2232 if ((this_min <= max_int) && (max_int <= this_max)) return true; 2160 if ((this_min <= max_int) && (max_int <= this_max)) return true;
2233 if ((min_int < this_min) && (max_int > this_max)) return true; 2161 if ((min_int < this_min) && (max_int > this_max)) return true;
2234 return false; 2162 return false;
2235 } 2163 }
2236 2164
2237
2238 bool Range::IsUnsatisfiable() const { 2165 bool Range::IsUnsatisfiable() const {
2239 // Infinity case: [+inf, ...] || [..., -inf] 2166 // Infinity case: [+inf, ...] || [..., -inf]
2240 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { 2167 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) {
2241 return true; 2168 return true;
2242 } 2169 }
2243 // Constant case: For example [0, -1]. 2170 // Constant case: For example [0, -1].
2244 if (Range::ConstantMin(this).ConstantValue() > 2171 if (Range::ConstantMin(this).ConstantValue() >
2245 Range::ConstantMax(this).ConstantValue()) { 2172 Range::ConstantMax(this).ConstantValue()) {
2246 return true; 2173 return true;
2247 } 2174 }
2248 // Symbol case: For example [v+1, v]. 2175 // Symbol case: For example [v+1, v].
2249 return DependOnSameSymbol(min(), max()) && min().offset() > max().offset(); 2176 return DependOnSameSymbol(min(), max()) && min().offset() > max().offset();
2250 } 2177 }
2251 2178
2252
2253 void Range::Clamp(RangeBoundary::RangeSize size) { 2179 void Range::Clamp(RangeBoundary::RangeSize size) {
2254 min_ = min_.Clamp(size); 2180 min_ = min_.Clamp(size);
2255 max_ = max_.Clamp(size); 2181 max_ = max_.Clamp(size);
2256 } 2182 }
2257 2183
2258
2259 void Range::ClampToConstant(RangeBoundary::RangeSize size) { 2184 void Range::ClampToConstant(RangeBoundary::RangeSize size) {
2260 min_ = min_.LowerBound().Clamp(size); 2185 min_ = min_.LowerBound().Clamp(size);
2261 max_ = max_.UpperBound().Clamp(size); 2186 max_ = max_.UpperBound().Clamp(size);
2262 } 2187 }
2263 2188
2264
2265 void Range::Shl(const Range* left, 2189 void Range::Shl(const Range* left,
2266 const Range* right, 2190 const Range* right,
2267 RangeBoundary* result_min, 2191 RangeBoundary* result_min,
2268 RangeBoundary* result_max) { 2192 RangeBoundary* result_max) {
2269 ASSERT(left != NULL); 2193 ASSERT(left != NULL);
2270 ASSERT(right != NULL); 2194 ASSERT(right != NULL);
2271 ASSERT(result_min != NULL); 2195 ASSERT(result_min != NULL);
2272 ASSERT(result_max != NULL); 2196 ASSERT(result_max != NULL);
2273 RangeBoundary left_max = Range::ConstantMax(left); 2197 RangeBoundary left_max = Range::ConstantMax(left);
2274 RangeBoundary left_min = Range::ConstantMin(left); 2198 RangeBoundary left_min = Range::ConstantMin(left);
2275 // A negative shift count always deoptimizes (and throws), so the minimum 2199 // A negative shift count always deoptimizes (and throws), so the minimum
2276 // shift count is zero. 2200 // shift count is zero.
2277 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(), 2201 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(),
2278 static_cast<int64_t>(0)); 2202 static_cast<int64_t>(0));
2279 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(), 2203 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(),
2280 static_cast<int64_t>(0)); 2204 static_cast<int64_t>(0));
2281 2205
2282 *result_min = RangeBoundary::Shl( 2206 *result_min = RangeBoundary::Shl(
2283 left_min, left_min.ConstantValue() > 0 ? right_min : right_max, 2207 left_min, left_min.ConstantValue() > 0 ? right_min : right_max,
2284 left_min.ConstantValue() > 0 ? RangeBoundary::PositiveInfinity() 2208 left_min.ConstantValue() > 0 ? RangeBoundary::PositiveInfinity()
2285 : RangeBoundary::NegativeInfinity()); 2209 : RangeBoundary::NegativeInfinity());
2286 2210
2287 *result_max = RangeBoundary::Shl( 2211 *result_max = RangeBoundary::Shl(
2288 left_max, left_max.ConstantValue() > 0 ? right_max : right_min, 2212 left_max, left_max.ConstantValue() > 0 ? right_max : right_min,
2289 left_max.ConstantValue() > 0 ? RangeBoundary::PositiveInfinity() 2213 left_max.ConstantValue() > 0 ? RangeBoundary::PositiveInfinity()
2290 : RangeBoundary::NegativeInfinity()); 2214 : RangeBoundary::NegativeInfinity());
2291 } 2215 }
2292 2216
2293
2294 void Range::Shr(const Range* left, 2217 void Range::Shr(const Range* left,
2295 const Range* right, 2218 const Range* right,
2296 RangeBoundary* result_min, 2219 RangeBoundary* result_min,
2297 RangeBoundary* result_max) { 2220 RangeBoundary* result_max) {
2298 RangeBoundary left_max = Range::ConstantMax(left); 2221 RangeBoundary left_max = Range::ConstantMax(left);
2299 RangeBoundary left_min = Range::ConstantMin(left); 2222 RangeBoundary left_min = Range::ConstantMin(left);
2300 // A negative shift count always deoptimizes (and throws), so the minimum 2223 // A negative shift count always deoptimizes (and throws), so the minimum
2301 // shift count is zero. 2224 // shift count is zero.
2302 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(), 2225 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(),
2303 static_cast<int64_t>(0)); 2226 static_cast<int64_t>(0));
2304 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(), 2227 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(),
2305 static_cast<int64_t>(0)); 2228 static_cast<int64_t>(0));
2306 2229
2307 *result_min = RangeBoundary::Shr( 2230 *result_min = RangeBoundary::Shr(
2308 left_min, left_min.ConstantValue() > 0 ? right_max : right_min); 2231 left_min, left_min.ConstantValue() > 0 ? right_max : right_min);
2309 2232
2310 *result_max = RangeBoundary::Shr( 2233 *result_max = RangeBoundary::Shr(
2311 left_max, left_max.ConstantValue() > 0 ? right_min : right_max); 2234 left_max, left_max.ConstantValue() > 0 ? right_min : right_max);
2312 } 2235 }
2313 2236
2314
2315 void Range::And(const Range* left_range, 2237 void Range::And(const Range* left_range,
2316 const Range* right_range, 2238 const Range* right_range,
2317 RangeBoundary* result_min, 2239 RangeBoundary* result_min,
2318 RangeBoundary* result_max) { 2240 RangeBoundary* result_max) {
2319 ASSERT(left_range != NULL); 2241 ASSERT(left_range != NULL);
2320 ASSERT(right_range != NULL); 2242 ASSERT(right_range != NULL);
2321 ASSERT(result_min != NULL); 2243 ASSERT(result_min != NULL);
2322 ASSERT(result_max != NULL); 2244 ASSERT(result_max != NULL);
2323 2245
2324 if (Range::ConstantMin(right_range).ConstantValue() >= 0) { 2246 if (Range::ConstantMin(right_range).ConstantValue() >= 0) {
2325 *result_min = RangeBoundary::FromConstant(0); 2247 *result_min = RangeBoundary::FromConstant(0);
2326 *result_max = Range::ConstantMax(right_range); 2248 *result_max = Range::ConstantMax(right_range);
2327 return; 2249 return;
2328 } 2250 }
2329 2251
2330 if (Range::ConstantMin(left_range).ConstantValue() >= 0) { 2252 if (Range::ConstantMin(left_range).ConstantValue() >= 0) {
2331 *result_min = RangeBoundary::FromConstant(0); 2253 *result_min = RangeBoundary::FromConstant(0);
2332 *result_max = Range::ConstantMax(left_range); 2254 *result_max = Range::ConstantMax(left_range);
2333 return; 2255 return;
2334 } 2256 }
2335 2257
2336 BitwiseOp(left_range, right_range, result_min, result_max); 2258 BitwiseOp(left_range, right_range, result_min, result_max);
2337 } 2259 }
2338 2260
2339
2340 static int BitSize(const Range* range) { 2261 static int BitSize(const Range* range) {
2341 const int64_t min = Range::ConstantMin(range).ConstantValue(); 2262 const int64_t min = Range::ConstantMin(range).ConstantValue();
2342 const int64_t max = Range::ConstantMax(range).ConstantValue(); 2263 const int64_t max = Range::ConstantMax(range).ConstantValue();
2343 return Utils::Maximum(Utils::BitLength(min), Utils::BitLength(max)); 2264 return Utils::Maximum(Utils::BitLength(min), Utils::BitLength(max));
2344 } 2265 }
2345 2266
2346
2347 void Range::BitwiseOp(const Range* left_range, 2267 void Range::BitwiseOp(const Range* left_range,
2348 const Range* right_range, 2268 const Range* right_range,
2349 RangeBoundary* result_min, 2269 RangeBoundary* result_min,
2350 RangeBoundary* result_max) { 2270 RangeBoundary* result_max) {
2351 const int bitsize = Utils::Maximum(BitSize(left_range), BitSize(right_range)); 2271 const int bitsize = Utils::Maximum(BitSize(left_range), BitSize(right_range));
2352 2272
2353 if (left_range->IsPositive() && right_range->IsPositive()) { 2273 if (left_range->IsPositive() && right_range->IsPositive()) {
2354 *result_min = RangeBoundary::FromConstant(0); 2274 *result_min = RangeBoundary::FromConstant(0);
2355 } else { 2275 } else {
2356 *result_min = 2276 *result_min =
2357 RangeBoundary::FromConstant(-(static_cast<int64_t>(1) << bitsize)); 2277 RangeBoundary::FromConstant(-(static_cast<int64_t>(1) << bitsize));
2358 } 2278 }
2359 2279
2360 *result_max = 2280 *result_max =
2361 RangeBoundary::FromConstant((static_cast<uint64_t>(1) << bitsize) - 1); 2281 RangeBoundary::FromConstant((static_cast<uint64_t>(1) << bitsize) - 1);
2362 } 2282 }
2363 2283
2364
2365 static bool IsArrayLength(Definition* defn) { 2284 static bool IsArrayLength(Definition* defn) {
2366 if (defn == NULL) { 2285 if (defn == NULL) {
2367 return false; 2286 return false;
2368 } 2287 }
2369 LoadFieldInstr* load = UnwrapConstraint(defn)->AsLoadField(); 2288 LoadFieldInstr* load = UnwrapConstraint(defn)->AsLoadField();
2370 return (load != NULL) && load->IsImmutableLengthLoad(); 2289 return (load != NULL) && load->IsImmutableLengthLoad();
2371 } 2290 }
2372 2291
2373
2374 void Range::Add(const Range* left_range, 2292 void Range::Add(const Range* left_range,
2375 const Range* right_range, 2293 const Range* right_range,
2376 RangeBoundary* result_min, 2294 RangeBoundary* result_min,
2377 RangeBoundary* result_max, 2295 RangeBoundary* result_max,
2378 Definition* left_defn) { 2296 Definition* left_defn) {
2379 ASSERT(left_range != NULL); 2297 ASSERT(left_range != NULL);
2380 ASSERT(right_range != NULL); 2298 ASSERT(right_range != NULL);
2381 ASSERT(result_min != NULL); 2299 ASSERT(result_min != NULL);
2382 ASSERT(result_max != NULL); 2300 ASSERT(result_max != NULL);
2383 2301
(...skipping 10 matching lines...) Expand all
2394 right_range->min().LowerBound(), 2312 right_range->min().LowerBound(),
2395 RangeBoundary::NegativeInfinity()); 2313 RangeBoundary::NegativeInfinity());
2396 } 2314 }
2397 if (!RangeBoundary::SymbolicAdd(left_max, right_range->max(), result_max)) { 2315 if (!RangeBoundary::SymbolicAdd(left_max, right_range->max(), result_max)) {
2398 *result_max = RangeBoundary::Add(right_range->max().UpperBound(), 2316 *result_max = RangeBoundary::Add(right_range->max().UpperBound(),
2399 left_range->max().UpperBound(), 2317 left_range->max().UpperBound(),
2400 RangeBoundary::PositiveInfinity()); 2318 RangeBoundary::PositiveInfinity());
2401 } 2319 }
2402 } 2320 }
2403 2321
2404
2405 void Range::Sub(const Range* left_range, 2322 void Range::Sub(const Range* left_range,
2406 const Range* right_range, 2323 const Range* right_range,
2407 RangeBoundary* result_min, 2324 RangeBoundary* result_min,
2408 RangeBoundary* result_max, 2325 RangeBoundary* result_max,
2409 Definition* left_defn) { 2326 Definition* left_defn) {
2410 ASSERT(left_range != NULL); 2327 ASSERT(left_range != NULL);
2411 ASSERT(right_range != NULL); 2328 ASSERT(right_range != NULL);
2412 ASSERT(result_min != NULL); 2329 ASSERT(result_min != NULL);
2413 ASSERT(result_max != NULL); 2330 ASSERT(result_max != NULL);
2414 2331
(...skipping 10 matching lines...) Expand all
2425 right_range->max().UpperBound(), 2342 right_range->max().UpperBound(),
2426 RangeBoundary::NegativeInfinity()); 2343 RangeBoundary::NegativeInfinity());
2427 } 2344 }
2428 if (!RangeBoundary::SymbolicSub(left_max, right_range->min(), result_max)) { 2345 if (!RangeBoundary::SymbolicSub(left_max, right_range->min(), result_max)) {
2429 *result_max = RangeBoundary::Sub(left_range->max().UpperBound(), 2346 *result_max = RangeBoundary::Sub(left_range->max().UpperBound(),
2430 right_range->min().LowerBound(), 2347 right_range->min().LowerBound(),
2431 RangeBoundary::PositiveInfinity()); 2348 RangeBoundary::PositiveInfinity());
2432 } 2349 }
2433 } 2350 }
2434 2351
2435
2436 void Range::Mul(const Range* left_range, 2352 void Range::Mul(const Range* left_range,
2437 const Range* right_range, 2353 const Range* right_range,
2438 RangeBoundary* result_min, 2354 RangeBoundary* result_min,
2439 RangeBoundary* result_max) { 2355 RangeBoundary* result_max) {
2440 ASSERT(left_range != NULL); 2356 ASSERT(left_range != NULL);
2441 ASSERT(right_range != NULL); 2357 ASSERT(right_range != NULL);
2442 ASSERT(result_min != NULL); 2358 ASSERT(result_min != NULL);
2443 ASSERT(result_max != NULL); 2359 ASSERT(result_max != NULL);
2444 2360
2445 const int64_t left_max = ConstantAbsMax(left_range); 2361 const int64_t left_max = ConstantAbsMax(left_range);
(...skipping 26 matching lines...) Expand all
2472 OnlyNegativeOrZero(*left_range, *right_range)) { 2388 OnlyNegativeOrZero(*left_range, *right_range)) {
2473 *result_min = RangeBoundary::FromConstant(0); 2389 *result_min = RangeBoundary::FromConstant(0);
2474 *result_max = RangeBoundary::PositiveInfinity(); 2390 *result_max = RangeBoundary::PositiveInfinity();
2475 return; 2391 return;
2476 } 2392 }
2477 2393
2478 *result_min = RangeBoundary::NegativeInfinity(); 2394 *result_min = RangeBoundary::NegativeInfinity();
2479 *result_max = RangeBoundary::PositiveInfinity(); 2395 *result_max = RangeBoundary::PositiveInfinity();
2480 } 2396 }
2481 2397
2482
2483 // Both the a and b ranges are >= 0. 2398 // Both the a and b ranges are >= 0.
2484 bool Range::OnlyPositiveOrZero(const Range& a, const Range& b) { 2399 bool Range::OnlyPositiveOrZero(const Range& a, const Range& b) {
2485 return a.OnlyGreaterThanOrEqualTo(0) && b.OnlyGreaterThanOrEqualTo(0); 2400 return a.OnlyGreaterThanOrEqualTo(0) && b.OnlyGreaterThanOrEqualTo(0);
2486 } 2401 }
2487 2402
2488
2489 // Both the a and b ranges are <= 0. 2403 // Both the a and b ranges are <= 0.
2490 bool Range::OnlyNegativeOrZero(const Range& a, const Range& b) { 2404 bool Range::OnlyNegativeOrZero(const Range& a, const Range& b) {
2491 return a.OnlyLessThanOrEqualTo(0) && b.OnlyLessThanOrEqualTo(0); 2405 return a.OnlyLessThanOrEqualTo(0) && b.OnlyLessThanOrEqualTo(0);
2492 } 2406 }
2493 2407
2494
2495 // Return the maximum absolute value included in range. 2408 // Return the maximum absolute value included in range.
2496 int64_t Range::ConstantAbsMax(const Range* range) { 2409 int64_t Range::ConstantAbsMax(const Range* range) {
2497 if (range == NULL) { 2410 if (range == NULL) {
2498 return RangeBoundary::kMax; 2411 return RangeBoundary::kMax;
2499 } 2412 }
2500 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); 2413 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue());
2501 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); 2414 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue());
2502 return Utils::Maximum(abs_min, abs_max); 2415 return Utils::Maximum(abs_min, abs_max);
2503 } 2416 }
2504 2417
2505
2506 // Return the minimum absolute value included in range. 2418 // Return the minimum absolute value included in range.
2507 int64_t Range::ConstantAbsMin(const Range* range) { 2419 int64_t Range::ConstantAbsMin(const Range* range) {
2508 if (range == NULL) { 2420 if (range == NULL) {
2509 return 0; 2421 return 0;
2510 } 2422 }
2511 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue()); 2423 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue());
2512 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue()); 2424 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue());
2513 return Utils::Minimum(abs_min, abs_max); 2425 return Utils::Minimum(abs_min, abs_max);
2514 } 2426 }
2515 2427
2516
2517 void Range::BinaryOp(const Token::Kind op, 2428 void Range::BinaryOp(const Token::Kind op,
2518 const Range* left_range, 2429 const Range* left_range,
2519 const Range* right_range, 2430 const Range* right_range,
2520 Definition* left_defn, 2431 Definition* left_defn,
2521 Range* result) { 2432 Range* result) {
2522 ASSERT(left_range != NULL); 2433 ASSERT(left_range != NULL);
2523 ASSERT(right_range != NULL); 2434 ASSERT(right_range != NULL);
2524 2435
2525 // Both left and right ranges are finite. 2436 // Both left and right ranges are finite.
2526 ASSERT(left_range->IsFinite()); 2437 ASSERT(left_range->IsFinite());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2564 *result = Range(RangeBoundary::NegativeInfinity(), 2475 *result = Range(RangeBoundary::NegativeInfinity(),
2565 RangeBoundary::PositiveInfinity()); 2476 RangeBoundary::PositiveInfinity());
2566 return; 2477 return;
2567 } 2478 }
2568 2479
2569 ASSERT(!min.IsUnknown() && !max.IsUnknown()); 2480 ASSERT(!min.IsUnknown() && !max.IsUnknown());
2570 2481
2571 *result = Range(min, max); 2482 *result = Range(min, max);
2572 } 2483 }
2573 2484
2574
2575 void Definition::set_range(const Range& range) { 2485 void Definition::set_range(const Range& range) {
2576 if (range_ == NULL) { 2486 if (range_ == NULL) {
2577 range_ = new Range(); 2487 range_ = new Range();
2578 } 2488 }
2579 *range_ = range; 2489 *range_ = range;
2580 } 2490 }
2581 2491
2582
2583 void Definition::InferRange(RangeAnalysis* analysis, Range* range) { 2492 void Definition::InferRange(RangeAnalysis* analysis, Range* range) {
2584 if (Type()->ToCid() == kSmiCid) { 2493 if (Type()->ToCid() == kSmiCid) {
2585 *range = Range::Full(RangeBoundary::kRangeBoundarySmi); 2494 *range = Range::Full(RangeBoundary::kRangeBoundarySmi);
2586 } else if (IsMintDefinition()) { 2495 } else if (IsMintDefinition()) {
2587 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64); 2496 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
2588 } else if (IsInt32Definition()) { 2497 } else if (IsInt32Definition()) {
2589 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32); 2498 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32);
2590 } else if (Type()->IsInt()) { 2499 } else if (Type()->IsInt()) {
2591 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64); 2500 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
2592 } else { 2501 } else {
2593 // Only Smi and Mint supported. 2502 // Only Smi and Mint supported.
2594 UNREACHABLE(); 2503 UNREACHABLE();
2595 } 2504 }
2596 } 2505 }
2597 2506
2598
2599 static bool DependsOnSymbol(const RangeBoundary& a, Definition* symbol) { 2507 static bool DependsOnSymbol(const RangeBoundary& a, Definition* symbol) {
2600 return a.IsSymbol() && (UnwrapConstraint(a.symbol()) == symbol); 2508 return a.IsSymbol() && (UnwrapConstraint(a.symbol()) == symbol);
2601 } 2509 }
2602 2510
2603
2604 // Given the range and definition update the range so that 2511 // Given the range and definition update the range so that
2605 // it covers both original range and definitions range. 2512 // it covers both original range and definitions range.
2606 // 2513 //
2607 // The following should also hold: 2514 // The following should also hold:
2608 // 2515 //
2609 // [_|_, _|_] U a = a U [_|_, _|_] = a 2516 // [_|_, _|_] U a = a U [_|_, _|_] = a
2610 // 2517 //
2611 static void Join(Range* range, 2518 static void Join(Range* range,
2612 Definition* defn, 2519 Definition* defn,
2613 const Range* defn_range, 2520 const Range* defn_range,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2651 // The range is fully above defn's range. Keep the maximum and 2558 // The range is fully above defn's range. Keep the maximum and
2652 // expand the minimum. 2559 // expand the minimum.
2653 range->set_min(other.min()); 2560 range->set_min(other.min());
2654 } else { 2561 } else {
2655 // Can't compare ranges as whole. Join minimum and maximum separately. 2562 // Can't compare ranges as whole. Join minimum and maximum separately.
2656 *range = Range(RangeBoundary::JoinMin(range->min(), other.min(), size), 2563 *range = Range(RangeBoundary::JoinMin(range->min(), other.min(), size),
2657 RangeBoundary::JoinMax(range->max(), other.max(), size)); 2564 RangeBoundary::JoinMax(range->max(), other.max(), size));
2658 } 2565 }
2659 } 2566 }
2660 2567
2661
2662 // A definition dominates a phi if its block dominates the phi's block 2568 // A definition dominates a phi if its block dominates the phi's block
2663 // and the two blocks are different. 2569 // and the two blocks are different.
2664 static bool DominatesPhi(BlockEntryInstr* a, BlockEntryInstr* phi_block) { 2570 static bool DominatesPhi(BlockEntryInstr* a, BlockEntryInstr* phi_block) {
2665 return a->Dominates(phi_block) && (a != phi_block); 2571 return a->Dominates(phi_block) && (a != phi_block);
2666 } 2572 }
2667 2573
2668
2669 // When assigning range to a phi we must take care to avoid self-reference 2574 // When assigning range to a phi we must take care to avoid self-reference
2670 // cycles when phi's range depends on the phi itself. 2575 // cycles when phi's range depends on the phi itself.
2671 // To prevent such cases we impose additional restriction on symbols that 2576 // To prevent such cases we impose additional restriction on symbols that
2672 // can be used as boundaries for phi's range: they must dominate 2577 // can be used as boundaries for phi's range: they must dominate
2673 // phi's definition. 2578 // phi's definition.
2674 static RangeBoundary EnsureAcyclicSymbol(BlockEntryInstr* phi_block, 2579 static RangeBoundary EnsureAcyclicSymbol(BlockEntryInstr* phi_block,
2675 const RangeBoundary& a, 2580 const RangeBoundary& a,
2676 const RangeBoundary& limit) { 2581 const RangeBoundary& limit) {
2677 if (!a.IsSymbol() || DominatesPhi(a.symbol()->GetBlock(), phi_block)) { 2582 if (!a.IsSymbol() || DominatesPhi(a.symbol()->GetBlock(), phi_block)) {
2678 return a; 2583 return a;
2679 } 2584 }
2680 2585
2681 // Symbol does not dominate phi. Try unwrapping constraint and check again. 2586 // Symbol does not dominate phi. Try unwrapping constraint and check again.
2682 Definition* unwrapped = UnwrapConstraint(a.symbol()); 2587 Definition* unwrapped = UnwrapConstraint(a.symbol());
2683 if ((unwrapped != a.symbol()) && 2588 if ((unwrapped != a.symbol()) &&
2684 DominatesPhi(unwrapped->GetBlock(), phi_block)) { 2589 DominatesPhi(unwrapped->GetBlock(), phi_block)) {
2685 return RangeBoundary::FromDefinition(unwrapped, a.offset()); 2590 return RangeBoundary::FromDefinition(unwrapped, a.offset());
2686 } 2591 }
2687 2592
2688 return limit; 2593 return limit;
2689 } 2594 }
2690 2595
2691
2692 static const Range* GetInputRange(RangeAnalysis* analysis, 2596 static const Range* GetInputRange(RangeAnalysis* analysis,
2693 RangeBoundary::RangeSize size, 2597 RangeBoundary::RangeSize size,
2694 Value* input) { 2598 Value* input) {
2695 switch (size) { 2599 switch (size) {
2696 case RangeBoundary::kRangeBoundarySmi: 2600 case RangeBoundary::kRangeBoundarySmi:
2697 return analysis->GetSmiRange(input); 2601 return analysis->GetSmiRange(input);
2698 case RangeBoundary::kRangeBoundaryInt32: 2602 case RangeBoundary::kRangeBoundaryInt32:
2699 return input->definition()->range(); 2603 return input->definition()->range();
2700 case RangeBoundary::kRangeBoundaryInt64: 2604 case RangeBoundary::kRangeBoundaryInt64:
2701 return analysis->GetIntRange(input); 2605 return analysis->GetIntRange(input);
2702 default: 2606 default:
2703 UNREACHABLE(); 2607 UNREACHABLE();
2704 return NULL; 2608 return NULL;
2705 } 2609 }
2706 } 2610 }
2707 2611
2708
2709 void PhiInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2612 void PhiInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2710 const RangeBoundary::RangeSize size = RangeSizeForPhi(this); 2613 const RangeBoundary::RangeSize size = RangeSizeForPhi(this);
2711 for (intptr_t i = 0; i < InputCount(); i++) { 2614 for (intptr_t i = 0; i < InputCount(); i++) {
2712 Value* input = InputAt(i); 2615 Value* input = InputAt(i);
2713 Join(range, input->definition(), GetInputRange(analysis, size, input), 2616 Join(range, input->definition(), GetInputRange(analysis, size, input),
2714 size); 2617 size);
2715 } 2618 }
2716 2619
2717 BlockEntryInstr* phi_block = GetBlock(); 2620 BlockEntryInstr* phi_block = GetBlock();
2718 range->set_min( 2621 range->set_min(
2719 EnsureAcyclicSymbol(phi_block, range->min(), RangeBoundary::MinSmi())); 2622 EnsureAcyclicSymbol(phi_block, range->min(), RangeBoundary::MinSmi()));
2720 range->set_max( 2623 range->set_max(
2721 EnsureAcyclicSymbol(phi_block, range->max(), RangeBoundary::MaxSmi())); 2624 EnsureAcyclicSymbol(phi_block, range->max(), RangeBoundary::MaxSmi()));
2722 } 2625 }
2723 2626
2724
2725 void ConstantInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2627 void ConstantInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2726 if (value_.IsSmi()) { 2628 if (value_.IsSmi()) {
2727 int64_t value = Smi::Cast(value_).Value(); 2629 int64_t value = Smi::Cast(value_).Value();
2728 *range = Range(RangeBoundary::FromConstant(value), 2630 *range = Range(RangeBoundary::FromConstant(value),
2729 RangeBoundary::FromConstant(value)); 2631 RangeBoundary::FromConstant(value));
2730 } else if (value_.IsMint()) { 2632 } else if (value_.IsMint()) {
2731 int64_t value = Mint::Cast(value_).value(); 2633 int64_t value = Mint::Cast(value_).value();
2732 *range = Range(RangeBoundary::FromConstant(value), 2634 *range = Range(RangeBoundary::FromConstant(value),
2733 RangeBoundary::FromConstant(value)); 2635 RangeBoundary::FromConstant(value));
2734 } else { 2636 } else {
2735 // Only Smi and Mint supported. 2637 // Only Smi and Mint supported.
2736 UNREACHABLE(); 2638 UNREACHABLE();
2737 } 2639 }
2738 } 2640 }
2739 2641
2740
2741 void ConstraintInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2642 void ConstraintInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2742 const Range* value_range = analysis->GetSmiRange(value()); 2643 const Range* value_range = analysis->GetSmiRange(value());
2743 if (Range::IsUnknown(value_range)) { 2644 if (Range::IsUnknown(value_range)) {
2744 return; 2645 return;
2745 } 2646 }
2746 2647
2747 // TODO(vegorov) check if precision of the analysis can be improved by 2648 // TODO(vegorov) check if precision of the analysis can be improved by
2748 // recognizing intersections of the form: 2649 // recognizing intersections of the form:
2749 // 2650 //
2750 // (..., S+x] ^ [S+x, ...) = [S+x, S+x] 2651 // (..., S+x] ^ [S+x, ...) = [S+x, S+x]
2751 // 2652 //
2752 Range result = value_range->Intersect(constraint()); 2653 Range result = value_range->Intersect(constraint());
2753 2654
2754 if (result.IsUnsatisfiable()) { 2655 if (result.IsUnsatisfiable()) {
2755 return; 2656 return;
2756 } 2657 }
2757 2658
2758 *range = result; 2659 *range = result;
2759 } 2660 }
2760 2661
2761
2762 void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2662 void LoadFieldInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2763 switch (recognized_kind()) { 2663 switch (recognized_kind()) {
2764 case MethodRecognizer::kObjectArrayLength: 2664 case MethodRecognizer::kObjectArrayLength:
2765 case MethodRecognizer::kImmutableArrayLength: 2665 case MethodRecognizer::kImmutableArrayLength:
2766 *range = Range(RangeBoundary::FromConstant(0), 2666 *range = Range(RangeBoundary::FromConstant(0),
2767 RangeBoundary::FromConstant(Array::kMaxElements)); 2667 RangeBoundary::FromConstant(Array::kMaxElements));
2768 break; 2668 break;
2769 2669
2770 case MethodRecognizer::kTypedDataLength: 2670 case MethodRecognizer::kTypedDataLength:
2771 *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi()); 2671 *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
2772 break; 2672 break;
2773 2673
2774 case MethodRecognizer::kStringBaseLength: 2674 case MethodRecognizer::kStringBaseLength:
2775 *range = Range(RangeBoundary::FromConstant(0), 2675 *range = Range(RangeBoundary::FromConstant(0),
2776 RangeBoundary::FromConstant(String::kMaxElements)); 2676 RangeBoundary::FromConstant(String::kMaxElements));
2777 break; 2677 break;
2778 2678
2779 default: 2679 default:
2780 Definition::InferRange(analysis, range); 2680 Definition::InferRange(analysis, range);
2781 } 2681 }
2782 } 2682 }
2783 2683
2784
2785 void LoadIndexedInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2684 void LoadIndexedInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2786 switch (class_id()) { 2685 switch (class_id()) {
2787 case kTypedDataInt8ArrayCid: 2686 case kTypedDataInt8ArrayCid:
2788 *range = Range(RangeBoundary::FromConstant(-128), 2687 *range = Range(RangeBoundary::FromConstant(-128),
2789 RangeBoundary::FromConstant(127)); 2688 RangeBoundary::FromConstant(127));
2790 break; 2689 break;
2791 case kTypedDataUint8ArrayCid: 2690 case kTypedDataUint8ArrayCid:
2792 case kTypedDataUint8ClampedArrayCid: 2691 case kTypedDataUint8ClampedArrayCid:
2793 case kExternalTypedDataUint8ArrayCid: 2692 case kExternalTypedDataUint8ArrayCid:
2794 case kExternalTypedDataUint8ClampedArrayCid: 2693 case kExternalTypedDataUint8ClampedArrayCid:
(...skipping 23 matching lines...) Expand all
2818 case kTwoByteStringCid: 2717 case kTwoByteStringCid:
2819 *range = Range(RangeBoundary::FromConstant(0), 2718 *range = Range(RangeBoundary::FromConstant(0),
2820 RangeBoundary::FromConstant(0xFFFF)); 2719 RangeBoundary::FromConstant(0xFFFF));
2821 break; 2720 break;
2822 default: 2721 default:
2823 Definition::InferRange(analysis, range); 2722 Definition::InferRange(analysis, range);
2824 break; 2723 break;
2825 } 2724 }
2826 } 2725 }
2827 2726
2828
2829 void LoadCodeUnitsInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2727 void LoadCodeUnitsInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2830 ASSERT(RawObject::IsStringClassId(class_id())); 2728 ASSERT(RawObject::IsStringClassId(class_id()));
2831 switch (class_id()) { 2729 switch (class_id()) {
2832 case kOneByteStringCid: 2730 case kOneByteStringCid:
2833 case kTwoByteStringCid: 2731 case kTwoByteStringCid:
2834 case kExternalOneByteStringCid: 2732 case kExternalOneByteStringCid:
2835 case kExternalTwoByteStringCid: 2733 case kExternalTwoByteStringCid:
2836 *range = Range(RangeBoundary::FromConstant(0), 2734 *range = Range(RangeBoundary::FromConstant(0),
2837 RangeBoundary::FromConstant(kMaxUint32)); 2735 RangeBoundary::FromConstant(kMaxUint32));
2838 break; 2736 break;
2839 default: 2737 default:
2840 UNREACHABLE(); 2738 UNREACHABLE();
2841 break; 2739 break;
2842 } 2740 }
2843 } 2741 }
2844 2742
2845
2846 void IfThenElseInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2743 void IfThenElseInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2847 const intptr_t min = Utils::Minimum(if_true_, if_false_); 2744 const intptr_t min = Utils::Minimum(if_true_, if_false_);
2848 const intptr_t max = Utils::Maximum(if_true_, if_false_); 2745 const intptr_t max = Utils::Maximum(if_true_, if_false_);
2849 *range = 2746 *range =
2850 Range(RangeBoundary::FromConstant(min), RangeBoundary::FromConstant(max)); 2747 Range(RangeBoundary::FromConstant(min), RangeBoundary::FromConstant(max));
2851 } 2748 }
2852 2749
2853
2854 static RangeBoundary::RangeSize RepresentationToRangeSize(Representation r) { 2750 static RangeBoundary::RangeSize RepresentationToRangeSize(Representation r) {
2855 switch (r) { 2751 switch (r) {
2856 case kTagged: 2752 case kTagged:
2857 return RangeBoundary::kRangeBoundarySmi; 2753 return RangeBoundary::kRangeBoundarySmi;
2858 case kUnboxedInt32: 2754 case kUnboxedInt32:
2859 return RangeBoundary::kRangeBoundaryInt32; 2755 return RangeBoundary::kRangeBoundaryInt32;
2860 case kUnboxedMint: 2756 case kUnboxedMint:
2861 return RangeBoundary::kRangeBoundaryInt64; 2757 return RangeBoundary::kRangeBoundaryInt64;
2862 default: 2758 default:
2863 UNREACHABLE(); 2759 UNREACHABLE();
2864 return RangeBoundary::kRangeBoundarySmi; 2760 return RangeBoundary::kRangeBoundarySmi;
2865 } 2761 }
2866 } 2762 }
2867 2763
2868
2869 void BinaryIntegerOpInstr::InferRangeHelper(const Range* left_range, 2764 void BinaryIntegerOpInstr::InferRangeHelper(const Range* left_range,
2870 const Range* right_range, 2765 const Range* right_range,
2871 Range* range) { 2766 Range* range) {
2872 // TODO(vegorov): canonicalize BinaryIntegerOp to always have constant on the 2767 // TODO(vegorov): canonicalize BinaryIntegerOp to always have constant on the
2873 // right and a non-constant on the left. 2768 // right and a non-constant on the left.
2874 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) { 2769 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
2875 return; 2770 return;
2876 } 2771 }
2877 2772
2878 Range::BinaryOp(op_kind(), left_range, right_range, left()->definition(), 2773 Range::BinaryOp(op_kind(), left_range, right_range, left()->definition(),
2879 range); 2774 range);
2880 ASSERT(!Range::IsUnknown(range)); 2775 ASSERT(!Range::IsUnknown(range));
2881 2776
2882 const RangeBoundary::RangeSize range_size = 2777 const RangeBoundary::RangeSize range_size =
2883 RepresentationToRangeSize(representation()); 2778 RepresentationToRangeSize(representation());
2884 2779
2885 // Calculate overflowed status before clamping if operation is 2780 // Calculate overflowed status before clamping if operation is
2886 // not truncating. 2781 // not truncating.
2887 if (!is_truncating()) { 2782 if (!is_truncating()) {
2888 set_can_overflow(!range->Fits(range_size)); 2783 set_can_overflow(!range->Fits(range_size));
2889 } 2784 }
2890 2785
2891 range->Clamp(range_size); 2786 range->Clamp(range_size);
2892 } 2787 }
2893 2788
2894
2895 static void CacheRange(Range** slot, 2789 static void CacheRange(Range** slot,
2896 const Range* range, 2790 const Range* range,
2897 RangeBoundary::RangeSize size) { 2791 RangeBoundary::RangeSize size) {
2898 if (range != NULL) { 2792 if (range != NULL) {
2899 if (*slot == NULL) { 2793 if (*slot == NULL) {
2900 *slot = new Range(); 2794 *slot = new Range();
2901 } 2795 }
2902 **slot = *range; 2796 **slot = *range;
2903 2797
2904 // Eliminate any symbolic dependencies from the range information. 2798 // Eliminate any symbolic dependencies from the range information.
2905 (*slot)->ClampToConstant(size); 2799 (*slot)->ClampToConstant(size);
2906 } else if (*slot != NULL) { 2800 } else if (*slot != NULL) {
2907 **slot = Range(); // Clear cached range information. 2801 **slot = Range(); // Clear cached range information.
2908 } 2802 }
2909 } 2803 }
2910 2804
2911
2912 void BinarySmiOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2805 void BinarySmiOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2913 const Range* right_smi_range = analysis->GetSmiRange(right()); 2806 const Range* right_smi_range = analysis->GetSmiRange(right());
2914 // TODO(vegorov) completely remove this once GetSmiRange is eliminated. 2807 // TODO(vegorov) completely remove this once GetSmiRange is eliminated.
2915 if (op_kind() == Token::kSHR || op_kind() == Token::kSHL || 2808 if (op_kind() == Token::kSHR || op_kind() == Token::kSHL ||
2916 op_kind() == Token::kMOD || op_kind() == Token::kTRUNCDIV) { 2809 op_kind() == Token::kMOD || op_kind() == Token::kTRUNCDIV) {
2917 CacheRange(&right_range_, right_smi_range, 2810 CacheRange(&right_range_, right_smi_range,
2918 RangeBoundary::kRangeBoundarySmi); 2811 RangeBoundary::kRangeBoundarySmi);
2919 } 2812 }
2920 InferRangeHelper(analysis->GetSmiRange(left()), right_smi_range, range); 2813 InferRangeHelper(analysis->GetSmiRange(left()), right_smi_range, range);
2921 } 2814 }
2922 2815
2923
2924 void BinaryInt32OpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2816 void BinaryInt32OpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2925 InferRangeHelper(analysis->GetSmiRange(left()), 2817 InferRangeHelper(analysis->GetSmiRange(left()),
2926 analysis->GetSmiRange(right()), range); 2818 analysis->GetSmiRange(right()), range);
2927 } 2819 }
2928 2820
2929
2930 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2821 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2931 InferRangeHelper(left()->definition()->range(), 2822 InferRangeHelper(left()->definition()->range(),
2932 right()->definition()->range(), range); 2823 right()->definition()->range(), range);
2933 } 2824 }
2934 2825
2935
2936 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2826 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2937 CacheRange(&shift_range_, right()->definition()->range(), 2827 CacheRange(&shift_range_, right()->definition()->range(),
2938 RangeBoundary::kRangeBoundaryInt64); 2828 RangeBoundary::kRangeBoundaryInt64);
2939 InferRangeHelper(left()->definition()->range(), 2829 InferRangeHelper(left()->definition()->range(),
2940 right()->definition()->range(), range); 2830 right()->definition()->range(), range);
2941 } 2831 }
2942 2832
2943
2944 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2833 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2945 const Range* value_range = value()->definition()->range(); 2834 const Range* value_range = value()->definition()->range();
2946 if (!Range::IsUnknown(value_range)) { 2835 if (!Range::IsUnknown(value_range)) {
2947 *range = *value_range; 2836 *range = *value_range;
2948 } 2837 }
2949 } 2838 }
2950 2839
2951
2952 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2840 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2953 if (value()->Type()->ToCid() == kSmiCid) { 2841 if (value()->Type()->ToCid() == kSmiCid) {
2954 const Range* value_range = analysis->GetSmiRange(value()); 2842 const Range* value_range = analysis->GetSmiRange(value());
2955 if (!Range::IsUnknown(value_range)) { 2843 if (!Range::IsUnknown(value_range)) {
2956 *range = *value_range; 2844 *range = *value_range;
2957 } 2845 }
2958 } else if (RangeAnalysis::IsIntegerDefinition(value()->definition())) { 2846 } else if (RangeAnalysis::IsIntegerDefinition(value()->definition())) {
2959 const Range* value_range = analysis->GetIntRange(value()); 2847 const Range* value_range = analysis->GetIntRange(value());
2960 if (!Range::IsUnknown(value_range)) { 2848 if (!Range::IsUnknown(value_range)) {
2961 *range = *value_range; 2849 *range = *value_range;
2962 } 2850 }
2963 } else if (value()->Type()->ToCid() == kSmiCid) { 2851 } else if (value()->Type()->ToCid() == kSmiCid) {
2964 *range = Range::Full(RangeBoundary::kRangeBoundarySmi); 2852 *range = Range::Full(RangeBoundary::kRangeBoundarySmi);
2965 } else { 2853 } else {
2966 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32); 2854 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32);
2967 } 2855 }
2968 } 2856 }
2969 2857
2970
2971 void UnboxUint32Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2858 void UnboxUint32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2972 const Range* value_range = NULL; 2859 const Range* value_range = NULL;
2973 2860
2974 if (value()->Type()->ToCid() == kSmiCid) { 2861 if (value()->Type()->ToCid() == kSmiCid) {
2975 value_range = analysis->GetSmiRange(value()); 2862 value_range = analysis->GetSmiRange(value());
2976 } else if (RangeAnalysis::IsIntegerDefinition(value()->definition())) { 2863 } else if (RangeAnalysis::IsIntegerDefinition(value()->definition())) {
2977 value_range = analysis->GetIntRange(value()); 2864 value_range = analysis->GetIntRange(value());
2978 } else { 2865 } else {
2979 *range = Range(RangeBoundary::FromConstant(0), 2866 *range = Range(RangeBoundary::FromConstant(0),
2980 RangeBoundary::FromConstant(kMaxUint32)); 2867 RangeBoundary::FromConstant(kMaxUint32));
2981 return; 2868 return;
2982 } 2869 }
2983 2870
2984 if (!Range::IsUnknown(value_range)) { 2871 if (!Range::IsUnknown(value_range)) {
2985 if (value_range->IsPositive()) { 2872 if (value_range->IsPositive()) {
2986 *range = *value_range; 2873 *range = *value_range;
2987 } else { 2874 } else {
2988 *range = Range(RangeBoundary::FromConstant(0), 2875 *range = Range(RangeBoundary::FromConstant(0),
2989 RangeBoundary::FromConstant(kMaxUint32)); 2876 RangeBoundary::FromConstant(kMaxUint32));
2990 } 2877 }
2991 } 2878 }
2992 } 2879 }
2993 2880
2994
2995 void UnboxInt64Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2881 void UnboxInt64Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2996 const Range* value_range = value()->definition()->range(); 2882 const Range* value_range = value()->definition()->range();
2997 if (value_range != NULL) { 2883 if (value_range != NULL) {
2998 *range = *value_range; 2884 *range = *value_range;
2999 } else if (!value()->definition()->IsMintDefinition() && 2885 } else if (!value()->definition()->IsMintDefinition() &&
3000 (value()->definition()->Type()->ToCid() != kSmiCid)) { 2886 (value()->definition()->Type()->ToCid() != kSmiCid)) {
3001 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64); 2887 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
3002 } 2888 }
3003 } 2889 }
3004 2890
3005
3006 void UnboxedIntConverterInstr::InferRange(RangeAnalysis* analysis, 2891 void UnboxedIntConverterInstr::InferRange(RangeAnalysis* analysis,
3007 Range* range) { 2892 Range* range) {
3008 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedMint) || 2893 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedMint) ||
3009 (from() == kUnboxedUint32)); 2894 (from() == kUnboxedUint32));
3010 ASSERT((to() == kUnboxedInt32) || (to() == kUnboxedMint) || 2895 ASSERT((to() == kUnboxedInt32) || (to() == kUnboxedMint) ||
3011 (to() == kUnboxedUint32)); 2896 (to() == kUnboxedUint32));
3012 const Range* value_range = value()->definition()->range(); 2897 const Range* value_range = value()->definition()->range();
3013 if (Range::IsUnknown(value_range)) { 2898 if (Range::IsUnknown(value_range)) {
3014 return; 2899 return;
3015 } 2900 }
3016 2901
3017 if (to() == kUnboxedUint32) { 2902 if (to() == kUnboxedUint32) {
3018 // TODO(vegorov): improve range information for unboxing to Uint32. 2903 // TODO(vegorov): improve range information for unboxing to Uint32.
3019 *range = 2904 *range =
3020 Range(RangeBoundary::FromConstant(0), 2905 Range(RangeBoundary::FromConstant(0),
3021 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32))); 2906 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32)));
3022 } else { 2907 } else {
3023 *range = *value_range; 2908 *range = *value_range;
3024 if (to() == kUnboxedInt32) { 2909 if (to() == kUnboxedInt32) {
3025 range->Clamp(RangeBoundary::kRangeBoundaryInt32); 2910 range->Clamp(RangeBoundary::kRangeBoundaryInt32);
3026 } 2911 }
3027 } 2912 }
3028 } 2913 }
3029 2914
3030
3031 bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) { 2915 bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) {
3032 Range* index_range = index()->definition()->range(); 2916 Range* index_range = index()->definition()->range();
3033 2917
3034 // Range of the index is unknown can't decide if the check is redundant. 2918 // Range of the index is unknown can't decide if the check is redundant.
3035 if (index_range == NULL) { 2919 if (index_range == NULL) {
3036 if (!(index()->BindsToConstant() && index()->BoundConstant().IsSmi())) { 2920 if (!(index()->BindsToConstant() && index()->BoundConstant().IsSmi())) {
3037 return false; 2921 return false;
3038 } 2922 }
3039 2923
3040 Range range; 2924 Range range;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3074 if (DependOnSameSymbol(max, canonical_length)) { 2958 if (DependOnSameSymbol(max, canonical_length)) {
3075 return max.offset() < canonical_length.offset(); 2959 return max.offset() < canonical_length.offset();
3076 } 2960 }
3077 } while (CanonicalizeMaxBoundary(&max) || 2961 } while (CanonicalizeMaxBoundary(&max) ||
3078 CanonicalizeMinBoundary(&canonical_length)); 2962 CanonicalizeMinBoundary(&canonical_length));
3079 2963
3080 // Failed to prove that maximum is bounded with array length. 2964 // Failed to prove that maximum is bounded with array length.
3081 return false; 2965 return false;
3082 } 2966 }
3083 2967
3084
3085 } // namespace dart 2968 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_range_analysis.h ('k') | runtime/vm/flow_graph_range_analysis_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698