Chromium Code Reviews| 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 // This method is recursive but it is guaranteed to terminate because | 170 // This method is recursive but it is guaranteed to terminate because |
| 171 // RedefinedOperand() always dominates "this". | 171 // RedefinedOperand() always dominates "this". |
| 172 bool HValue::IsRelationTrue(NumericRelation relation, | 172 bool HValue::IsRelationTrue(NumericRelation relation, |
| 173 HValue* other, | 173 HValue* other, |
| 174 int offset, | 174 int offset, |
| 175 int scale) { | 175 int scale) { |
| 176 if (this == other) { | 176 if (ActualValue() == other->ActualValue()) { |
| 177 return scale == 0 && relation.IsExtendable(offset); | 177 return scale == 0 && relation.IsExtendable(offset); |
| 178 } | 178 } |
| 179 | 179 |
| 180 // Test the direct relation. | 180 // Test the direct relation. |
| 181 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; | 181 if (IsRelationTrueInternal(relation, other, offset, scale)) return true; |
| 182 | 182 |
| 183 // If scale is 0 try the reversed relation. | 183 // If scale is 0 try the reversed relation. |
| 184 if (scale == 0 && | 184 if (scale == 0 && |
| 185 // TODO(mmassi): do we need the full, recursive IsRelationTrue? | 185 // TODO(mmassi): do we need the full, recursive IsRelationTrue? |
| 186 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { | 186 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) { |
| 187 return true; | 187 return true; |
| 188 } | 188 } |
| 189 | 189 |
| 190 // Try decomposition (but do not accept scaled compounds). | 190 // Try decomposition, but only if we are not scaled. |
| 191 DecompositionResult decomposition; | 191 DecompositionResult decomposition; |
| 192 if (TryDecompose(&decomposition) && | 192 if (scale == 0 && TryDecompose(&decomposition)) { |
| 193 decomposition.scale() == 0 && | 193 // Check if the compound is scaled. |
| 194 decomposition.base()->IsRelationTrue(relation, other, | 194 if (decomposition.scale() == 0) { |
| 195 offset + decomposition.offset(), | 195 // Non-scaled compounds can be handled normally. |
| 196 scale)) { | 196 if (decomposition.base()->IsRelationTrue( |
| 197 return true; | 197 relation, other, offset + decomposition.offset(), scale)) { |
| 198 return true; | |
| 199 } | |
| 200 } else if (decomposition.offset() == 0 && offset == 0) { | |
| 201 // We only have a scale value which means that we can apply chaining | |
| 202 // using relation extensibility: negative scales grow values (positive | |
| 203 // direction), positive scales make them smaller (negative direction). | |
| 204 // As a concrete example: "(x << 1) <= 0" <== "x <= 0". | |
| 205 int direction = decomposition.scale() > 0 ? -1 : 1; | |
|
Jakob Kummerow
2013/04/17 11:34:15
why not just "int direction = -decomposition.scale
Massi
2013/05/07 11:32:03
Done.
| |
| 206 if (relation.IsExtendable(direction) | |
| 207 && decomposition.base()->IsRelationTrue( | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: '&&' on the previous line please
Massi
2013/05/07 11:32:03
Done.
| |
| 208 relation, other, 0, 0)) { | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: fits on last line?
Massi
2013/05/07 11:32:03
Done.
| |
| 209 return true; | |
| 210 } | |
| 211 | |
| 212 } else { | |
| 213 // Just test for "same value" relation extensibility. | |
| 214 | |
| 215 if (decomposition.base() == other) { | |
| 216 // The direction of the extensibility test is determined by scale and | |
| 217 // offset, but we can not handle all combinations. | |
| 218 int direction = 0; | |
| 219 // Do not accept left shifts greater than 1. | |
| 220 if (decomposition.scale() <= -1) { | |
| 221 if (decomposition.offset() == 0) { | |
| 222 // A positive scale makes values smaller. | |
| 223 direction = -decomposition.scale(); | |
| 224 } else { | |
| 225 // If offset and scale have different signs they both go in the | |
| 226 // same direction, otherwise we cannot handle the combination. | |
| 227 if (decomposition.offset() * decomposition.scale() < 0) { | |
| 228 direction = offset; | |
| 229 } | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 if (direction != 0 && relation.IsExtendable(direction)) { | |
| 234 return true; | |
| 235 } | |
| 236 } | |
| 237 } | |
| 198 } | 238 } |
| 199 | 239 |
| 200 // Pass the request to the redefined value. | 240 // Pass the request to the redefined value. |
| 201 HValue* redefined = RedefinedOperand(); | 241 HValue* redefined = RedefinedOperand(); |
| 202 return redefined != NULL && redefined->IsRelationTrue(relation, other, | 242 return redefined != NULL && redefined->IsRelationTrue(relation, other, |
| 203 offset, scale); | 243 offset, scale); |
| 204 } | 244 } |
| 205 | 245 |
| 206 | 246 |
| 207 bool HValue::TryGuaranteeRange(HValue* upper_bound) { | 247 bool HValue::TryGuaranteeRange(HValue* upper_bound, |
| 208 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound); | 248 HBasicBlock* starting_block_for_hoisting) { |
| 249 if (starting_block_for_hoisting == NULL) { | |
| 250 starting_block_for_hoisting = block(); | |
| 251 } | |
| 252 RangeEvaluationContext context = RangeEvaluationContext( | |
| 253 this, upper_bound, starting_block_for_hoisting); | |
| 209 TryGuaranteeRangeRecursive(&context); | 254 TryGuaranteeRangeRecursive(&context); |
| 210 bool result = context.is_range_satisfied(); | 255 bool result = context.is_range_satisfied(); |
| 211 if (result) { | 256 if (result) { |
| 212 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); | 257 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER); |
| 213 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); | 258 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER); |
| 214 } | 259 } |
| 215 return result; | 260 return result; |
| 216 } | 261 } |
| 217 | 262 |
| 218 | 263 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 context->swap_candidate(&decomposition); | 297 context->swap_candidate(&decomposition); |
| 253 } | 298 } |
| 254 if (context->is_range_satisfied()) return; | 299 if (context->is_range_satisfied()) return; |
| 255 | 300 |
| 256 // Try to modify this to satisfy the constraint. | 301 // Try to modify this to satisfy the constraint. |
| 257 | 302 |
| 258 TryGuaranteeRangeChanging(context); | 303 TryGuaranteeRangeChanging(context); |
| 259 } | 304 } |
| 260 | 305 |
| 261 | 306 |
| 262 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper) | 307 RangeEvaluationContext::RangeEvaluationContext(HValue* value, |
| 263 : lower_bound_(upper->block()->graph()->GetConstant0()), | 308 HValue* upper, |
| 309 HBasicBlock* starting_block) | |
| 310 : starting_block_(starting_block), | |
| 311 lower_bound_(upper->block()->graph()->GetConstant0()), | |
| 264 lower_bound_guarantee_(NULL), | 312 lower_bound_guarantee_(NULL), |
| 265 candidate_(value), | 313 candidate_(value), |
| 266 upper_bound_(upper), | 314 upper_bound_(upper), |
| 267 upper_bound_guarantee_(NULL), | 315 upper_bound_guarantee_(NULL), |
| 268 offset_(0), | 316 offset_(0), |
| 269 scale_(0) { | 317 scale_(0) { |
| 270 } | 318 } |
| 271 | 319 |
| 272 | 320 |
| 273 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { | 321 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) { |
| (...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 925 } | 973 } |
| 926 } | 974 } |
| 927 } | 975 } |
| 928 #endif | 976 #endif |
| 929 | 977 |
| 930 | 978 |
| 931 HNumericConstraint* HNumericConstraint::AddToGraph( | 979 HNumericConstraint* HNumericConstraint::AddToGraph( |
| 932 HValue* constrained_value, | 980 HValue* constrained_value, |
| 933 NumericRelation relation, | 981 NumericRelation relation, |
| 934 HValue* related_value, | 982 HValue* related_value, |
| 935 HInstruction* insertion_point) { | 983 HInstruction* insertion_point, |
| 984 HBasicBlock* other_block) { | |
| 936 if (insertion_point == NULL) { | 985 if (insertion_point == NULL) { |
| 937 if (constrained_value->IsInstruction()) { | 986 if (constrained_value->IsInstruction()) { |
| 938 insertion_point = HInstruction::cast(constrained_value); | 987 insertion_point = HInstruction::cast(constrained_value); |
| 939 } else if (constrained_value->IsPhi()) { | 988 } else if (constrained_value->IsPhi()) { |
| 940 insertion_point = constrained_value->block()->first(); | 989 insertion_point = constrained_value->block()->first(); |
| 941 } else { | 990 } else { |
| 942 UNREACHABLE(); | 991 UNREACHABLE(); |
| 943 } | 992 } |
| 944 } | 993 } |
| 945 HNumericConstraint* result = | 994 HNumericConstraint* result = |
| 946 new(insertion_point->block()->zone()) HNumericConstraint( | 995 new(insertion_point->block()->zone()) HNumericConstraint( |
| 947 constrained_value, relation, related_value); | 996 constrained_value, relation, related_value, other_block); |
| 948 result->InsertAfter(insertion_point); | 997 result->InsertAfter(insertion_point); |
| 949 return result; | 998 return result; |
| 950 } | 999 } |
| 951 | 1000 |
| 952 | 1001 |
| 953 void HNumericConstraint::PrintDataTo(StringStream* stream) { | 1002 void HNumericConstraint::PrintDataTo(StringStream* stream) { |
| 954 stream->Add("("); | 1003 stream->Add("("); |
| 955 constrained_value()->PrintNameTo(stream); | 1004 constrained_value()->PrintNameTo(stream); |
| 956 stream->Add(" %s ", relation().Mnemonic()); | 1005 stream->Add(" %s ", relation().Mnemonic()); |
| 957 related_value()->PrintNameTo(stream); | 1006 related_value()->PrintNameTo(stream); |
| 958 stream->Add(")"); | 1007 stream->Add(")"); |
| 959 } | 1008 } |
| 960 | 1009 |
| 961 | 1010 |
| 962 HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph( | 1011 HInductionVariableAnnotation* HInductionVariableAnnotation::AddToGraph( |
| 963 HPhi* phi, | 1012 HPhi* phi, |
| 964 NumericRelation relation, | 1013 NumericRelation relation, |
| 965 int operand_index) { | 1014 int operand_index) { |
| 966 HInductionVariableAnnotation* result = | 1015 HInductionVariableAnnotation* result = new(phi->block()->zone()) |
| 967 new(phi->block()->zone()) HInductionVariableAnnotation(phi, relation, | 1016 HInductionVariableAnnotation(phi, relation, operand_index, |
| 968 operand_index); | 1017 phi->block()->zone()); |
| 969 result->InsertAfter(phi->block()->first()); | 1018 result->InsertAfter(phi->block()->first()); |
| 970 return result; | 1019 return result; |
| 971 } | 1020 } |
| 972 | 1021 |
| 973 | 1022 |
| 1023 void HInductionVariableAnnotation::AddHoistedCheck(HBoundsCheck* check) { | |
| 1024 hoisted_checks_.Add(check, block()->zone()); | |
| 1025 } | |
| 1026 | |
| 1027 | |
| 1028 HInductionVariableAnnotation::HInductionVariableAnnotation( | |
| 1029 HPhi* phi, | |
| 1030 NumericRelation relation, | |
| 1031 int operand_index, | |
| 1032 Zone* zone) | |
| 1033 : HUnaryOperation(phi), phi_(phi), relation_(relation), | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: one line per initializer, please
Massi
2013/05/07 11:32:03
Done.
| |
| 1034 operand_index_(operand_index), hoisted_checks_(4, zone) { | |
| 1035 } | |
| 1036 | |
| 1037 | |
| 1038 void HInductionVariableAnnotation::TryGuaranteeRangeChanging( | |
| 1039 RangeEvaluationContext* context) { | |
| 1040 if (relation().IsExtendable(1)) { | |
| 1041 if (context->lower_bound_guarantee() == NULL) return; | |
| 1042 } else { | |
| 1043 return; | |
| 1044 } | |
| 1045 | |
| 1046 for (int i = 0; i < hoisted_checks()->length(); i++) { | |
| 1047 HBoundsCheck* hoisted_check = hoisted_checks()->at(i); | |
| 1048 if (hoisted_check->length()->ActualValue() | |
| 1049 == context->upper_bound()->ActualValue()) { | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: operator on the previous line
Massi
2013/05/07 11:32:03
Done.
| |
| 1050 context->set_upper_bound_guarantee(hoisted_check); | |
| 1051 return; | |
| 1052 } | |
| 1053 } | |
| 1054 | |
| 1055 HBasicBlock* starting_block = context->starting_block(); | |
| 1056 HLoopInformation* starting_loop = starting_block->current_loop(); | |
| 1057 if (starting_loop == NULL) return; | |
| 1058 HLoopInformation* my_loop = block()->current_loop(); | |
| 1059 if (my_loop == NULL) return; | |
| 1060 if (my_loop->exits_count() > 1 | |
| 1061 && !block()->graph()->use_optimistic_licm()) return; | |
|
Jakob Kummerow
2013/04/17 11:34:15
If it doesn't make a significant difference, I'd r
| |
| 1062 | |
| 1063 bool starting_loop_is_nested_in_my_loop = false; | |
|
Jakob Kummerow
2013/04/17 11:34:15
we can make this loop a little simpler:
// See
| |
| 1064 while (starting_loop != NULL) { | |
| 1065 if (starting_loop == my_loop) { | |
| 1066 starting_loop_is_nested_in_my_loop = true; | |
| 1067 break; | |
| 1068 } | |
| 1069 starting_loop = starting_loop->parent_loop(); | |
| 1070 } | |
| 1071 if (!starting_loop_is_nested_in_my_loop) return; | |
| 1072 starting_loop = starting_block->current_loop(); | |
| 1073 | |
| 1074 for (HValue* candidate = context->candidate(); | |
| 1075 candidate != NULL; | |
| 1076 candidate = candidate->RedefinedOperand()) { | |
| 1077 if (candidate->IsNumericConstraint()) { | |
|
Jakob Kummerow
2013/04/17 11:34:15
for consistency with code below, I'd transform thi
Massi
2013/05/07 11:32:03
Done.
| |
| 1078 HNumericConstraint* constraint = HNumericConstraint::cast(candidate); | |
| 1079 if (!constraint->relation().IsExtendable(-1)) continue; | |
| 1080 HLoopInformation* other_loop = constraint->other_block()->current_loop(); | |
| 1081 if (other_loop == my_loop) continue; | |
| 1082 | |
| 1083 HBasicBlock* my_header = my_loop->loop_header(); | |
| 1084 HBasicBlock* my_pre_header = my_header->predecessors()->at(0); | |
| 1085 | |
| 1086 HValue* induction_limit = constraint->related_value()->ActualValue(); | |
| 1087 HValue* upper_bound = context->upper_bound()->ActualValue(); | |
| 1088 | |
| 1089 if (induction_limit->block() != my_pre_header | |
| 1090 && !induction_limit->block()->Dominates(my_pre_header)) continue; | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: operator on the previous line
Massi
2013/05/07 11:32:03
Done.
| |
| 1091 if (upper_bound->block() != my_pre_header | |
| 1092 && !upper_bound->block()->Dominates(my_pre_header)) continue; | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: operator on the previous line
Massi
2013/05/07 11:32:03
Done.
| |
| 1093 | |
| 1094 if (!(induction_limit->representation().Equals( | |
| 1095 upper_bound->representation()) | |
| 1096 || induction_limit->IsInteger32Constant())) { | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: operator on the previous line
Massi
2013/05/07 11:32:03
Done.
| |
| 1097 continue; | |
| 1098 } | |
| 1099 | |
| 1100 HBoundsCheck* check = new(block()->zone()) HBoundsCheck( | |
| 1101 induction_limit, upper_bound); | |
| 1102 check->InsertBefore(my_pre_header->end()); | |
| 1103 check->set_allow_equality(true); | |
| 1104 check->UpdateRedefinedUses(); | |
| 1105 AddHoistedCheck(check); | |
| 1106 context->set_upper_bound_guarantee(check); | |
| 1107 return; | |
| 1108 } | |
| 1109 } | |
| 1110 } | |
| 1111 | |
| 1112 | |
| 974 void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) { | 1113 void HInductionVariableAnnotation::PrintDataTo(StringStream* stream) { |
| 975 stream->Add("("); | 1114 stream->Add("("); |
| 976 RedefinedOperand()->PrintNameTo(stream); | 1115 RedefinedOperand()->PrintNameTo(stream); |
| 977 stream->Add(" %s ", relation().Mnemonic()); | 1116 stream->Add(" %s ", relation().Mnemonic()); |
| 978 induction_base()->PrintNameTo(stream); | 1117 induction_base()->PrintNameTo(stream); |
| 979 stream->Add(")"); | 1118 stream->Add(")"); |
| 980 } | 1119 } |
| 981 | 1120 |
| 982 | 1121 |
| 983 void HDummyUse::PrintDataTo(StringStream* stream) { | 1122 void HDummyUse::PrintDataTo(StringStream* stream) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1000 stream->Add("#%d", argument_count()); | 1139 stream->Add("#%d", argument_count()); |
| 1001 } | 1140 } |
| 1002 | 1141 |
| 1003 | 1142 |
| 1004 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { | 1143 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) { |
| 1005 if (context->candidate()->ActualValue() != base()->ActualValue() || | 1144 if (context->candidate()->ActualValue() != base()->ActualValue() || |
| 1006 context->scale() < scale()) { | 1145 context->scale() < scale()) { |
| 1007 return; | 1146 return; |
| 1008 } | 1147 } |
| 1009 | 1148 |
| 1149 if (context->lower_bound_guarantee() != NULL && | |
| 1150 context->lower_bound_guarantee() != this) { | |
| 1151 if (context->lower_bound_guarantee()->IsBoundsCheck()) { | |
| 1152 HBoundsCheck* guarantee = HBoundsCheck::cast( | |
| 1153 context->lower_bound_guarantee()); | |
| 1154 if (guarantee->base()->ActualValue() == base()->ActualValue() | |
| 1155 && guarantee->scale() == scale() | |
| 1156 && guarantee->offset() > offset()) { | |
| 1157 context->set_lower_bound_guarantee(this); | |
| 1158 } | |
| 1159 } | |
| 1160 } else if (context->upper_bound_guarantee() != NULL && | |
|
Jakob Kummerow
2013/04/17 11:34:15
I think the "else" needs to be removed.
Massi
2013/05/07 11:32:03
Done.
Massi
2013/05/07 11:32:03
Done.
| |
| 1161 context->upper_bound_guarantee() != this) { | |
| 1162 if (context->upper_bound_guarantee()->IsBoundsCheck()) { | |
| 1163 HBoundsCheck* guarantee = HBoundsCheck::cast( | |
| 1164 context->upper_bound_guarantee()); | |
| 1165 if (guarantee->base()->ActualValue() == base()->ActualValue() | |
| 1166 && guarantee->scale() == scale() | |
| 1167 && guarantee->offset() < offset()) { | |
| 1168 context->set_upper_bound_guarantee(this); | |
| 1169 } | |
| 1170 } | |
| 1171 } | |
| 1172 | |
| 1010 // TODO(mmassi) | 1173 // TODO(mmassi) |
| 1011 // Instead of checking for "same basic block" we should check for | 1174 // Instead of checking for "same basic block" we should check for |
| 1012 // "dominates and postdominates". | 1175 // "dominates and postdominates". |
| 1013 if (context->upper_bound() == length() && | 1176 if (context->upper_bound() == length() && |
| 1014 context->lower_bound_guarantee() != NULL && | 1177 context->lower_bound_guarantee() != NULL && |
| 1015 context->lower_bound_guarantee() != this && | 1178 context->lower_bound_guarantee() != this && |
| 1016 context->lower_bound_guarantee()->block() != block() && | 1179 context->lower_bound_guarantee()->block() == block() && |
| 1017 offset() < context->offset() && | 1180 offset() < context->offset() && |
| 1018 index_can_increase() && | 1181 index_can_increase() && |
| 1019 context->upper_bound_guarantee() == NULL) { | 1182 context->upper_bound_guarantee() == NULL) { |
| 1020 offset_ = context->offset(); | 1183 offset_ = context->offset(); |
| 1021 SetResponsibilityForRange(DIRECTION_UPPER); | 1184 SetResponsibilityForRange(DIRECTION_UPPER); |
| 1022 context->set_upper_bound_guarantee(this); | 1185 context->set_upper_bound_guarantee(this); |
| 1023 } else if (context->upper_bound_guarantee() != NULL && | 1186 } else if (context->upper_bound_guarantee() != NULL && |
| 1024 context->upper_bound_guarantee() != this && | 1187 context->upper_bound_guarantee() != this && |
| 1025 context->upper_bound_guarantee()->block() != block() && | 1188 context->upper_bound_guarantee()->block() == block() && |
| 1026 offset() > context->offset() && | 1189 offset() > context->offset() && |
| 1027 index_can_decrease() && | 1190 index_can_decrease() && |
| 1028 context->lower_bound_guarantee() == NULL) { | 1191 context->lower_bound_guarantee() == NULL) { |
| 1029 offset_ = context->offset(); | 1192 offset_ = context->offset(); |
| 1030 SetResponsibilityForRange(DIRECTION_LOWER); | 1193 SetResponsibilityForRange(DIRECTION_LOWER); |
| 1031 context->set_lower_bound_guarantee(this); | 1194 context->set_lower_bound_guarantee(this); |
| 1032 } | 1195 } |
| 1033 } | 1196 } |
| 1034 | 1197 |
| 1035 | 1198 |
| 1036 void HBoundsCheck::ApplyIndexChange() { | 1199 void HBoundsCheck::ApplyIndexChange() { |
| 1037 if (skip_check()) return; | 1200 if (skip_check() || base() == NULL) return; |
| 1038 | 1201 |
| 1039 DecompositionResult decomposition; | 1202 DecompositionResult decomposition; |
| 1040 bool index_is_decomposable = index()->TryDecompose(&decomposition); | 1203 bool index_is_decomposable = index()->TryDecompose(&decomposition); |
| 1041 if (index_is_decomposable) { | 1204 if (index_is_decomposable) { |
| 1042 ASSERT(decomposition.base() == base()); | 1205 ASSERT(decomposition.base() == base()); |
| 1043 if (decomposition.offset() == offset() && | 1206 if (decomposition.offset() == offset() && |
| 1044 decomposition.scale() == scale()) return; | 1207 decomposition.scale() == scale()) return; |
| 1045 } else { | 1208 } else { |
| 1046 return; | 1209 return; |
| 1047 } | 1210 } |
| 1048 | 1211 |
| 1049 ReplaceAllUsesWith(index()); | 1212 ReplaceAllUsesWith(index()); |
| 1050 | 1213 |
| 1051 HValue* current_index = decomposition.base(); | 1214 HValue* current_index = decomposition.base(); |
| 1052 int actual_offset = decomposition.offset() + offset(); | |
| 1053 int actual_scale = decomposition.scale() + scale(); | |
| 1054 | 1215 |
| 1055 if (actual_offset != 0) { | 1216 if (offset() != 0) { |
| 1056 HConstant* add_offset = new(block()->graph()->zone()) HConstant( | 1217 HConstant* add_offset = new(block()->graph()->zone()) HConstant( |
| 1057 actual_offset, index()->representation()); | 1218 offset(), index()->representation()); |
| 1058 add_offset->InsertBefore(this); | 1219 add_offset->InsertBefore(this); |
| 1059 HInstruction* add = HAdd::New(block()->graph()->zone(), | 1220 HInstruction* add = HAdd::New(block()->graph()->zone(), |
| 1060 block()->graph()->GetInvalidContext(), current_index, add_offset); | 1221 block()->graph()->GetInvalidContext(), current_index, add_offset); |
| 1061 add->InsertBefore(this); | 1222 add->InsertBefore(this); |
| 1062 add->AssumeRepresentation(index()->representation()); | 1223 add->AssumeRepresentation(index()->representation()); |
| 1063 current_index = add; | 1224 current_index = add; |
| 1064 } | 1225 } |
| 1065 | 1226 |
| 1066 if (actual_scale != 0) { | 1227 if (scale() != 0) { |
| 1067 HConstant* sar_scale = new(block()->graph()->zone()) HConstant( | 1228 HConstant* sar_scale = new(block()->graph()->zone()) HConstant( |
| 1068 actual_scale, index()->representation()); | 1229 scale(), index()->representation()); |
| 1069 sar_scale->InsertBefore(this); | 1230 sar_scale->InsertBefore(this); |
| 1070 HInstruction* sar = HSar::New(block()->graph()->zone(), | 1231 HInstruction* sar = HSar::New(block()->graph()->zone(), |
| 1071 block()->graph()->GetInvalidContext(), current_index, sar_scale); | 1232 block()->graph()->GetInvalidContext(), current_index, sar_scale); |
| 1072 sar->InsertBefore(this); | 1233 sar->InsertBefore(this); |
| 1073 sar->AssumeRepresentation(index()->representation()); | 1234 sar->AssumeRepresentation(index()->representation()); |
| 1074 current_index = sar; | 1235 current_index = sar; |
| 1075 } | 1236 } |
| 1076 | 1237 |
| 1077 SetOperandAt(0, current_index); | 1238 SetOperandAt(0, current_index); |
| 1078 | 1239 |
| 1079 base_ = NULL; | 1240 base_ = NULL; |
| 1080 offset_ = 0; | 1241 offset_ = 0; |
| 1081 scale_ = 0; | 1242 scale_ = 0; |
| 1082 responsibility_direction_ = DIRECTION_NONE; | 1243 responsibility_direction_ = DIRECTION_NONE; |
| 1083 } | 1244 } |
| 1084 | 1245 |
| 1085 | 1246 |
| 1086 void HBoundsCheck::AddInformativeDefinitions() { | 1247 void HBoundsCheck::AddInformativeDefinitions() { |
| 1087 // TODO(mmassi): Executing this code during AddInformativeDefinitions | 1248 // TODO(mmassi): Executing this code during AddInformativeDefinitions |
| 1088 // is a hack. Move it to some other HPhase. | 1249 // is a hack. Move it to some other HPhase. |
| 1089 if (FLAG_array_bounds_checks_elimination) { | 1250 if (FLAG_array_bounds_checks_elimination) { |
| 1090 if (index()->TryGuaranteeRange(length())) { | 1251 if (index()->TryGuaranteeRange(length(), block())) { |
| 1091 set_skip_check(true); | 1252 set_skip_check(true); |
| 1092 } | 1253 } |
| 1093 if (DetectCompoundIndex()) { | 1254 if (DetectCompoundIndex()) { |
| 1094 HBoundsCheckBaseIndexInformation* base_index_info = | 1255 HBoundsCheckBaseIndexInformation* base_index_info = |
| 1095 new(block()->graph()->zone()) | 1256 new(block()->graph()->zone()) |
| 1096 HBoundsCheckBaseIndexInformation(this); | 1257 HBoundsCheckBaseIndexInformation(this); |
| 1097 base_index_info->InsertAfter(this); | 1258 base_index_info->InsertAfter(this); |
| 1098 } | 1259 } |
| 1099 } | 1260 } |
| 1100 } | 1261 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 } | 1317 } |
| 1157 UpdateRepresentation(r, h_infer, "boundscheck"); | 1318 UpdateRepresentation(r, h_infer, "boundscheck"); |
| 1158 } | 1319 } |
| 1159 | 1320 |
| 1160 | 1321 |
| 1161 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( | 1322 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal( |
| 1162 NumericRelation relation, | 1323 NumericRelation relation, |
| 1163 HValue* related_value, | 1324 HValue* related_value, |
| 1164 int offset, | 1325 int offset, |
| 1165 int scale) { | 1326 int scale) { |
| 1327 if (bounds_check() == NULL) return false; | |
| 1328 | |
| 1166 if (related_value == bounds_check()->length()) { | 1329 if (related_value == bounds_check()->length()) { |
| 1167 return NumericRelation::Lt().CompoundImplies( | 1330 return NumericRelation::Lt().CompoundImplies( |
| 1168 relation, | 1331 relation, |
| 1169 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | 1332 bounds_check()->offset(), bounds_check()->scale(), offset, scale); |
| 1170 } else if (related_value == block()->graph()->GetConstant0()) { | 1333 } else if (related_value == block()->graph()->GetConstant0()) { |
| 1171 return NumericRelation::Ge().CompoundImplies( | 1334 return NumericRelation::Ge().CompoundImplies( |
| 1172 relation, | 1335 relation, |
| 1173 bounds_check()->offset(), bounds_check()->scale(), offset, scale); | 1336 bounds_check()->offset(), bounds_check()->scale(), offset, scale); |
| 1174 } else { | 1337 } else { |
| 1175 return false; | 1338 return false; |
| 1176 } | 1339 } |
| 1177 } | 1340 } |
| 1178 | 1341 |
| 1179 | 1342 |
| 1180 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { | 1343 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) { |
| 1181 stream->Add("base: "); | 1344 stream->Add("base: "); |
| 1182 base_index()->PrintNameTo(stream); | 1345 base_index()->PrintNameTo(stream); |
| 1183 stream->Add(", check: "); | 1346 stream->Add(", check: "); |
| 1184 base_index()->PrintNameTo(stream); | 1347 if (bounds_check() != NULL) { |
| 1348 bounds_check()->PrintNameTo(stream); | |
| 1349 } else { | |
| 1350 stream->Add("DISCONNECTED "); | |
| 1351 OperandAt(1)->PrintNameTo(stream); | |
| 1352 } | |
| 1185 } | 1353 } |
| 1186 | 1354 |
| 1187 | 1355 |
| 1188 void HCallConstantFunction::PrintDataTo(StringStream* stream) { | 1356 void HCallConstantFunction::PrintDataTo(StringStream* stream) { |
| 1189 if (IsApplyFunction()) { | 1357 if (IsApplyFunction()) { |
| 1190 stream->Add("optimized apply "); | 1358 stream->Add("optimized apply "); |
| 1191 } else { | 1359 } else { |
| 1192 stream->Add("%o ", function()->shared()->DebugName()); | 1360 stream->Add("%o ", function()->shared()->DebugName()); |
| 1193 } | 1361 } |
| 1194 stream->Add("#%d", argument_count()); | 1362 stream->Add("#%d", argument_count()); |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2337 stream->Add(Token::Name(token())); | 2505 stream->Add(Token::Name(token())); |
| 2338 stream->Add(" "); | 2506 stream->Add(" "); |
| 2339 HControlInstruction::PrintDataTo(stream); | 2507 HControlInstruction::PrintDataTo(stream); |
| 2340 } | 2508 } |
| 2341 | 2509 |
| 2342 | 2510 |
| 2343 void HCompareIDAndBranch::AddInformativeDefinitions() { | 2511 void HCompareIDAndBranch::AddInformativeDefinitions() { |
| 2344 NumericRelation r = NumericRelation::FromToken(token()); | 2512 NumericRelation r = NumericRelation::FromToken(token()); |
| 2345 if (r.IsNone()) return; | 2513 if (r.IsNone()) return; |
| 2346 | 2514 |
| 2347 HNumericConstraint::AddToGraph(left(), r, right(), SuccessorAt(0)->first()); | |
| 2348 HNumericConstraint::AddToGraph( | 2515 HNumericConstraint::AddToGraph( |
| 2349 left(), r.Negated(), right(), SuccessorAt(1)->first()); | 2516 left(), r, right(), SuccessorAt(0)->first(), SuccessorAt(1)); |
| 2517 HNumericConstraint::AddToGraph( | |
| 2518 left(), r.Negated(), right(), SuccessorAt(1)->first(), SuccessorAt(0)); | |
| 2350 } | 2519 } |
| 2351 | 2520 |
| 2352 | 2521 |
| 2353 void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { | 2522 void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { |
| 2354 stream->Add(Token::Name(token())); | 2523 stream->Add(Token::Name(token())); |
| 2355 stream->Add(" "); | 2524 stream->Add(" "); |
| 2356 left()->PrintNameTo(stream); | 2525 left()->PrintNameTo(stream); |
| 2357 stream->Add(" "); | 2526 stream->Add(" "); |
| 2358 right()->PrintNameTo(stream); | 2527 right()->PrintNameTo(stream); |
| 2359 HControlInstruction::PrintDataTo(stream); | 2528 HControlInstruction::PrintDataTo(stream); |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3031 visited->Add(id()); | 3200 visited->Add(id()); |
| 3032 // Propagate to the left argument. If the left argument cannot be -0, then | 3201 // Propagate to the left argument. If the left argument cannot be -0, then |
| 3033 // the result of the sub operation cannot be either. | 3202 // the result of the sub operation cannot be either. |
| 3034 if (range() == NULL || range()->CanBeMinusZero()) { | 3203 if (range() == NULL || range()->CanBeMinusZero()) { |
| 3035 return left(); | 3204 return left(); |
| 3036 } | 3205 } |
| 3037 return NULL; | 3206 return NULL; |
| 3038 } | 3207 } |
| 3039 | 3208 |
| 3040 | 3209 |
| 3210 bool HAdd::IsRelationTrueInternal(NumericRelation relation, | |
| 3211 HValue* other, | |
| 3212 int offset, | |
| 3213 int scale) { | |
| 3214 if (offset != 0 || scale != 0) return false; | |
| 3215 | |
| 3216 // We look for a pattern like "x + delta rel x", where we should return | |
| 3217 // true if "delta >= 0 && rel.IsExtendable(1)" or | |
| 3218 // "delta <= 0 && rel.IsExtendable(-1)". | |
| 3219 HValue* delta = NULL; | |
| 3220 if (left()->ActualValue() == other->ActualValue()) { | |
| 3221 delta = right(); | |
| 3222 } else if (right()->ActualValue() == other->ActualValue()) { | |
| 3223 delta = left(); | |
| 3224 } else { | |
| 3225 return false; | |
| 3226 } | |
| 3227 | |
| 3228 if (relation.IsExtendable(1) | |
| 3229 && delta->IsRelationTrue(NumericRelation::Ge(), | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: operator on the previous line
Massi
2013/05/07 11:32:03
Done.
| |
| 3230 block()->graph()->GetConstant0())) { | |
| 3231 return true; | |
| 3232 } | |
| 3233 | |
| 3234 if (relation.IsExtendable(-1) | |
| 3235 && delta->IsRelationTrue(NumericRelation::Le(), | |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: operator on the previous line
Massi
2013/05/07 11:32:03
Done.
| |
| 3236 block()->graph()->GetConstant0())) { | |
| 3237 return true; | |
| 3238 } | |
| 3239 | |
| 3240 return false; | |
| 3241 } | |
| 3242 | |
| 3243 | |
| 3041 bool HStoreKeyed::NeedsCanonicalization() { | 3244 bool HStoreKeyed::NeedsCanonicalization() { |
| 3042 // If value is an integer or smi or comes from the result of a keyed load or | 3245 // If value is an integer or smi or comes from the result of a keyed load or |
| 3043 // constant then it is either be a non-hole value or in the case of a constant | 3246 // constant then it is either be a non-hole value or in the case of a constant |
| 3044 // the hole is only being stored explicitly: no need for canonicalization. | 3247 // the hole is only being stored explicitly: no need for canonicalization. |
| 3045 // | 3248 // |
| 3046 // The exception to that is keyed loads from external float or double arrays: | 3249 // The exception to that is keyed loads from external float or double arrays: |
| 3047 // these can load arbitrary representation of NaN. | 3250 // these can load arbitrary representation of NaN. |
| 3048 | 3251 |
| 3049 if (value()->IsConstant()) { | 3252 if (value()->IsConstant()) { |
| 3050 return false; | 3253 return false; |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3533 | 3736 |
| 3534 | 3737 |
| 3535 void HCheckFunction::Verify() { | 3738 void HCheckFunction::Verify() { |
| 3536 HInstruction::Verify(); | 3739 HInstruction::Verify(); |
| 3537 ASSERT(HasNoUses()); | 3740 ASSERT(HasNoUses()); |
| 3538 } | 3741 } |
| 3539 | 3742 |
| 3540 #endif | 3743 #endif |
| 3541 | 3744 |
| 3542 } } // namespace v8::internal | 3745 } } // namespace v8::internal |
| OLD | NEW |