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 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) { | 142 void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) { |
143 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 143 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
144 h_infer->AddToWorklist(it.value()); | 144 h_infer->AddToWorklist(it.value()); |
145 } | 145 } |
146 for (int i = 0; i < OperandCount(); ++i) { | 146 for (int i = 0; i < OperandCount(); ++i) { |
147 h_infer->AddToWorklist(OperandAt(i)); | 147 h_infer->AddToWorklist(OperandAt(i)); |
148 } | 148 } |
149 } | 149 } |
150 | 150 |
151 | 151 |
152 // This method is recursive but it is guaranteed to terminate because | |
153 // RedefinedOperand() always dominates "this". | |
154 bool HValue::IsRelationTrue(NumericRelation relation, | |
155 HValue* other, | |
156 int offset, | |
157 int scale) { | |
158 if (this == other) { | |
159 return scale == 0 && relation.IsExtendable(offset); | |
160 } | |
161 | |
162 // Test the direct relation. | |
163 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; | |
164 | |
165 // If scale is 0 try the reversed relation. | |
166 if (scale == 0 && | |
167 // TODO(mmassi): do we need the full, recursive IsRelationTrue? | |
168 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { | |
169 return true; | |
170 } | |
171 | |
172 // Try decomposition (but do not accept scaled compounds). | |
173 DecompositionResult decomposition; | |
174 if (TryDecompose(&decomposition) && | |
175 decomposition.scale() == 0 && | |
176 decomposition.base()->IsRelationTrue(relation, other, | |
177 offset + decomposition.offset(), | |
178 scale)) { | |
179 return true; | |
180 } | |
181 | |
182 // Pass the request to the redefined value. | |
183 HValue* redefined = RedefinedOperand(); | |
184 return redefined != NULL && redefined->IsRelationTrue(relation, other, | |
185 offset, scale); | |
186 } | |
187 | |
188 | |
189 bool HValue::TryGuaranteeRange(HValue* upper_bound) { | |
190 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound); | |
191 TryGuaranteeRangeRecursive(&context); | |
192 bool result = context.is_range_satisfied(); | |
193 if (result) { | |
194 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); | |
195 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); | |
196 } | |
197 return result; | |
198 } | |
199 | |
200 | |
201 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) { | |
202 // Check if we already know that this value satisfies the lower bound. | |
203 if (context->lower_bound_guarantee() == NULL) { | |
204 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(), | |
205 context->offset(), context->scale())) { | |
206 context->set_lower_bound_guarantee(this); | |
207 } | |
208 } | |
209 | |
210 // Check if we already know that this value satisfies the upper bound. | |
211 if (context->upper_bound_guarantee() == NULL) { | |
212 if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(), | |
213 context->offset(), context->scale()) || | |
214 (context->scale() == 0 && | |
215 context->upper_bound()->IsRelationTrue(NumericRelation::Gt(), | |
216 this, -context->offset()))) { | |
217 context->set_upper_bound_guarantee(this); | |
218 } | |
219 } | |
220 | |
221 if (context->is_range_satisfied()) return; | |
222 | |
223 // See if our RedefinedOperand() satisfies the constraints. | |
224 if (RedefinedOperand() != NULL) { | |
225 RedefinedOperand()->TryGuaranteeRangeRecursive(context); | |
226 } | |
227 if (context->is_range_satisfied()) return; | |
228 | |
229 // See if the constraints can be satisfied by decomposition. | |
230 DecompositionResult decomposition; | |
231 if (TryDecompose(&decomposition)) { | |
232 context->swap_candidate(&decomposition); | |
233 context->candidate()->TryGuaranteeRangeRecursive(context); | |
234 context->swap_candidate(&decomposition); | |
235 } | |
236 if (context->is_range_satisfied()) return; | |
237 | |
238 // Try to modify this to satisfy the constraint. | |
239 | |
240 TryGuaranteeRangeChanging(context); | |
241 } | |
242 | |
243 | |
244 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper) | |
245 : lower_bound_(upper->block()->graph()->GetConstant0()), | |
246 lower_bound_guarantee_(NULL), | |
247 candidate_(value), | |
248 upper_bound_(upper), | |
249 upper_bound_guarantee_(NULL), | |
250 offset_(0), | |
251 scale_(0) { | |
252 } | |
253 | |
254 | |
255 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { | |
256 return guarantee->IsBoundsCheckBaseIndexInformation() | |
257 ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check() | |
258 : guarantee; | |
259 } | |
260 | |
261 | |
262 static int32_t ConvertAndSetOverflow(Representation r, | 152 static int32_t ConvertAndSetOverflow(Representation r, |
263 int64_t result, | 153 int64_t result, |
264 bool* overflow) { | 154 bool* overflow) { |
265 if (r.IsSmi()) { | 155 if (r.IsSmi()) { |
266 if (result > Smi::kMaxValue) { | 156 if (result > Smi::kMaxValue) { |
267 *overflow = true; | 157 *overflow = true; |
268 return Smi::kMaxValue; | 158 return Smi::kMaxValue; |
269 } | 159 } |
270 if (result < Smi::kMinValue) { | 160 if (result < Smi::kMinValue) { |
271 *overflow = true; | 161 *overflow = true; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 result = HType::Boolean(); | 367 result = HType::Boolean(); |
478 } else if (value->IsJSObject()) { | 368 } else if (value->IsJSObject()) { |
479 result = HType::JSObject(); | 369 result = HType::JSObject(); |
480 } else if (value->IsJSArray()) { | 370 } else if (value->IsJSArray()) { |
481 result = HType::JSArray(); | 371 result = HType::JSArray(); |
482 } | 372 } |
483 return result; | 373 return result; |
484 } | 374 } |
485 | 375 |
486 | 376 |
487 bool HValue::Dominates(HValue* dominator, HValue* dominated) { | |
488 if (dominator->block() != dominated->block()) { | |
489 // If they are in different blocks we can use the dominance relation | |
490 // between the blocks. | |
491 return dominator->block()->Dominates(dominated->block()); | |
492 } else { | |
493 // Otherwise we must see which instruction comes first, considering | |
494 // that phis always precede regular instructions. | |
495 if (dominator->IsInstruction()) { | |
496 if (dominated->IsInstruction()) { | |
497 for (HInstruction* next = HInstruction::cast(dominator)->next(); | |
498 next != NULL; | |
499 next = next->next()) { | |
500 if (next == dominated) return true; | |
501 } | |
502 return false; | |
503 } else if (dominated->IsPhi()) { | |
504 return false; | |
505 } else { | |
506 UNREACHABLE(); | |
507 } | |
508 } else if (dominator->IsPhi()) { | |
509 if (dominated->IsInstruction()) { | |
510 return true; | |
511 } else { | |
512 // We cannot compare which phi comes first. | |
513 UNREACHABLE(); | |
514 } | |
515 } else { | |
516 UNREACHABLE(); | |
517 } | |
518 return false; | |
519 } | |
520 } | |
521 | |
522 | |
523 bool HValue::TestDominanceUsingProcessedFlag(HValue* dominator, | |
524 HValue* dominated) { | |
525 if (dominator->block() != dominated->block()) { | |
526 return dominator->block()->Dominates(dominated->block()); | |
527 } else { | |
528 // If both arguments are in the same block we check if dominator is a phi | |
529 // or if dominated has not already been processed: in either case we know | |
530 // that dominator precedes dominated. | |
531 return dominator->IsPhi() || !dominated->CheckFlag(kIDefsProcessingDone); | |
532 } | |
533 } | |
534 | |
535 | |
536 bool HValue::IsDefinedAfter(HBasicBlock* other) const { | 377 bool HValue::IsDefinedAfter(HBasicBlock* other) const { |
537 return block()->block_id() > other->block_id(); | 378 return block()->block_id() > other->block_id(); |
538 } | 379 } |
539 | 380 |
540 | 381 |
541 HUseListNode* HUseListNode::tail() { | 382 HUseListNode* HUseListNode::tail() { |
542 // Skip and remove dead items in the use list. | 383 // Skip and remove dead items in the use list. |
543 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { | 384 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) { |
544 tail_ = tail_->tail_; | 385 tail_ = tail_->tail_; |
545 } | 386 } |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 // Verify that all uses are in the graph. | 794 // Verify that all uses are in the graph. |
954 for (HUseIterator use = uses(); !use.Done(); use.Advance()) { | 795 for (HUseIterator use = uses(); !use.Done(); use.Advance()) { |
955 if (use.value()->IsInstruction()) { | 796 if (use.value()->IsInstruction()) { |
956 ASSERT(HInstruction::cast(use.value())->IsLinked()); | 797 ASSERT(HInstruction::cast(use.value())->IsLinked()); |
957 } | 798 } |
958 } | 799 } |
959 } | 800 } |
960 #endif | 801 #endif |
961 | 802 |
962 | 803 |
963 HNumericConstraint* HNumericConstraint::AddToGraph( | |
964 HValue* constrained_value, | |
965 NumericRelation relation, | |
966 HValue* related_value, | |
967 HInstruction* insertion_point) { | |
968 if (insertion_point == NULL) { | |
969 if (constrained_value->IsInstruction()) { | |
970 insertion_point = HInstruction::cast(constrained_value); | |
971 } else if (constrained_value->IsPhi()) { | |
972 insertion_point = constrained_value->block()->first(); | |
973 } else { | |
974 UNREACHABLE(); | |
975 } | |
976 } | |
977 HNumericConstraint* result = | |
978 new(insertion_point->block()->zone()) HNumericConstraint( | |
979 constrained_value, relation, related_value); | |
980 result->InsertAfter(insertion_point); | |
981 return result; | |
982 } | |
983 | |
984 | |
985 void HNumericConstraint::PrintDataTo(StringStream* stream) { | |
986 stream->Add("("); | |
987 constrained_value()->PrintNameTo(stream); | |
988 stream->Add(" %s ", relation().Mnemonic()); | |
989 related_value()->PrintNameTo(stream); | |
990 stream->Add(")"); | |
991 } | |
992 | |
993 | |
994 HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph( | |
995 HPhi* phi, | |
996 NumericRelation relation, | |
997 int operand_index) { | |
998 HInductionVariableAnnotation* result = | |
999 new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation, | |
1000 operand_index); | |
1001 result->InsertAfter(phi->block()->first()); | |
1002 return result; | |
1003 } | |
1004 | |
1005 | |
1006 void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) { | |
1007 stream->Add("("); | |
1008 RedefinedOperand()->PrintNameTo(stream); | |
1009 stream->Add(" %s ", relation().Mnemonic()); | |
1010 induction_base()->PrintNameTo(stream); | |
1011 stream->Add(")"); | |
1012 } | |
1013 | |
1014 | |
1015 void HDummyUse::PrintDataTo(StringStream* stream) { | 804 void HDummyUse::PrintDataTo(StringStream* stream) { |
1016 value()->PrintNameTo(stream); | 805 value()->PrintNameTo(stream); |
1017 } | 806 } |
1018 | 807 |
1019 | 808 |
1020 void HEnvironmentMarker::PrintDataTo(StringStream* stream) { | 809 void HEnvironmentMarker::PrintDataTo(StringStream* stream) { |
1021 stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); | 810 stream->Add("%s var[%d]", kind() == BIND ? "bind" : "lookup", index()); |
1022 } | 811 } |
1023 | 812 |
1024 | 813 |
1025 void HUnaryCall::PrintDataTo(StringStream* stream) { | 814 void HUnaryCall::PrintDataTo(StringStream* stream) { |
1026 value()->PrintNameTo(stream); | 815 value()->PrintNameTo(stream); |
1027 stream->Add(" "); | 816 stream->Add(" "); |
1028 stream->Add("#%d", argument_count()); | 817 stream->Add("#%d", argument_count()); |
1029 } | 818 } |
1030 | 819 |
1031 | 820 |
1032 void HBinaryCall::PrintDataTo(StringStream* stream) { | 821 void HBinaryCall::PrintDataTo(StringStream* stream) { |
1033 first()->PrintNameTo(stream); | 822 first()->PrintNameTo(stream); |
1034 stream->Add(" "); | 823 stream->Add(" "); |
1035 second()->PrintNameTo(stream); | 824 second()->PrintNameTo(stream); |
1036 stream->Add(" "); | 825 stream->Add(" "); |
1037 stream->Add("#%d", argument_count()); | 826 stream->Add("#%d", argument_count()); |
1038 } | 827 } |
1039 | 828 |
1040 | 829 |
1041 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | |
1042 if (context->candidate()->ActualValue() != base()->ActualValue() || | |
1043 context->scale() < scale()) { | |
1044 return; | |
1045 } | |
1046 | |
1047 // TODO(mmassi) | |
1048 // Instead of checking for "same basic block" we should check for | |
1049 // "dominates and postdominates". | |
1050 if (context->upper_bound() == length() && | |
1051 context->lower_bound_guarantee() != NULL && | |
1052 context->lower_bound_guarantee() != this && | |
1053 context->lower_bound_guarantee()->block() != block() && | |
1054 offset() < context->offset() && | |
1055 index_can_increase() && | |
1056 context->upper_bound_guarantee() == NULL) { | |
1057 offset_ = context->offset(); | |
1058 SetResponsibilityForRange(DIRECTION_UPPER); | |
1059 context->set_upper_bound_guarantee(this); | |
1060 isolate()->counters()->bounds_checks_eliminated()->Increment(); | |
1061 } else if (context->upper_bound_guarantee() != NULL && | |
1062 context->upper_bound_guarantee() != this && | |
1063 context->upper_bound_guarantee()->block() != block() && | |
1064 offset() > context->offset() && | |
1065 index_can_decrease() && | |
1066 context->lower_bound_guarantee() == NULL) { | |
1067 offset_ = context->offset(); | |
1068 SetResponsibilityForRange(DIRECTION_LOWER); | |
1069 context->set_lower_bound_guarantee(this); | |
1070 isolate()->counters()->bounds_checks_eliminated()->Increment(); | |
1071 } | |
1072 } | |
1073 | |
1074 | |
1075 void HBoundsCheck::ApplyIndexChange() { | 830 void HBoundsCheck::ApplyIndexChange() { |
1076 if (skip_check()) return; | 831 if (skip_check()) return; |
1077 | 832 |
1078 DecompositionResult decomposition; | 833 DecompositionResult decomposition; |
1079 bool index_is_decomposable = index()->TryDecompose(&decomposition); | 834 bool index_is_decomposable = index()->TryDecompose(&decomposition); |
1080 if (index_is_decomposable) { | 835 if (index_is_decomposable) { |
1081 ASSERT(decomposition.base() == base()); | 836 ASSERT(decomposition.base() == base()); |
1082 if (decomposition.offset() == offset() && | 837 if (decomposition.offset() == offset() && |
1083 decomposition.scale() == scale()) return; | 838 decomposition.scale() == scale()) return; |
1084 } else { | 839 } else { |
(...skipping 27 matching lines...) Expand all Loading... |
1112 sar->InsertBefore(this); | 867 sar->InsertBefore(this); |
1113 sar->AssumeRepresentation(index()->representation()); | 868 sar->AssumeRepresentation(index()->representation()); |
1114 current_index = sar; | 869 current_index = sar; |
1115 } | 870 } |
1116 | 871 |
1117 SetOperandAt(0, current_index); | 872 SetOperandAt(0, current_index); |
1118 | 873 |
1119 base_ = NULL; | 874 base_ = NULL; |
1120 offset_ = 0; | 875 offset_ = 0; |
1121 scale_ = 0; | 876 scale_ = 0; |
1122 responsibility_direction_ = DIRECTION_NONE; | |
1123 } | 877 } |
1124 | 878 |
1125 | 879 |
1126 void HBoundsCheck::AddInformativeDefinitions() { | |
1127 // TODO(mmassi): Executing this code during AddInformativeDefinitions | |
1128 // is a hack. Move it to some other HPhase. | |
1129 if (FLAG_array_bounds_checks_elimination) { | |
1130 if (index()->TryGuaranteeRange(length())) { | |
1131 set_skip_check(); | |
1132 } | |
1133 if (DetectCompoundIndex()) { | |
1134 HBoundsCheckBaseIndexInformation* base_index_info = | |
1135 new(block()->graph()->zone()) | |
1136 HBoundsCheckBaseIndexInformation(this); | |
1137 base_index_info->InsertAfter(this); | |
1138 } | |
1139 } | |
1140 } | |
1141 | |
1142 | |
1143 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, | |
1144 HValue* related_value, | |
1145 int offset, | |
1146 int scale) { | |
1147 if (related_value == length()) { | |
1148 // A HBoundsCheck is smaller than the length it compared against. | |
1149 return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale); | |
1150 } else if (related_value == block()->graph()->GetConstant0()) { | |
1151 // A HBoundsCheck is greater than or equal to zero. | |
1152 return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale); | |
1153 } else { | |
1154 return false; | |
1155 } | |
1156 } | |
1157 | |
1158 | |
1159 void HBoundsCheck::PrintDataTo(StringStream* stream) { | 880 void HBoundsCheck::PrintDataTo(StringStream* stream) { |
1160 index()->PrintNameTo(stream); | 881 index()->PrintNameTo(stream); |
1161 stream->Add(" "); | 882 stream->Add(" "); |
1162 length()->PrintNameTo(stream); | 883 length()->PrintNameTo(stream); |
1163 if (base() != NULL && (offset() != 0 || scale() != 0)) { | 884 if (base() != NULL && (offset() != 0 || scale() != 0)) { |
1164 stream->Add(" base: (("); | 885 stream->Add(" base: (("); |
1165 if (base() != index()) { | 886 if (base() != index()) { |
1166 index()->PrintNameTo(stream); | 887 index()->PrintNameTo(stream); |
1167 } else { | 888 } else { |
1168 stream->Add("index"); | 889 stream->Add("index"); |
(...skipping 19 matching lines...) Expand all Loading... |
1188 length_rep = Representation::Smi(); | 909 length_rep = Representation::Smi(); |
1189 } | 910 } |
1190 Representation r = index_rep.generalize(length_rep); | 911 Representation r = index_rep.generalize(length_rep); |
1191 if (r.is_more_general_than(Representation::Integer32())) { | 912 if (r.is_more_general_than(Representation::Integer32())) { |
1192 r = Representation::Integer32(); | 913 r = Representation::Integer32(); |
1193 } | 914 } |
1194 UpdateRepresentation(r, h_infer, "boundscheck"); | 915 UpdateRepresentation(r, h_infer, "boundscheck"); |
1195 } | 916 } |
1196 | 917 |
1197 | 918 |
1198 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( | |
1199 NumericRelation relation, | |
1200 HValue* related_value, | |
1201 int offset, | |
1202 int scale) { | |
1203 if (related_value == bounds_check()->length()) { | |
1204 return NumericRelation::Lt().CompoundImplies( | |
1205 relation, | |
1206 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | |
1207 } else if (related_value == block()->graph()->GetConstant0()) { | |
1208 return NumericRelation::Ge().CompoundImplies( | |
1209 relation, | |
1210 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | |
1211 } else { | |
1212 return false; | |
1213 } | |
1214 } | |
1215 | |
1216 | |
1217 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { | 919 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { |
1218 stream->Add("base: "); | 920 stream->Add("base: "); |
1219 base_index()->PrintNameTo(stream); | 921 base_index()->PrintNameTo(stream); |
1220 stream->Add(", check: "); | 922 stream->Add(", check: "); |
1221 base_index()->PrintNameTo(stream); | 923 base_index()->PrintNameTo(stream); |
1222 } | 924 } |
1223 | 925 |
1224 | 926 |
1225 void HCallConstantFunction::PrintDataTo(StringStream* stream) { | 927 void HCallConstantFunction::PrintDataTo(StringStream* stream) { |
1226 if (IsApplyFunction()) { | 928 if (IsApplyFunction()) { |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1943 if (!b->CanBeZero()) { | 1645 if (!b->CanBeZero()) { |
1944 ClearFlag(HValue::kCanBeDivByZero); | 1646 ClearFlag(HValue::kCanBeDivByZero); |
1945 } | 1647 } |
1946 return result; | 1648 return result; |
1947 } else { | 1649 } else { |
1948 return HValue::InferRange(zone); | 1650 return HValue::InferRange(zone); |
1949 } | 1651 } |
1950 } | 1652 } |
1951 | 1653 |
1952 | 1654 |
1953 void HPhi::AddInformativeDefinitions() { | |
1954 if (OperandCount() == 2) { | |
1955 // If one of the operands is an OSR block give up (this cannot be an | |
1956 // induction variable). | |
1957 if (OperandAt(0)->block()->is_osr_entry() || | |
1958 OperandAt(1)->block()->is_osr_entry()) return; | |
1959 | |
1960 for (int operand_index = 0; operand_index < 2; operand_index++) { | |
1961 int other_operand_index = (operand_index + 1) % 2; | |
1962 | |
1963 static NumericRelation relations[] = { | |
1964 NumericRelation::Ge(), | |
1965 NumericRelation::Le() | |
1966 }; | |
1967 | |
1968 // Check if this phi is an induction variable. If, e.g., we know that | |
1969 // its first input is greater than the phi itself, then that must be | |
1970 // the back edge, and the phi is always greater than its second input. | |
1971 for (int relation_index = 0; relation_index < 2; relation_index++) { | |
1972 if (OperandAt(operand_index)->IsRelationTrue(relations[relation_index], | |
1973 this)) { | |
1974 HInductionVariableAnnotation::AddToGraph(this, | |
1975 relations[relation_index], | |
1976 other_operand_index); | |
1977 } | |
1978 } | |
1979 } | |
1980 } | |
1981 } | |
1982 | |
1983 | |
1984 bool HPhi::IsRelationTrueInternal(NumericRelation relation, | |
1985 HValue* other, | |
1986 int offset, | |
1987 int scale) { | |
1988 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false; | |
1989 | |
1990 SetFlag(kNumericConstraintEvaluationInProgress); | |
1991 bool result = true; | |
1992 for (int i = 0; i < OperandCount(); i++) { | |
1993 // Skip OSR entry blocks | |
1994 if (OperandAt(i)->block()->is_osr_entry()) continue; | |
1995 | |
1996 if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) { | |
1997 result = false; | |
1998 break; | |
1999 } | |
2000 } | |
2001 ClearFlag(kNumericConstraintEvaluationInProgress); | |
2002 | |
2003 return result; | |
2004 } | |
2005 | |
2006 | |
2007 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { | 1655 InductionVariableData* InductionVariableData::ExaminePhi(HPhi* phi) { |
2008 if (phi->block()->loop_information() == NULL) return NULL; | 1656 if (phi->block()->loop_information() == NULL) return NULL; |
2009 if (phi->OperandCount() != 2) return NULL; | 1657 if (phi->OperandCount() != 2) return NULL; |
2010 int32_t candidate_increment; | 1658 int32_t candidate_increment; |
2011 | 1659 |
2012 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); | 1660 candidate_increment = ComputeIncrement(phi, phi->OperandAt(0)); |
2013 if (candidate_increment != 0) { | 1661 if (candidate_increment != 0) { |
2014 return new(phi->block()->graph()->zone()) | 1662 return new(phi->block()->graph()->zone()) |
2015 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); | 1663 InductionVariableData(phi, phi->OperandAt(1), candidate_increment); |
2016 } | 1664 } |
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3083 } | 2731 } |
3084 | 2732 |
3085 | 2733 |
3086 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { | 2734 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { |
3087 stream->Add(Token::Name(token())); | 2735 stream->Add(Token::Name(token())); |
3088 stream->Add(" "); | 2736 stream->Add(" "); |
3089 HControlInstruction::PrintDataTo(stream); | 2737 HControlInstruction::PrintDataTo(stream); |
3090 } | 2738 } |
3091 | 2739 |
3092 | 2740 |
3093 void HCompareNumericAndBranch::AddInformativeDefinitions() { | |
3094 NumericRelation r = NumericRelation::FromToken(token()); | |
3095 if (r.IsNone()) return; | |
3096 | |
3097 HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first()); | |
3098 HNumericConstraint::AddToGraph( | |
3099 left(), r.Negated(), right(), SuccessorAt(1)->first()); | |
3100 } | |
3101 | |
3102 | |
3103 void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { | 2741 void HCompareNumericAndBranch::PrintDataTo(StringStream* stream) { |
3104 stream->Add(Token::Name(token())); | 2742 stream->Add(Token::Name(token())); |
3105 stream->Add(" "); | 2743 stream->Add(" "); |
3106 left()->PrintNameTo(stream); | 2744 left()->PrintNameTo(stream); |
3107 stream->Add(" "); | 2745 stream->Add(" "); |
3108 right()->PrintNameTo(stream); | 2746 right()->PrintNameTo(stream); |
3109 HControlInstruction::PrintDataTo(stream); | 2747 HControlInstruction::PrintDataTo(stream); |
3110 } | 2748 } |
3111 | 2749 |
3112 | 2750 |
(...skipping 1366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4479 break; | 4117 break; |
4480 case kExternalMemory: | 4118 case kExternalMemory: |
4481 stream->Add("[external-memory]"); | 4119 stream->Add("[external-memory]"); |
4482 break; | 4120 break; |
4483 } | 4121 } |
4484 | 4122 |
4485 stream->Add("@%d", offset()); | 4123 stream->Add("@%d", offset()); |
4486 } | 4124 } |
4487 | 4125 |
4488 } } // namespace v8::internal | 4126 } } // namespace v8::internal |
OLD | NEW |