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

Side by Side Diff: src/hydrogen-instructions.cc

Issue 12377072: Handling expression decomposition and array bounds check hoisting: working code with lots of debugg… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased on master and fixed conflicts. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) { 160 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
161 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { 161 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
162 h_infer->AddToWorklist(it.value()); 162 h_infer->AddToWorklist(it.value());
163 } 163 }
164 for (int i = 0; i < OperandCount(); ++i) { 164 for (int i = 0; i < OperandCount(); ++i) {
165 h_infer->AddToWorklist(OperandAt(i)); 165 h_infer->AddToWorklist(OperandAt(i));
166 } 166 }
167 } 167 }
168 168
169 169
170 // This method is recursive but it is guaranteed to terminate because
171 // RedefinedOperand() always dominates "this".
172 bool HValue::IsRelationTrue(NumericRelation relation,
173 HValue* other,
174 int offset,
175 int scale) {
176 if (this == other) {
177 return NumericRelation::Eq().Implies(relation);
178 }
179
180 // Test the direct relation.
181 if (IsRelationTrueInternal(relation, other, offset, scale)) return true;
182
183 // If scale is 0 try the reversed relation.
184 if (scale == 0 &&
185 // TODO(mmassi): do we need the full, recursive IsRelationTrue?
186 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) {
187 return true;
188 }
189
190 // Try decomposition (but do not accept scaled compounds).
191 DecompositionResult decomposition;
192 if (TryDecompose(&decomposition) &&
193 decomposition.scale() == 0 &&
194 decomposition.base()->IsRelationTrue(relation, other,
195 offset + decomposition.offset(),
196 scale)) {
197 return true;
198 }
199
200 // Pass the request to the redefined value.
201 HValue* redefined = RedefinedOperand();
202 return redefined != NULL && redefined->IsRelationTrue(relation, other,
203 offset, scale);
204 }
205
206
207 bool HValue::TryGuaranteeRange(HValue* upper_bound) {
208 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
209 TryGuaranteeRangeRecursive(&context);
210 bool result = context.is_range_satisfied();
211 if (result) {
212 context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER);
213 context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER);
214 }
215 return result;
216 }
217
218
219 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
220 // Check if we already know that this value satisfies the lower bound.
221 if (context->lower_bound_guarantee() == NULL) {
222 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
223 context->offset(), context->scale())) {
224 context->set_lower_bound_guarantee(this);
225 }
226 }
227
228 // Check if we already know that this value satisfies the upper bound.
229 if (context->upper_bound_guarantee() == NULL) {
230 if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
231 context->offset(), context->scale()) ||
232 (context->scale() == 0 &&
233 context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
234 this, -context->offset()))) {
235 context->set_upper_bound_guarantee(this);
236 }
237 }
238
239 if (context->is_range_satisfied()) return;
240
241 // See if our RedefinedOperand() satisfies the constraints.
242 if (RedefinedOperand() != NULL) {
243 RedefinedOperand()->TryGuaranteeRangeRecursive(context);
244 }
245 if (context->is_range_satisfied()) return;
246
247 // See if the constraints can be satisfied by decomposition.
248 DecompositionResult decomposition;
249 if (TryDecompose(&decomposition)) {
250 context->swap_candidate(&decomposition);
251 context->candidate()->TryGuaranteeRangeRecursive(context);
252 context->swap_candidate(&decomposition);
253 }
254 if (context->is_range_satisfied()) return;
255
256 // Try to modify this to satisfy the constraint.
257
258 TryGuaranteeRangeChanging(context);
259 }
260
261
262 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper)
263 : lower_bound_(upper->block()->graph()->GetConstant0()),
264 lower_bound_guarantee_(NULL),
265 candidate_(value),
266 upper_bound_(upper),
267 upper_bound_guarantee_(NULL),
268 offset_(0),
269 scale_(0) {
270 }
271
272
273 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
274 return guarantee->IsBoundsCheckBaseIndexInformation()
275 ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
276 : guarantee;
277 }
278
279
170 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { 280 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
171 if (result > kMaxInt) { 281 if (result > kMaxInt) {
172 *overflow = true; 282 *overflow = true;
173 return kMaxInt; 283 return kMaxInt;
174 } 284 }
175 if (result < kMinInt) { 285 if (result < kMinInt) {
176 *overflow = true; 286 *overflow = true;
177 return kMinInt; 287 return kMinInt;
178 } 288 }
179 return static_cast<int32_t>(result); 289 return static_cast<int32_t>(result);
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 991
882 void HBinaryCall::PrintDataTo(StringStream* stream) { 992 void HBinaryCall::PrintDataTo(StringStream* stream) {
883 first()->PrintNameTo(stream); 993 first()->PrintNameTo(stream);
884 stream->Add(" "); 994 stream->Add(" ");
885 second()->PrintNameTo(stream); 995 second()->PrintNameTo(stream);
886 stream->Add(" "); 996 stream->Add(" ");
887 stream->Add("#%d", argument_count()); 997 stream->Add("#%d", argument_count());
888 } 998 }
889 999
890 1000
1001 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
1002 if (context->candidate()->ActualValue() != base()->ActualValue() ||
1003 context->scale() < scale()) {
1004 return;
1005 }
1006
1007 // TODO(mmassi)
1008 // Instead of checking for "same basic block" we should check for
1009 // "dominates and postdominates".
1010 if (context->upper_bound() == length() &&
1011 context->lower_bound_guarantee() != NULL &&
1012 context->lower_bound_guarantee() != this &&
1013 context->lower_bound_guarantee()->block() != block() &&
1014 offset() < context->offset() &&
1015 index_can_increase() &&
1016 context->upper_bound_guarantee() == NULL) {
1017 offset_ = context->offset();
1018 SetResponsibilityForRange(DIRECTION_UPPER);
1019 context->set_upper_bound_guarantee(this);
1020 } else if (context->upper_bound_guarantee() != NULL &&
1021 context->upper_bound_guarantee() != this &&
1022 context->upper_bound_guarantee()->block() != block() &&
1023 offset() > context->offset() &&
1024 index_can_decrease() &&
1025 context->lower_bound_guarantee() == NULL) {
1026 offset_ = context->offset();
1027 SetResponsibilityForRange(DIRECTION_LOWER);
1028 context->set_lower_bound_guarantee(this);
1029 }
1030 }
1031
1032
1033 void HBoundsCheck::ApplyIndexChange() {
1034 if (skip_check()) return;
1035
1036 DecompositionResult decomposition;
1037 bool index_is_decomposable = index()->TryDecompose(&decomposition);
1038 if (index_is_decomposable) {
1039 ASSERT(decomposition.base() == base());
1040 if (decomposition.offset() == offset() &&
1041 decomposition.scale() == scale()) return;
1042 } else {
1043 return;
1044 }
1045
1046 ReplaceAllUsesWith(index());
1047
1048 HValue* current_index = decomposition.base();
1049 int actual_offset = decomposition.offset() + offset();
1050 int actual_scale = decomposition.scale() + scale();
1051
1052 if (actual_offset != 0) {
1053 HConstant* add_offset = new(block()->graph()->zone()) HConstant(
1054 actual_offset, index()->representation());
1055 add_offset->InsertBefore(this);
1056 HInstruction* add = HAdd::New(block()->graph()->zone(),
1057 block()->graph()->GetInvalidContext(), current_index, add_offset);
1058 add->InsertBefore(this);
1059 add->AssumeRepresentation(index()->representation());
1060 current_index = add;
1061 }
1062
1063 if (actual_scale != 0) {
1064 HConstant* sar_scale = new(block()->graph()->zone()) HConstant(
1065 actual_scale, index()->representation());
1066 sar_scale->InsertBefore(this);
1067 HInstruction* sar = HSar::New(block()->graph()->zone(),
1068 block()->graph()->GetInvalidContext(), current_index, sar_scale);
1069 sar->InsertBefore(this);
1070 sar->AssumeRepresentation(index()->representation());
1071 current_index = sar;
1072 }
1073
1074 SetOperandAt(0, current_index);
1075
1076 base_ = NULL;
1077 offset_ = 0;
1078 scale_ = 0;
1079 responsibility_direction_ = DIRECTION_NONE;
1080 }
1081
1082
891 void HBoundsCheck::AddInformativeDefinitions() { 1083 void HBoundsCheck::AddInformativeDefinitions() {
892 // TODO(mmassi): Executing this code during AddInformativeDefinitions 1084 // TODO(mmassi): Executing this code during AddInformativeDefinitions
893 // is a hack. Move it to some other HPhase. 1085 // is a hack. Move it to some other HPhase.
894 if (index()->IsRelationTrue(NumericRelation::Ge(), 1086 if (FLAG_array_bounds_checks_elimination) {
895 block()->graph()->GetConstant0()) && 1087 if (index()->TryGuaranteeRange(length())) {
896 index()->IsRelationTrue(NumericRelation::Lt(), length())) { 1088 set_skip_check(true);
897 set_skip_check(true); 1089 }
1090 if (DetectCompoundIndex()) {
1091 HBoundsCheckBaseIndexInformation* base_index_info =
1092 new(block()->graph()->zone())
1093 HBoundsCheckBaseIndexInformation(this);
1094 base_index_info->InsertAfter(this);
1095 }
898 } 1096 }
899 } 1097 }
900 1098
901 1099
902 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, 1100 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation,
903 HValue* related_value) { 1101 HValue* related_value,
1102 int offset,
1103 int scale) {
904 if (related_value == length()) { 1104 if (related_value == length()) {
905 // A HBoundsCheck is smaller than the length it compared against. 1105 // A HBoundsCheck is smaller than the length it compared against.
906 return NumericRelation::Lt().Implies(relation); 1106 return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale);
907 } else if (related_value == block()->graph()->GetConstant0()) { 1107 } else if (related_value == block()->graph()->GetConstant0()) {
908 // A HBoundsCheck is greater than or equal to zero. 1108 // A HBoundsCheck is greater than or equal to zero.
909 return NumericRelation::Ge().Implies(relation); 1109 return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale);
910 } else { 1110 } else {
911 return false; 1111 return false;
912 } 1112 }
913 } 1113 }
914 1114
915 1115
916 void HBoundsCheck::PrintDataTo(StringStream* stream) { 1116 void HBoundsCheck::PrintDataTo(StringStream* stream) {
917 index()->PrintNameTo(stream); 1117 index()->PrintNameTo(stream);
918 stream->Add(" "); 1118 stream->Add(" ");
919 length()->PrintNameTo(stream); 1119 length()->PrintNameTo(stream);
1120 if (base() != NULL && (offset() != 0 || scale() != 0)) {
1121 stream->Add(" base: ((");
1122 if (base() != index()) {
1123 index()->PrintNameTo(stream);
1124 } else {
1125 stream->Add("index");
1126 }
1127 stream->Add(" + %d) >> %d)", offset(), scale());
1128 }
920 if (skip_check()) { 1129 if (skip_check()) {
921 stream->Add(" [DISABLED]"); 1130 stream->Add(" [DISABLED]");
922 } 1131 }
923 } 1132 }
924 1133
925 1134
926 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) { 1135 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
927 ASSERT(CheckFlag(kFlexibleRepresentation)); 1136 ASSERT(CheckFlag(kFlexibleRepresentation));
928 Representation r; 1137 Representation r;
929 HValue* actual_length = length()->ActualValue(); 1138 HValue* actual_length = length()->ActualValue();
930 HValue* actual_index = index()->ActualValue(); 1139 HValue* actual_index = index()->ActualValue();
931 if (key_mode_ == DONT_ALLOW_SMI_KEY || 1140 if (key_mode_ == DONT_ALLOW_SMI_KEY ||
932 !actual_length->representation().IsTagged()) { 1141 !actual_length->representation().IsTagged()) {
933 r = Representation::Integer32(); 1142 r = Representation::Integer32();
934 } else if (actual_index->representation().IsTagged() || 1143 } else if (actual_index->representation().IsTagged() ||
935 (actual_index->IsConstant() && 1144 (actual_index->IsConstant() &&
936 HConstant::cast(actual_index)->HasSmiValue())) { 1145 HConstant::cast(actual_index)->HasSmiValue())) {
937 // If the index is tagged, or a constant that holds a Smi, allow the length 1146 // If the index is tagged, or a constant that holds a Smi, allow the length
938 // to be tagged, since it is usually already tagged from loading it out of 1147 // to be tagged, since it is usually already tagged from loading it out of
939 // the length field of a JSArray. This allows for direct comparison without 1148 // the length field of a JSArray. This allows for direct comparison without
940 // untagging. 1149 // untagging.
941 r = Representation::Tagged(); 1150 r = Representation::Tagged();
942 } else { 1151 } else {
943 r = Representation::Integer32(); 1152 r = Representation::Integer32();
944 } 1153 }
945 UpdateRepresentation(r, h_infer, "boundscheck"); 1154 UpdateRepresentation(r, h_infer, "boundscheck");
946 } 1155 }
947 1156
948 1157
1158 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal(
1159 NumericRelation relation,
1160 HValue* related_value,
1161 int offset,
1162 int scale) {
1163 if (related_value == bounds_check()->length()) {
1164 return NumericRelation::Lt().CompoundImplies(
1165 relation,
1166 bounds_check()->offset(), bounds_check()->scale(), offset, scale);
1167 } else if (related_value == block()->graph()->GetConstant0()) {
1168 return NumericRelation::Ge().CompoundImplies(
1169 relation,
1170 bounds_check()->offset(), bounds_check()->scale(), offset, scale);
1171 } else {
1172 return false;
1173 }
1174 }
1175
1176
1177 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
1178 stream->Add("base: ");
1179 base_index()->PrintNameTo(stream);
1180 stream->Add(", check: ");
1181 base_index()->PrintNameTo(stream);
1182 }
1183
1184
949 void HCallConstantFunction::PrintDataTo(StringStream* stream) { 1185 void HCallConstantFunction::PrintDataTo(StringStream* stream) {
950 if (IsApplyFunction()) { 1186 if (IsApplyFunction()) {
951 stream->Add("optimized apply "); 1187 stream->Add("optimized apply ");
952 } else { 1188 } else {
953 stream->Add("%o ", function()->shared()->DebugName()); 1189 stream->Add("%o ", function()->shared()->DebugName());
954 } 1190 }
955 stream->Add("#%d", argument_count()); 1191 stream->Add("#%d", argument_count());
956 } 1192 }
957 1193
958 1194
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after
1604 HInductionVariableAnnotation::AddToGraph(this, 1840 HInductionVariableAnnotation::AddToGraph(this,
1605 relations[relation_index], 1841 relations[relation_index],
1606 other_operand_index); 1842 other_operand_index);
1607 } 1843 }
1608 } 1844 }
1609 } 1845 }
1610 } 1846 }
1611 } 1847 }
1612 1848
1613 1849
1614 bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) { 1850 bool HPhi::IsRelationTrueInternal(NumericRelation relation,
1851 HValue* other,
1852 int offset,
1853 int scale) {
1615 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false; 1854 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
1616 1855
1617 SetFlag(kNumericConstraintEvaluationInProgress); 1856 SetFlag(kNumericConstraintEvaluationInProgress);
1618 bool result = true; 1857 bool result = true;
1619 for (int i = 0; i < OperandCount(); i++) { 1858 for (int i = 0; i < OperandCount(); i++) {
1620 // Skip OSR entry blocks 1859 // Skip OSR entry blocks
1621 if (OperandAt(i)->block()->is_osr_entry()) continue; 1860 if (OperandAt(i)->block()->is_osr_entry()) continue;
1622 1861
1623 if (!OperandAt(i)->IsRelationTrue(relation, other)) { 1862 if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) {
1624 result = false; 1863 result = false;
1625 break; 1864 break;
1626 } 1865 }
1627 } 1866 }
1628 ClearFlag(kNumericConstraintEvaluationInProgress); 1867 ClearFlag(kNumericConstraintEvaluationInProgress);
1629 1868
1630 return result; 1869 return result;
1631 } 1870 }
1632 1871
1633 1872
(...skipping 1645 matching lines...) Expand 10 before | Expand all | Expand 10 after
3279 3518
3280 3519
3281 void HCheckFunction::Verify() { 3520 void HCheckFunction::Verify() {
3282 HInstruction::Verify(); 3521 HInstruction::Verify();
3283 ASSERT(HasNoUses()); 3522 ASSERT(HasNoUses());
3284 } 3523 }
3285 3524
3286 #endif 3525 #endif
3287 3526
3288 } } // namespace v8::internal 3527 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698