| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 namespace internal { | 47 namespace internal { |
| 48 | 48 |
| 49 #define DEFINE_COMPILE(type) \ | 49 #define DEFINE_COMPILE(type) \ |
| 50 LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \ | 50 LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \ |
| 51 return builder->Do##type(this); \ | 51 return builder->Do##type(this); \ |
| 52 } | 52 } |
| 53 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) | 53 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) |
| 54 #undef DEFINE_COMPILE | 54 #undef DEFINE_COMPILE |
| 55 | 55 |
| 56 | 56 |
| 57 bool NumericRelationTable::IsInTable(int value_id, |
| 58 NumericRelation relation, |
| 59 int other_value_id, |
| 60 int offset, |
| 61 int scale, |
| 62 int block_id, |
| 63 bool* result) { |
| 64 NumericRelationTableElement element(value_id, relation, other_value_id, |
| 65 offset, scale, block_id, false); |
| 66 int index = FindInsertionPoint(element, result); |
| 67 return index < 0; |
| 68 } |
| 69 |
| 70 |
| 71 void NumericRelationTable::AddToTable(int value_id, |
| 72 NumericRelation relation, |
| 73 int other_value_id, |
| 74 int offset, |
| 75 int scale, |
| 76 int block_id, |
| 77 bool result) { |
| 78 NumericRelationTableElement element(value_id, relation, other_value_id, |
| 79 offset, scale, block_id, result); |
| 80 bool res; |
| 81 int index = FindInsertionPoint(element, &res); |
| 82 if (index >= 0) { |
| 83 Insert(element, index); |
| 84 } |
| 85 } |
| 86 |
| 87 |
| 88 void NumericRelationTable::Clear() { |
| 89 table_.Clear(); |
| 90 } |
| 91 |
| 92 |
| 93 int NumericRelationTable::FindInsertionPoint( |
| 94 const NumericRelationTableElement& element, |
| 95 bool* result) { |
| 96 int lower = 0; |
| 97 int upper = table_.length(); |
| 98 if (upper == 0) return 0; |
| 99 |
| 100 while (true) { |
| 101 int middle = (lower + upper) >> 1; |
| 102 |
| 103 int comparison = element.Compare(table_.at(middle)); |
| 104 if (comparison > 0) { |
| 105 if (lower == middle) { |
| 106 if (upper < table_.length()) { |
| 107 if (element.Compare(table_.at(upper)) == 0) { |
| 108 *result = table_.at(upper).result(); |
| 109 return -1; |
| 110 } else { |
| 111 return upper; |
| 112 } |
| 113 } else { |
| 114 return upper; |
| 115 } |
| 116 } else { |
| 117 lower = middle; |
| 118 } |
| 119 } else if (comparison < 0) { |
| 120 if (upper == middle) { |
| 121 return middle; |
| 122 } else { |
| 123 upper = middle; |
| 124 } |
| 125 } else { |
| 126 *result = table_.at(middle).result(); |
| 127 return -1; |
| 128 } |
| 129 } |
| 130 } |
| 131 |
| 132 |
| 133 void NumericRelationTable::Insert(const NumericRelationTableElement& element, |
| 134 int index) { |
| 135 table_.InsertAt(index, element, zone_); |
| 136 } |
| 137 |
| 138 |
| 57 int HValue::LoopWeight() const { | 139 int HValue::LoopWeight() const { |
| 58 const int w = FLAG_loop_weight; | 140 const int w = FLAG_loop_weight; |
| 59 static const int weights[] = { 1, w, w*w, w*w*w, w*w*w*w }; | 141 static const int weights[] = { 1, w, w*w, w*w*w, w*w*w*w }; |
| 60 return weights[Min(block()->LoopNestingDepth(), | 142 return weights[Min(block()->LoopNestingDepth(), |
| 61 static_cast<int>(ARRAY_SIZE(weights)-1))]; | 143 static_cast<int>(ARRAY_SIZE(weights)-1))]; |
| 62 } | 144 } |
| 63 | 145 |
| 64 | 146 |
| 65 Isolate* HValue::isolate() const { | 147 Isolate* HValue::isolate() const { |
| 66 ASSERT(block() != NULL); | 148 ASSERT(block() != NULL); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) { | 228 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) { |
| 147 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 229 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 148 h_infer->AddToWorklist(it.value()); | 230 h_infer->AddToWorklist(it.value()); |
| 149 } | 231 } |
| 150 for (int i = 0; i < OperandCount(); ++i) { | 232 for (int i = 0; i < OperandCount(); ++i) { |
| 151 h_infer->AddToWorklist(OperandAt(i)); | 233 h_infer->AddToWorklist(OperandAt(i)); |
| 152 } | 234 } |
| 153 } | 235 } |
| 154 | 236 |
| 155 | 237 |
| 156 // This method is recursive but it is guaranteed to terminate because | |
| 157 // RedefinedOperand() always dominates "this". | |
| 158 bool HValue::IsRelationTrue(NumericRelation relation, | 238 bool HValue::IsRelationTrue(NumericRelation relation, |
| 159 HValue* other, | 239 HValue* other, |
| 160 int offset, | 240 int offset, |
| 161 int scale) { | 241 int scale) { |
| 162 if (this == other) { | 242 bool result; |
| 163 return scale == 0 && relation.IsExtendable(offset); | 243 if (block()->graph()->HasRelationBeenEvaluated( |
| 244 this, relation, other, offset, scale, block(), &result)) { |
| 245 return result; |
| 246 } |
| 247 |
| 248 result = EvaluateRelationRecursively(relation, other, offset, scale); |
| 249 |
| 250 block()->graph()->AddRelationToTable( |
| 251 this, relation, other, offset, scale, block(), result); |
| 252 return result; |
| 253 } |
| 254 |
| 255 |
| 256 // This method is a recursive graph walk but it is guaranteed to terminate |
| 257 // because RedefinedOperand() always dominates "this" and phis will check |
| 258 // the "kNumericConstraintEvaluationInProgress" flag and never re-evaluate |
| 259 // themselves. |
| 260 bool HValue::EvaluateRelationRecursively(NumericRelation relation, |
| 261 HValue* other, |
| 262 int offset, |
| 263 int scale) { |
| 264 if (ActualValue() == other->ActualValue()) { |
| 265 return scale == 0 && relation.ImpliedByEquality(offset); |
| 164 } | 266 } |
| 165 | 267 |
| 166 // Test the direct relation. | 268 // Test the direct relation. |
| 167 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; | 269 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; |
| 168 | 270 |
| 169 // If scale is 0 try the reversed relation. | 271 // If scale is 0 try the reversed relation. |
| 170 if (scale == 0 && | 272 if (scale == 0 && |
| 171 // TODO(mmassi): do we need the full, recursive IsRelationTrue? | 273 // TODO(mmassi): do we need the full, recursive IsRelationTrue? |
| 172 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { | 274 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { |
| 173 return true; | 275 return true; |
| 174 } | 276 } |
| 175 | 277 |
| 176 // Try decomposition (but do not accept scaled compounds). | 278 // Try decomposition, but only if we are not scaled. |
| 177 DecompositionResult decomposition; | 279 DecompositionResult decomposition; |
| 178 if (TryDecompose(&decomposition) && | 280 if (scale == 0 && TryDecompose(&decomposition)) { |
| 179 decomposition.scale() == 0 && | 281 // Check if the compound is scaled. |
| 180 decomposition.base()->IsRelationTrue(relation, other, | 282 if (decomposition.scale() == 0) { |
| 181 offset + decomposition.offset(), | 283 // Non-scaled compounds can be handled normally. |
| 182 scale)) { | 284 if (decomposition.base()->IsRelationTrue( |
| 183 return true; | 285 relation, other, offset + decomposition.offset(), scale)) { |
| 286 return true; |
| 287 } |
| 288 } else if (decomposition.offset() == 0 && offset == 0) { |
| 289 // We only have a scale value which means that we can apply chaining |
| 290 // using relation extensibility: negative scales grow values (positive |
| 291 // direction), positive scales make them smaller (negative direction). |
| 292 // As a concrete example: "(x << 1) <= 0" <== "x <= 0". |
| 293 int direction = -decomposition.scale(); |
| 294 if (relation.IsExtendable(direction) && |
| 295 decomposition.base()->IsRelationTrue(relation, other, 0, 0)) { |
| 296 return true; |
| 297 } |
| 298 |
| 299 } else { |
| 300 // Just test for "same value" relation extensibility. |
| 301 |
| 302 if (decomposition.base() == other) { |
| 303 // The direction of the extensibility test is determined by scale and |
| 304 // offset, but we can not handle all combinations. |
| 305 int direction = 0; |
| 306 // Do not accept left shifts greater than 1. |
| 307 if (decomposition.scale() <= -1) { |
| 308 if (decomposition.offset() == 0) { |
| 309 // A positive scale makes values smaller. |
| 310 direction = -decomposition.scale(); |
| 311 } else { |
| 312 // If offset and scale have different signs they both go in the |
| 313 // same direction, otherwise we cannot handle the combination. |
| 314 if (decomposition.offset() * decomposition.scale() < 0) { |
| 315 direction = offset; |
| 316 } |
| 317 } |
| 318 } |
| 319 |
| 320 if (relation.ImpliedByEquality(direction)) { |
| 321 return true; |
| 322 } |
| 323 } |
| 324 } |
| 184 } | 325 } |
| 185 | 326 |
| 186 // Pass the request to the redefined value. | 327 // Pass the request to the redefined value. |
| 187 HValue* redefined = RedefinedOperand(); | 328 HValue* redefined = RedefinedOperand(); |
| 188 return redefined != NULL && redefined->IsRelationTrue(relation, other, | 329 return redefined != NULL && redefined->IsRelationTrue(relation, other, |
| 189 offset, scale); | 330 offset, scale); |
| 190 } | 331 } |
| 191 | 332 |
| 192 | 333 |
| 193 bool HValue::TryGuaranteeRange(HValue* upper_bound) { | 334 bool HValue::TryGuaranteeRange(HValue* upper_bound, |
| 194 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound); | 335 HBasicBlock* starting_block_for_hoisting) { |
| 336 if (starting_block_for_hoisting == NULL) { |
| 337 starting_block_for_hoisting = block(); |
| 338 } |
| 339 |
| 340 bool lower_done, upper_done, lower_result, upper_result; |
| 341 lower_done = block()->graph()->HasRelationBeenEvaluated( |
| 342 this, NumericRelation::Ge(), block()->graph()->GetConstant0(), |
| 343 0, 0, starting_block_for_hoisting, &lower_result); |
| 344 upper_done = block()->graph()->HasRelationBeenEvaluated( |
| 345 this, NumericRelation::Lt(), upper_bound, |
| 346 0, 0, starting_block_for_hoisting, &upper_result); |
| 347 if (lower_done && upper_done) return lower_result && upper_result; |
| 348 |
| 349 RangeEvaluationContext context = RangeEvaluationContext( |
| 350 this, upper_bound, starting_block_for_hoisting); |
| 195 TryGuaranteeRangeRecursive(&context); | 351 TryGuaranteeRangeRecursive(&context); |
| 196 bool result = context.is_range_satisfied(); | 352 bool result = context.is_range_satisfied(); |
| 197 if (result) { | 353 if (result) { |
| 198 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); | 354 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); |
| 199 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); | 355 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); |
| 200 } | 356 } |
| 357 |
| 358 block()->graph()->AddRelationToTable( |
| 359 this, NumericRelation::Ge(), block()->graph()->GetConstant0(), 0, 0, |
| 360 starting_block_for_hoisting, context.lower_bound_guarantee() != NULL); |
| 361 block()->graph()->AddRelationToTable( |
| 362 this, NumericRelation::Lt(), upper_bound, 0, 0, |
| 363 starting_block_for_hoisting, context.upper_bound_guarantee() != NULL); |
| 364 |
| 201 return result; | 365 return result; |
| 202 } | 366 } |
| 203 | 367 |
| 204 | 368 |
| 205 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) { | 369 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) { |
| 206 // Check if we already know that this value satisfies the lower bound. | 370 // Check if we already know that this value satisfies the lower bound. |
| 207 if (context->lower_bound_guarantee() == NULL) { | 371 if (context->lower_bound_guarantee() == NULL) { |
| 208 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(), | 372 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(), |
| 209 context->offset(), context->scale())) { | 373 context->offset(), context->scale())) { |
| 210 context->set_lower_bound_guarantee(this); | 374 context->set_lower_bound_guarantee(this); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 238 context->swap_candidate(&decomposition); | 402 context->swap_candidate(&decomposition); |
| 239 } | 403 } |
| 240 if (context->is_range_satisfied()) return; | 404 if (context->is_range_satisfied()) return; |
| 241 | 405 |
| 242 // Try to modify this to satisfy the constraint. | 406 // Try to modify this to satisfy the constraint. |
| 243 | 407 |
| 244 TryGuaranteeRangeChanging(context); | 408 TryGuaranteeRangeChanging(context); |
| 245 } | 409 } |
| 246 | 410 |
| 247 | 411 |
| 248 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper) | 412 RangeEvaluationContext::RangeEvaluationContext(HValue* value, |
| 249 : lower_bound_(upper->block()->graph()->GetConstant0()), | 413 HValue* upper, |
| 414 HBasicBlock* starting_block) |
| 415 : starting_block_(starting_block), |
| 416 lower_bound_(upper->block()->graph()->GetConstant0()), |
| 250 lower_bound_guarantee_(NULL), | 417 lower_bound_guarantee_(NULL), |
| 251 candidate_(value), | 418 candidate_(value), |
| 252 upper_bound_(upper), | 419 upper_bound_(upper), |
| 253 upper_bound_guarantee_(NULL), | 420 upper_bound_guarantee_(NULL), |
| 254 offset_(0), | 421 offset_(0), |
| 255 scale_(0) { | 422 scale_(0) { |
| 256 } | 423 } |
| 257 | 424 |
| 258 | 425 |
| 259 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { | 426 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { |
| (...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 } | 1094 } |
| 928 } | 1095 } |
| 929 } | 1096 } |
| 930 #endif | 1097 #endif |
| 931 | 1098 |
| 932 | 1099 |
| 933 HNumericConstraint* HNumericConstraint::AddToGraph( | 1100 HNumericConstraint* HNumericConstraint::AddToGraph( |
| 934 HValue* constrained_value, | 1101 HValue* constrained_value, |
| 935 NumericRelation relation, | 1102 NumericRelation relation, |
| 936 HValue* related_value, | 1103 HValue* related_value, |
| 937 HInstruction* insertion_point) { | 1104 HInstruction* insertion_point, |
| 1105 HBasicBlock* jump_target_when_false) { |
| 938 if (insertion_point == NULL) { | 1106 if (insertion_point == NULL) { |
| 939 if (constrained_value->IsInstruction()) { | 1107 if (constrained_value->IsInstruction()) { |
| 940 insertion_point = HInstruction::cast(constrained_value); | 1108 insertion_point = HInstruction::cast(constrained_value); |
| 941 } else if (constrained_value->IsPhi()) { | 1109 } else if (constrained_value->IsPhi()) { |
| 942 insertion_point = constrained_value->block()->first(); | 1110 insertion_point = constrained_value->block()->first(); |
| 943 } else { | 1111 } else { |
| 944 UNREACHABLE(); | 1112 UNREACHABLE(); |
| 945 } | 1113 } |
| 946 } | 1114 } |
| 947 HNumericConstraint* result = | 1115 HNumericConstraint* result = |
| 948 new(insertion_point->block()->zone()) HNumericConstraint( | 1116 new(insertion_point->block()->zone()) HNumericConstraint( |
| 949 constrained_value, relation, related_value); | 1117 constrained_value, relation, related_value, jump_target_when_false); |
| 950 result->InsertAfter(insertion_point); | 1118 result->InsertAfter(insertion_point); |
| 951 return result; | 1119 return result; |
| 952 } | 1120 } |
| 953 | 1121 |
| 954 | 1122 |
| 955 void HNumericConstraint::PrintDataTo(StringStream* stream) { | 1123 void HNumericConstraint::PrintDataTo(StringStream* stream) { |
| 956 stream->Add("("); | 1124 stream->Add("("); |
| 957 constrained_value()->PrintNameTo(stream); | 1125 constrained_value()->PrintNameTo(stream); |
| 958 stream->Add(" %s ", relation().Mnemonic()); | 1126 stream->Add(" %s ", relation().Mnemonic()); |
| 959 related_value()->PrintNameTo(stream); | 1127 related_value()->PrintNameTo(stream); |
| 960 stream->Add(")"); | 1128 stream->Add(")"); |
| 961 } | 1129 } |
| 962 | 1130 |
| 963 | 1131 |
| 964 HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph( | 1132 HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph( |
| 965 HPhi* phi, | 1133 HPhi* phi, |
| 966 NumericRelation relation, | 1134 NumericRelation relation, |
| 967 int operand_index) { | 1135 int operand_index) { |
| 968 HInductionVariableAnnotation* result = | 1136 HInductionVariableAnnotation* result = new(phi->block()->zone()) |
| 969 new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation, | 1137 HInductionVariableAnnotation(phi, relation, operand_index, |
| 970 operand_index); | 1138 phi->block()->zone()); |
| 971 result->InsertAfter(phi->block()->first()); | 1139 result->InsertAfter(phi->block()->first()); |
| 972 return result; | 1140 return result; |
| 973 } | 1141 } |
| 974 | 1142 |
| 975 | 1143 |
| 1144 void HInductionVariableAnnotation::AddHoistedCheck(HBoundsCheck* check) { |
| 1145 hoisted_checks_.Add(check, block()->zone()); |
| 1146 } |
| 1147 |
| 1148 |
| 1149 HInductionVariableAnnotation::HInductionVariableAnnotation( |
| 1150 HPhi* phi, |
| 1151 NumericRelation relation, |
| 1152 int operand_index, |
| 1153 Zone* zone) |
| 1154 : HUnaryOperation(phi), |
| 1155 phi_(phi), |
| 1156 relation_(relation), |
| 1157 operand_index_(operand_index), |
| 1158 hoisted_checks_(4, zone) { |
| 1159 } |
| 1160 |
| 1161 |
| 1162 void HInductionVariableAnnotation::TryGuaranteeRangeChanging( |
| 1163 RangeEvaluationContext* context) { |
| 1164 if (relation().IsExtendable(1)) { |
| 1165 if (context->lower_bound_guarantee() == NULL) return; |
| 1166 } else { |
| 1167 return; |
| 1168 } |
| 1169 |
| 1170 for (int i = 0; i < hoisted_checks()->length(); i++) { |
| 1171 HBoundsCheck* hoisted_check = hoisted_checks()->at(i); |
| 1172 if (hoisted_check->length()->ActualValue() == |
| 1173 context->upper_bound()->ActualValue()) { |
| 1174 context->set_upper_bound_guarantee(hoisted_check); |
| 1175 return; |
| 1176 } |
| 1177 } |
| 1178 |
| 1179 HBasicBlock* starting_block = context->starting_block(); |
| 1180 HLoopInformation* starting_loop = starting_block->current_loop(); |
| 1181 if (starting_loop == NULL) return; |
| 1182 HLoopInformation* my_loop = block()->current_loop(); |
| 1183 if (my_loop == NULL) return; |
| 1184 if (my_loop->exits_count() > 1 |
| 1185 && !block()->graph()->use_optimistic_licm()) return; |
| 1186 if (!my_loop->IsNestedInThisLoop(starting_loop)) return; |
| 1187 |
| 1188 for (HValue* candidate = context->candidate(); |
| 1189 candidate != NULL; |
| 1190 candidate = candidate->RedefinedOperand()) { |
| 1191 if (!candidate->IsNumericConstraint()) continue; |
| 1192 |
| 1193 HNumericConstraint* constraint = HNumericConstraint::cast(candidate); |
| 1194 if (!constraint->relation().IsExtendable(-1)) continue; |
| 1195 HLoopInformation* other_loop = |
| 1196 constraint->jump_target_when_false()->current_loop(); |
| 1197 if (other_loop == my_loop) continue; |
| 1198 |
| 1199 HBasicBlock* my_header = my_loop->loop_header(); |
| 1200 HBasicBlock* my_pre_header = my_header->predecessors()->at(0); |
| 1201 |
| 1202 HValue* induction_limit = constraint->related_value()->ActualValue(); |
| 1203 HValue* upper_bound = context->upper_bound()->ActualValue(); |
| 1204 |
| 1205 if (induction_limit->block() != my_pre_header && |
| 1206 !induction_limit->block()->Dominates(my_pre_header)) { |
| 1207 continue; |
| 1208 } |
| 1209 if (upper_bound->block() != my_pre_header && |
| 1210 !upper_bound->block()->Dominates(my_pre_header)) { |
| 1211 continue; |
| 1212 } |
| 1213 |
| 1214 if (!(induction_limit->representation().Equals( |
| 1215 upper_bound->representation()) || |
| 1216 induction_limit->IsInteger32Constant())) { |
| 1217 continue; |
| 1218 } |
| 1219 |
| 1220 block()->graph()->ClearRelationsTable(); |
| 1221 |
| 1222 HBoundsCheck* check = new(block()->zone()) HBoundsCheck( |
| 1223 induction_limit, upper_bound); |
| 1224 check->InsertBefore(my_pre_header->end()); |
| 1225 check->set_allow_equality(true); |
| 1226 check->UpdateRedefinedUses(); |
| 1227 AddHoistedCheck(check); |
| 1228 context->set_upper_bound_guarantee(check); |
| 1229 return; |
| 1230 } |
| 1231 } |
| 1232 |
| 1233 |
| 976 void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) { | 1234 void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) { |
| 977 stream->Add("("); | 1235 stream->Add("("); |
| 978 RedefinedOperand()->PrintNameTo(stream); | 1236 RedefinedOperand()->PrintNameTo(stream); |
| 979 stream->Add(" %s ", relation().Mnemonic()); | 1237 stream->Add(" %s ", relation().Mnemonic()); |
| 980 induction_base()->PrintNameTo(stream); | 1238 induction_base()->PrintNameTo(stream); |
| 981 stream->Add(")"); | 1239 stream->Add(")"); |
| 982 } | 1240 } |
| 983 | 1241 |
| 984 | 1242 |
| 985 void HDummyUse::PrintDataTo(StringStream* stream) { | 1243 void HDummyUse::PrintDataTo(StringStream* stream) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1002 stream->Add("#%d", argument_count()); | 1260 stream->Add("#%d", argument_count()); |
| 1003 } | 1261 } |
| 1004 | 1262 |
| 1005 | 1263 |
| 1006 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | 1264 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { |
| 1007 if (context->candidate()->ActualValue() != base()->ActualValue() || | 1265 if (context->candidate()->ActualValue() != base()->ActualValue() || |
| 1008 context->scale() < scale()) { | 1266 context->scale() < scale()) { |
| 1009 return; | 1267 return; |
| 1010 } | 1268 } |
| 1011 | 1269 |
| 1270 // Make so that the strongest possible checks are used as guarantees. |
| 1271 if (context->lower_bound_guarantee() != NULL && |
| 1272 context->lower_bound_guarantee() != this) { |
| 1273 if (context->lower_bound_guarantee()->IsBoundsCheck()) { |
| 1274 HBoundsCheck* guarantee = HBoundsCheck::cast( |
| 1275 context->lower_bound_guarantee()); |
| 1276 if (guarantee->base()->ActualValue() == base()->ActualValue() |
| 1277 && guarantee->scale() == scale() |
| 1278 && guarantee->offset() > offset()) { |
| 1279 context->set_lower_bound_guarantee(this); |
| 1280 } |
| 1281 } |
| 1282 } |
| 1283 if (context->upper_bound_guarantee() != NULL && |
| 1284 context->upper_bound_guarantee() != this) { |
| 1285 if (context->upper_bound_guarantee()->IsBoundsCheck()) { |
| 1286 HBoundsCheck* guarantee = HBoundsCheck::cast( |
| 1287 context->upper_bound_guarantee()); |
| 1288 if (guarantee->base()->ActualValue() == base()->ActualValue() |
| 1289 && guarantee->scale() == scale() |
| 1290 && guarantee->offset() < offset()) { |
| 1291 context->set_upper_bound_guarantee(this); |
| 1292 } |
| 1293 } |
| 1294 } |
| 1295 |
| 1012 // TODO(mmassi) | 1296 // TODO(mmassi) |
| 1013 // Instead of checking for "same basic block" we should check for | 1297 // Instead of checking for "same basic block" we should check for |
| 1014 // "dominates and postdominates". | 1298 // "dominates and postdominates". |
| 1015 if (context->upper_bound() == length() && | 1299 if (context->upper_bound() == length() && |
| 1016 context->lower_bound_guarantee() != NULL && | 1300 context->lower_bound_guarantee() != NULL && |
| 1017 context->lower_bound_guarantee() != this && | 1301 context->lower_bound_guarantee() != this && |
| 1018 context->lower_bound_guarantee()->block() != block() && | 1302 context->lower_bound_guarantee()->block() == block() && |
| 1019 offset() < context->offset() && | 1303 offset() < context->offset() && |
| 1020 index_can_increase() && | 1304 index_can_increase() && |
| 1021 context->upper_bound_guarantee() == NULL) { | 1305 context->upper_bound_guarantee() == NULL) { |
| 1022 offset_ = context->offset(); | 1306 offset_ = context->offset(); |
| 1023 SetResponsibilityForRange(DIRECTION_UPPER); | 1307 SetResponsibilityForRange(DIRECTION_UPPER); |
| 1024 context->set_upper_bound_guarantee(this); | 1308 context->set_upper_bound_guarantee(this); |
| 1309 block()->graph()->ClearRelationsTable(); |
| 1025 } else if (context->upper_bound_guarantee() != NULL && | 1310 } else if (context->upper_bound_guarantee() != NULL && |
| 1026 context->upper_bound_guarantee() != this && | 1311 context->upper_bound_guarantee() != this && |
| 1027 context->upper_bound_guarantee()->block() != block() && | 1312 context->upper_bound_guarantee()->block() == block() && |
| 1028 offset() > context->offset() && | 1313 offset() > context->offset() && |
| 1029 index_can_decrease() && | 1314 index_can_decrease() && |
| 1030 context->lower_bound_guarantee() == NULL) { | 1315 context->lower_bound_guarantee() == NULL) { |
| 1031 offset_ = context->offset(); | 1316 offset_ = context->offset(); |
| 1032 SetResponsibilityForRange(DIRECTION_LOWER); | 1317 SetResponsibilityForRange(DIRECTION_LOWER); |
| 1033 context->set_lower_bound_guarantee(this); | 1318 context->set_lower_bound_guarantee(this); |
| 1319 block()->graph()->ClearRelationsTable(); |
| 1034 } | 1320 } |
| 1035 } | 1321 } |
| 1036 | 1322 |
| 1037 | 1323 |
| 1038 void HBoundsCheck::ApplyIndexChange() { | 1324 void HBoundsCheck::ApplyIndexChange() { |
| 1039 if (skip_check()) return; | 1325 if (skip_check() || base() == NULL) return; |
| 1040 | 1326 |
| 1041 DecompositionResult decomposition; | 1327 DecompositionResult decomposition; |
| 1042 bool index_is_decomposable = index()->TryDecompose(&decomposition); | 1328 bool index_is_decomposable = index()->TryDecompose(&decomposition); |
| 1043 if (index_is_decomposable) { | 1329 if (index_is_decomposable) { |
| 1044 ASSERT(decomposition.base() == base()); | 1330 ASSERT(decomposition.base() == base()); |
| 1045 if (decomposition.offset() == offset() && | 1331 if (decomposition.offset() == offset() && |
| 1046 decomposition.scale() == scale()) return; | 1332 decomposition.scale() == scale()) return; |
| 1047 } else { | 1333 } else { |
| 1048 return; | 1334 return; |
| 1049 } | 1335 } |
| 1050 | 1336 |
| 1051 ReplaceAllUsesWith(index()); | 1337 ReplaceAllUsesWith(index()); |
| 1052 | 1338 |
| 1053 HValue* current_index = decomposition.base(); | 1339 HValue* current_index = decomposition.base(); |
| 1054 int actual_offset = decomposition.offset() + offset(); | |
| 1055 int actual_scale = decomposition.scale() + scale(); | |
| 1056 | 1340 |
| 1057 if (actual_offset != 0) { | 1341 if (offset() != 0) { |
| 1058 HConstant* add_offset = new(block()->graph()->zone()) HConstant( | 1342 HConstant* add_offset = new(block()->graph()->zone()) HConstant( |
| 1059 actual_offset, index()->representation()); | 1343 offset(), index()->representation()); |
| 1060 add_offset->InsertBefore(this); | 1344 add_offset->InsertBefore(this); |
| 1061 HInstruction* add = HAdd::New(block()->graph()->zone(), | 1345 HInstruction* add = HAdd::New(block()->graph()->zone(), |
| 1062 block()->graph()->GetInvalidContext(), current_index, add_offset); | 1346 block()->graph()->GetInvalidContext(), current_index, add_offset); |
| 1063 add->InsertBefore(this); | 1347 add->InsertBefore(this); |
| 1064 add->AssumeRepresentation(index()->representation()); | 1348 add->AssumeRepresentation(index()->representation()); |
| 1065 current_index = add; | 1349 current_index = add; |
| 1066 } | 1350 } |
| 1067 | 1351 |
| 1068 if (actual_scale != 0) { | 1352 if (scale() != 0) { |
| 1069 HConstant* sar_scale = new(block()->graph()->zone()) HConstant( | 1353 HConstant* sar_scale = new(block()->graph()->zone()) HConstant( |
| 1070 actual_scale, index()->representation()); | 1354 scale(), index()->representation()); |
| 1071 sar_scale->InsertBefore(this); | 1355 sar_scale->InsertBefore(this); |
| 1072 HInstruction* sar = HSar::New(block()->graph()->zone(), | 1356 HInstruction* sar = HSar::New(block()->graph()->zone(), |
| 1073 block()->graph()->GetInvalidContext(), current_index, sar_scale); | 1357 block()->graph()->GetInvalidContext(), current_index, sar_scale); |
| 1074 sar->InsertBefore(this); | 1358 sar->InsertBefore(this); |
| 1075 sar->AssumeRepresentation(index()->representation()); | 1359 sar->AssumeRepresentation(index()->representation()); |
| 1076 current_index = sar; | 1360 current_index = sar; |
| 1077 } | 1361 } |
| 1078 | 1362 |
| 1079 SetOperandAt(0, current_index); | 1363 SetOperandAt(0, current_index); |
| 1080 | 1364 |
| 1081 base_ = NULL; | 1365 base_ = NULL; |
| 1082 offset_ = 0; | 1366 offset_ = 0; |
| 1083 scale_ = 0; | 1367 scale_ = 0; |
| 1084 responsibility_direction_ = DIRECTION_NONE; | 1368 responsibility_direction_ = DIRECTION_NONE; |
| 1085 } | 1369 } |
| 1086 | 1370 |
| 1087 | 1371 |
| 1088 void HBoundsCheck::AddInformativeDefinitions() { | 1372 void HBoundsCheck::AddInformativeDefinitions() { |
| 1089 // TODO(mmassi): Executing this code during AddInformativeDefinitions | 1373 if (DetectCompoundIndex()) { |
| 1090 // is a hack. Move it to some other HPhase. | 1374 HBoundsCheckBaseIndexInformation* base_index_info = |
| 1091 if (FLAG_array_bounds_checks_elimination) { | 1375 new(block()->graph()->zone()) |
| 1092 if (index()->TryGuaranteeRange(length())) { | 1376 HBoundsCheckBaseIndexInformation(this); |
| 1093 set_skip_check(true); | 1377 base_index_info->InsertAfter(this); |
| 1094 } | |
| 1095 if (DetectCompoundIndex()) { | |
| 1096 HBoundsCheckBaseIndexInformation* base_index_info = | |
| 1097 new(block()->graph()->zone()) | |
| 1098 HBoundsCheckBaseIndexInformation(this); | |
| 1099 base_index_info->InsertAfter(this); | |
| 1100 } | |
| 1101 } | 1378 } |
| 1102 } | 1379 } |
| 1103 | 1380 |
| 1104 | 1381 |
| 1105 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, | 1382 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, |
| 1106 HValue* related_value, | 1383 HValue* related_value, |
| 1107 int offset, | 1384 int offset, |
| 1108 int scale) { | 1385 int scale) { |
| 1109 if (related_value == length()) { | 1386 if (related_value == length()) { |
| 1110 // A HBoundsCheck is smaller than the length it compared against. | 1387 // A HBoundsCheck is smaller than the length it compared against. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 } | 1435 } |
| 1159 UpdateRepresentation(r, h_infer, "boundscheck"); | 1436 UpdateRepresentation(r, h_infer, "boundscheck"); |
| 1160 } | 1437 } |
| 1161 | 1438 |
| 1162 | 1439 |
| 1163 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( | 1440 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( |
| 1164 NumericRelation relation, | 1441 NumericRelation relation, |
| 1165 HValue* related_value, | 1442 HValue* related_value, |
| 1166 int offset, | 1443 int offset, |
| 1167 int scale) { | 1444 int scale) { |
| 1445 if (bounds_check() == NULL) return false; |
| 1446 |
| 1168 if (related_value == bounds_check()->length()) { | 1447 if (related_value == bounds_check()->length()) { |
| 1169 return NumericRelation::Lt().CompoundImplies( | 1448 return NumericRelation::Lt().CompoundImplies( |
| 1170 relation, | 1449 relation, |
| 1171 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | 1450 bounds_check()->offset(), bounds_check()->scale(), offset, scale); |
| 1172 } else if (related_value == block()->graph()->GetConstant0()) { | 1451 } else if (related_value == block()->graph()->GetConstant0()) { |
| 1173 return NumericRelation::Ge().CompoundImplies( | 1452 return NumericRelation::Ge().CompoundImplies( |
| 1174 relation, | 1453 relation, |
| 1175 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | 1454 bounds_check()->offset(), bounds_check()->scale(), offset, scale); |
| 1176 } else { | 1455 } else { |
| 1177 return false; | 1456 return false; |
| 1178 } | 1457 } |
| 1179 } | 1458 } |
| 1180 | 1459 |
| 1181 | 1460 |
| 1182 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { | 1461 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { |
| 1183 stream->Add("base: "); | 1462 stream->Add("base: "); |
| 1184 base_index()->PrintNameTo(stream); | 1463 base_index()->PrintNameTo(stream); |
| 1185 stream->Add(", check: "); | 1464 stream->Add(", check: "); |
| 1186 base_index()->PrintNameTo(stream); | 1465 if (bounds_check() != NULL) { |
| 1466 bounds_check()->PrintNameTo(stream); |
| 1467 } else { |
| 1468 stream->Add("DISCONNECTED "); |
| 1469 OperandAt(1)->PrintNameTo(stream); |
| 1470 } |
| 1187 } | 1471 } |
| 1188 | 1472 |
| 1189 | 1473 |
| 1190 void HCallConstantFunction::PrintDataTo(StringStream* stream) { | 1474 void HCallConstantFunction::PrintDataTo(StringStream* stream) { |
| 1191 if (IsApplyFunction()) { | 1475 if (IsApplyFunction()) { |
| 1192 stream->Add("optimized apply "); | 1476 stream->Add("optimized apply "); |
| 1193 } else { | 1477 } else { |
| 1194 stream->Add("%o ", function()->shared()->DebugName()); | 1478 stream->Add("%o ", function()->shared()->DebugName()); |
| 1195 } | 1479 } |
| 1196 stream->Add("#%d", argument_count()); | 1480 stream->Add("#%d", argument_count()); |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 ClearFlag(HValue::kCanBeDivByZero); | 2108 ClearFlag(HValue::kCanBeDivByZero); |
| 1825 } | 2109 } |
| 1826 return result; | 2110 return result; |
| 1827 } else { | 2111 } else { |
| 1828 return HValue::InferRange(zone); | 2112 return HValue::InferRange(zone); |
| 1829 } | 2113 } |
| 1830 } | 2114 } |
| 1831 | 2115 |
| 1832 | 2116 |
| 1833 void HPhi::AddInformativeDefinitions() { | 2117 void HPhi::AddInformativeDefinitions() { |
| 1834 if (OperandCount() == 2) { | 2118 HLoopInformation* my_loop = block()->current_loop(); |
| 2119 |
| 2120 if (OperandCount() == 2 && my_loop != NULL) { |
| 1835 // If one of the operands is an OSR block give up (this cannot be an | 2121 // If one of the operands is an OSR block give up (this cannot be an |
| 1836 // induction variable). | 2122 // induction variable). |
| 1837 if (OperandAt(0)->block()->is_osr_entry() || | 2123 if (OperandAt(0)->block()->is_osr_entry() || |
| 1838 OperandAt(1)->block()->is_osr_entry()) return; | 2124 OperandAt(1)->block()->is_osr_entry()) return; |
| 1839 | 2125 |
| 1840 for (int operand_index = 0; operand_index < 2; operand_index++) { | 2126 for (int operand_index = 0; operand_index < 2; operand_index++) { |
| 1841 int other_operand_index = (operand_index + 1) % 2; | 2127 int other_operand_index = (operand_index + 1) % 2; |
| 1842 | 2128 |
| 2129 HValue* induction_base_candidate = OperandAt(other_operand_index); |
| 2130 HLoopInformation* base_block_loop = |
| 2131 induction_base_candidate->block()->current_loop(); |
| 2132 if (base_block_loop != NULL && |
| 2133 (base_block_loop == my_loop || |
| 2134 base_block_loop->IsNestedInThisLoop(my_loop))) continue; |
| 2135 |
| 1843 static NumericRelation relations[] = { | 2136 static NumericRelation relations[] = { |
| 1844 NumericRelation::Ge(), | 2137 NumericRelation::Gt(), |
| 1845 NumericRelation::Le() | 2138 NumericRelation::Lt() |
| 1846 }; | 2139 }; |
| 1847 | 2140 |
| 1848 // Check if this phi is an induction variable. If, e.g., we know that | 2141 // Check if this phi is an induction variable. If, e.g., we know that |
| 1849 // its first input is greater than the phi itself, then that must be | 2142 // its first input is greater than the phi itself, then that must be |
| 1850 // the back edge, and the phi is always greater than its second input. | 2143 // the back edge, and the phi is always greater than its second input. |
| 1851 for (int relation_index = 0; relation_index < 2; relation_index++) { | 2144 for (int relation_index = 0; relation_index < 2; relation_index++) { |
| 1852 if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index], | 2145 if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index], |
| 1853 this)) { | 2146 this)) { |
| 1854 HInductionVariableAnnotation::AddToGraph(this, | 2147 HInductionVariableAnnotation::AddToGraph(this, |
| 1855 relations[relation_index], | 2148 relations[relation_index], |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2405 stream->Add(Token::Name(token())); | 2698 stream->Add(Token::Name(token())); |
| 2406 stream->Add(" "); | 2699 stream->Add(" "); |
| 2407 HControlInstruction::PrintDataTo(stream); | 2700 HControlInstruction::PrintDataTo(stream); |
| 2408 } | 2701 } |
| 2409 | 2702 |
| 2410 | 2703 |
| 2411 void HCompareIDAndBranch::AddInformativeDefinitions() { | 2704 void HCompareIDAndBranch::AddInformativeDefinitions() { |
| 2412 NumericRelation r = NumericRelation::FromToken(token()); | 2705 NumericRelation r = NumericRelation::FromToken(token()); |
| 2413 if (r.IsNone()) return; | 2706 if (r.IsNone()) return; |
| 2414 | 2707 |
| 2415 HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first()); | |
| 2416 HNumericConstraint::AddToGraph( | 2708 HNumericConstraint::AddToGraph( |
| 2417 left(), r.Negated(), right(), SuccessorAt(1)->first()); | 2709 left(), r, right(), SuccessorAt(0)->first(), SuccessorAt(1)); |
| 2710 HNumericConstraint::AddToGraph( |
| 2711 left(), r.Negated(), right(), SuccessorAt(1)->first(), SuccessorAt(0)); |
| 2418 } | 2712 } |
| 2419 | 2713 |
| 2420 | 2714 |
| 2421 void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { | 2715 void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { |
| 2422 stream->Add(Token::Name(token())); | 2716 stream->Add(Token::Name(token())); |
| 2423 stream->Add(" "); | 2717 stream->Add(" "); |
| 2424 left()->PrintNameTo(stream); | 2718 left()->PrintNameTo(stream); |
| 2425 stream->Add(" "); | 2719 stream->Add(" "); |
| 2426 right()->PrintNameTo(stream); | 2720 right()->PrintNameTo(stream); |
| 2427 HControlInstruction::PrintDataTo(stream); | 2721 HControlInstruction::PrintDataTo(stream); |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3144 visited->Add(id()); | 3438 visited->Add(id()); |
| 3145 // Propagate to the left argument. If the left argument cannot be -0, then | 3439 // Propagate to the left argument. If the left argument cannot be -0, then |
| 3146 // the result of the sub operation cannot be either. | 3440 // the result of the sub operation cannot be either. |
| 3147 if (range() == NULL || range()->CanBeMinusZero()) { | 3441 if (range() == NULL || range()->CanBeMinusZero()) { |
| 3148 return left(); | 3442 return left(); |
| 3149 } | 3443 } |
| 3150 return NULL; | 3444 return NULL; |
| 3151 } | 3445 } |
| 3152 | 3446 |
| 3153 | 3447 |
| 3448 bool HAdd::IsRelationTrueInternal(NumericRelation relation, |
| 3449 HValue* other, |
| 3450 int offset, |
| 3451 int scale) { |
| 3452 if (offset != 0 || scale != 0) return false; |
| 3453 |
| 3454 // We look for a pattern like "x + delta rel x", where we should return |
| 3455 // true if "delta >= 0 && rel.IsExtendable(1)" or |
| 3456 // "delta <= 0 && rel.IsExtendable(-1)". |
| 3457 HValue* delta = NULL; |
| 3458 if (left()->ActualValue() == other->ActualValue()) { |
| 3459 delta = right(); |
| 3460 } else if (right()->ActualValue() == other->ActualValue()) { |
| 3461 delta = left(); |
| 3462 } else { |
| 3463 return false; |
| 3464 } |
| 3465 |
| 3466 if (relation.IsExtendable(1) && |
| 3467 delta->IsRelationTrue(NumericRelation::Ge(), |
| 3468 block()->graph()->GetConstant0())) { |
| 3469 return true; |
| 3470 } |
| 3471 |
| 3472 if (relation.IsExtendable(-1) && |
| 3473 delta->IsRelationTrue(NumericRelation::Le(), |
| 3474 block()->graph()->GetConstant0())) { |
| 3475 return true; |
| 3476 } |
| 3477 |
| 3478 return false; |
| 3479 } |
| 3480 |
| 3481 |
| 3154 bool HStoreKeyed::NeedsCanonicalization() { | 3482 bool HStoreKeyed::NeedsCanonicalization() { |
| 3155 // If value is an integer or smi or comes from the result of a keyed load or | 3483 // If value is an integer or smi or comes from the result of a keyed load or |
| 3156 // constant then it is either be a non-hole value or in the case of a constant | 3484 // constant then it is either be a non-hole value or in the case of a constant |
| 3157 // the hole is only being stored explicitly: no need for canonicalization. | 3485 // the hole is only being stored explicitly: no need for canonicalization. |
| 3158 // | 3486 // |
| 3159 // The exception to that is keyed loads from external float or double arrays: | 3487 // The exception to that is keyed loads from external float or double arrays: |
| 3160 // these can load arbitrary representation of NaN. | 3488 // these can load arbitrary representation of NaN. |
| 3161 | 3489 |
| 3162 if (value()->IsConstant()) { | 3490 if (value()->IsConstant()) { |
| 3163 return false; | 3491 return false; |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3662 | 3990 |
| 3663 | 3991 |
| 3664 void HCheckFunction::Verify() { | 3992 void HCheckFunction::Verify() { |
| 3665 HInstruction::Verify(); | 3993 HInstruction::Verify(); |
| 3666 ASSERT(HasNoUses()); | 3994 ASSERT(HasNoUses()); |
| 3667 } | 3995 } |
| 3668 | 3996 |
| 3669 #endif | 3997 #endif |
| 3670 | 3998 |
| 3671 } } // namespace v8::internal | 3999 } } // namespace v8::internal |
| OLD | NEW |