OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 } | 71 } |
72 | 72 |
73 // Process phi instructions. | 73 // Process phi instructions. |
74 for (int i = 0; i < block->phis()->length(); ++i) { | 74 for (int i = 0; i < block->phis()->length(); ++i) { |
75 HPhi* phi = block->phis()->at(i); | 75 HPhi* phi = block->phis()->at(i); |
76 InferRange(phi); | 76 InferRange(phi); |
77 } | 77 } |
78 | 78 |
79 // Go through all instructions of the current block. | 79 // Go through all instructions of the current block. |
80 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { | 80 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { |
81 InferRange(it.Current()); | 81 HValue* value = it.Current(); |
| 82 InferRange(value); |
| 83 |
| 84 // Compute the bailout-on-minus-zero flag. |
| 85 if (value->IsChange()) { |
| 86 HChange* instr = HChange::cast(value); |
| 87 // Propagate flags for negative zero checks upwards from conversions |
| 88 // int32-to-tagged and int32-to-double. |
| 89 Representation from = instr->value()->representation(); |
| 90 ASSERT(from.Equals(instr->from())); |
| 91 if (from.IsSmiOrInteger32()) { |
| 92 ASSERT(instr->to().IsTagged() || |
| 93 instr->to().IsDouble() || |
| 94 instr->to().IsSmiOrInteger32()); |
| 95 PropagateMinusZeroChecks(instr->value()); |
| 96 } |
| 97 } else if (value->IsCompareMinusZeroAndBranch()) { |
| 98 HCompareMinusZeroAndBranch* instr = |
| 99 HCompareMinusZeroAndBranch::cast(value); |
| 100 if (instr->value()->representation().IsSmiOrInteger32()) { |
| 101 PropagateMinusZeroChecks(instr->value()); |
| 102 } |
| 103 } |
82 } | 104 } |
83 | 105 |
84 // Continue analysis in all dominated blocks. | 106 // Continue analysis in all dominated blocks. |
85 const ZoneList<HBasicBlock*>* dominated_blocks(block->dominated_blocks()); | 107 const ZoneList<HBasicBlock*>* dominated_blocks(block->dominated_blocks()); |
86 if (!dominated_blocks->is_empty()) { | 108 if (!dominated_blocks->is_empty()) { |
87 // Continue with first dominated block, and push the | 109 // Continue with first dominated block, and push the |
88 // remaining blocks on the stack (in reverse order). | 110 // remaining blocks on the stack (in reverse order). |
89 int last_changed_range = changed_ranges_.length(); | 111 int last_changed_range = changed_ranges_.length(); |
90 for (int i = dominated_blocks->length() - 1; i > 0; --i) { | 112 for (int i = dominated_blocks->length() - 1; i > 0; --i) { |
91 stack.Add(Pending(dominated_blocks->at(i), last_changed_range), zone()); | 113 stack.Add(Pending(dominated_blocks->at(i), last_changed_range), zone()); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 TraceRange("Original range was [%d,%d]\n", | 212 TraceRange("Original range was [%d,%d]\n", |
191 original_range->lower(), | 213 original_range->lower(), |
192 original_range->upper()); | 214 original_range->upper()); |
193 } | 215 } |
194 TraceRange("New information was [%d,%d]\n", | 216 TraceRange("New information was [%d,%d]\n", |
195 range->lower(), | 217 range->lower(), |
196 range->upper()); | 218 range->upper()); |
197 } | 219 } |
198 | 220 |
199 | 221 |
| 222 void HRangeAnalysisPhase::PropagateMinusZeroChecks(HValue* value) { |
| 223 ASSERT(worklist_.is_empty()); |
| 224 ASSERT(in_worklist_.IsEmpty()); |
| 225 |
| 226 AddToWorklist(value); |
| 227 while (!worklist_.is_empty()) { |
| 228 value = worklist_.RemoveLast(); |
| 229 |
| 230 if (value->IsPhi()) { |
| 231 // For phis, we must propagate the check to all of its inputs. |
| 232 HPhi* phi = HPhi::cast(value); |
| 233 for (int i = 0; i < phi->OperandCount(); ++i) { |
| 234 AddToWorklist(phi->OperandAt(i)); |
| 235 } |
| 236 } else if (value->IsUnaryMathOperation()) { |
| 237 HUnaryMathOperation* instr = HUnaryMathOperation::cast(value); |
| 238 if (instr->representation().IsSmiOrInteger32() && |
| 239 !instr->value()->representation().Equals(instr->representation())) { |
| 240 if (instr->value()->range() == NULL || |
| 241 instr->value()->range()->CanBeMinusZero()) { |
| 242 instr->SetFlag(HValue::kBailoutOnMinusZero); |
| 243 } |
| 244 } |
| 245 if (instr->RequiredInputRepresentation(0).IsSmiOrInteger32() && |
| 246 instr->representation().Equals( |
| 247 instr->RequiredInputRepresentation(0))) { |
| 248 AddToWorklist(instr->value()); |
| 249 } |
| 250 } else if (value->IsChange()) { |
| 251 HChange* instr = HChange::cast(value); |
| 252 if (!instr->from().IsSmiOrInteger32() && |
| 253 !instr->CanTruncateToInt32() && |
| 254 (instr->value()->range() == NULL || |
| 255 instr->value()->range()->CanBeMinusZero())) { |
| 256 instr->SetFlag(HValue::kBailoutOnMinusZero); |
| 257 } |
| 258 } else if (value->IsForceRepresentation()) { |
| 259 HForceRepresentation* instr = HForceRepresentation::cast(value); |
| 260 AddToWorklist(instr->value()); |
| 261 } else if (value->IsMod()) { |
| 262 HMod* instr = HMod::cast(value); |
| 263 if (instr->range() == NULL || instr->range()->CanBeMinusZero()) { |
| 264 instr->SetFlag(HValue::kBailoutOnMinusZero); |
| 265 AddToWorklist(instr->left()); |
| 266 } |
| 267 } else if (value->IsDiv() || value->IsMul()) { |
| 268 HBinaryOperation* instr = HBinaryOperation::cast(value); |
| 269 if (instr->range() == NULL || instr->range()->CanBeMinusZero()) { |
| 270 instr->SetFlag(HValue::kBailoutOnMinusZero); |
| 271 } |
| 272 AddToWorklist(instr->right()); |
| 273 AddToWorklist(instr->left()); |
| 274 } else if (value->IsMathFloorOfDiv()) { |
| 275 HMathFloorOfDiv* instr = HMathFloorOfDiv::cast(value); |
| 276 instr->SetFlag(HValue::kBailoutOnMinusZero); |
| 277 } else if (value->IsAdd() || value->IsSub()) { |
| 278 HBinaryOperation* instr = HBinaryOperation::cast(value); |
| 279 if (instr->range() == NULL || instr->range()->CanBeMinusZero()) { |
| 280 // Propagate to the left argument. If the left argument cannot be -0, |
| 281 // then the result of the add/sub operation cannot be either. |
| 282 AddToWorklist(instr->left()); |
| 283 } |
| 284 } else if (value->IsMathMinMax()) { |
| 285 HMathMinMax* instr = HMathMinMax::cast(value); |
| 286 AddToWorklist(instr->right()); |
| 287 AddToWorklist(instr->left()); |
| 288 } |
| 289 } |
| 290 |
| 291 in_worklist_.Clear(); |
| 292 ASSERT(in_worklist_.IsEmpty()); |
| 293 ASSERT(worklist_.is_empty()); |
| 294 } |
| 295 |
| 296 |
200 } } // namespace v8::internal | 297 } } // namespace v8::internal |
OLD | NEW |