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

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: Addressed review comments. 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
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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) { 153 void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
154 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { 154 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
155 h_infer->AddToWorklist(it.value()); 155 h_infer->AddToWorklist(it.value());
156 } 156 }
157 for (int i = 0; i < OperandCount(); ++i) { 157 for (int i = 0; i < OperandCount(); ++i) {
158 h_infer->AddToWorklist(OperandAt(i)); 158 h_infer->AddToWorklist(OperandAt(i));
159 } 159 }
160 } 160 }
161 161
162 162
163 // This method is recursive but it is guaranteed to terminate because
164 // RedefinedOperand() always dominates "this".
165 bool HValue::IsRelationTrue(NumericRelation relation,
166 HValue* other,
167 int offset,
168 int scale) {
169 if (this == other) {
170 return NumericRelation::Eq().Implies(relation);
171 }
172
173 // Test the direct relation.
174 if (IsRelationTrueInternal(relation, other, offset, scale)) return true;
175
176 // If scale is 0 try the reversed relation..
Jakob Kummerow 2013/03/14 12:50:09 nit: s/.././
Massi 2013/03/14 15:07:18 Done.
177 if (scale == 0 &&
178 // TODO(mmassi): do we need the full, recursive IsRelationTrue?
179 other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) {
180 return true;
181 }
182
183 // Try decomposition.
184 HValue* my_base = NULL;
185 int my_offset = 0;
186 int my_scale = 0;
187 if (TryDecompose(&my_base, &my_offset, &my_scale) && my_scale == 0 &&
188 my_base->IsRelationTrue(relation, other, offset + my_offset, scale)) {
189 return true;
190 }
191
192 // Pass the request to the redefined value.
193 HValue* redefined = RedefinedOperand();
194 return redefined != NULL && redefined->IsRelationTrue(relation, other,
195 offset, scale);
196 }
197
198
199 bool HValue::TryGuaranteeRange(HValue* upper_bound) {
200 RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
201 TryGuaranteeRangeRecursive(&context);
202 bool result = context.is_range_satisfied();
203 if (result) {
204 context.lower_check_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER);
205 context.upper_check_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER);
206 }
207 return result;
208 }
209
210
211 void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
212 // Check if we already know that this value satisfies the lower bound.
213 if (!context->is_lower_bound_satisfied()) {
214 if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
215 context->offset(), context->scale())) {
216 context->set_lower_check_guarantee(this);
217 }
218 }
219
220 // Check if we already know that this value satisfies the upper bound.
221 if (!context->is_upper_bound_satisfied()) {
222 if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
223 context->offset(), context->scale()) ||
224 (context->scale() == 0 &&
225 context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
226 this, -context->offset()))) {
227 context->set_upper_check_guarantee(this);
228 }
229 }
230
231 if (context->is_range_satisfied()) return;
232
233 // See if our RedefinedOperand() satisfies the constraints.
234 if (RedefinedOperand() != NULL) {
235 RedefinedOperand()->TryGuaranteeRangeRecursive(context);
236 }
237 if (context->is_range_satisfied()) return;
238
239 // See if the constraints can be satisfied by decomposition.
240 HValue* base = NULL;
241 int offset = context->offset();
242 int scale = context->scale();
243 if (TryDecompose(&base, &offset, &scale)) {
244 context->swap_candidate(&base, &offset, &scale);
245 context->candidate()->TryGuaranteeRangeRecursive(context);
246 context->swap_candidate(&base, &offset, &scale);
247 }
248 if (context->is_range_satisfied()) return;
249
250 // Try to modify this to satisfy the constraint.
251
252 TryGuaranteeRangeChanging(context);
253 }
254
255
256 RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper)
257 : lower_bound_(upper->block()->graph()->GetConstant0()),
258 lower_check_guarantee_(NULL),
259 candidate_(value),
260 upper_bound_(upper),
261 upper_check_guarantee_(NULL),
262 offset_(0),
263 scale_(0) {
264 }
265
266
267 HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
268 return guarantee->IsBoundsCheckBaseIndexInformation()
269 ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
270 : guarantee;
271 }
272
273
163 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { 274 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
164 if (result > kMaxInt) { 275 if (result > kMaxInt) {
165 *overflow = true; 276 *overflow = true;
166 return kMaxInt; 277 return kMaxInt;
167 } 278 }
168 if (result < kMinInt) { 279 if (result < kMinInt) {
169 *overflow = true; 280 *overflow = true;
170 return kMinInt; 281 return kMinInt;
171 } 282 }
172 return static_cast<int32_t>(result); 283 return static_cast<int32_t>(result);
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 989
879 void HBinaryCall::PrintDataTo(StringStream* stream) { 990 void HBinaryCall::PrintDataTo(StringStream* stream) {
880 first()->PrintNameTo(stream); 991 first()->PrintNameTo(stream);
881 stream->Add(" "); 992 stream->Add(" ");
882 second()->PrintNameTo(stream); 993 second()->PrintNameTo(stream);
883 stream->Add(" "); 994 stream->Add(" ");
884 stream->Add("#%d", argument_count()); 995 stream->Add("#%d", argument_count());
885 } 996 }
886 997
887 998
999 void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
1000 if (context->candidate()->ActualValue() != base()->ActualValue() ||
1001 context->scale() < scale()) {
1002 return;
1003 }
1004
1005 // TODO(mmassi)
1006 // Instead of checking for "same basic block" we should check for
1007 // "dominates and postdominates".
1008 if (context->upper_bound() == length() &&
1009 context->is_lower_bound_satisfied() &&
1010 context->lower_check_guarantee() != this &&
1011 context->lower_check_guarantee()->block() != block() &&
1012 offset() < context->offset() &&
1013 index_can_increase() &&
1014 !context->is_upper_bound_satisfied()) {
1015 offset_ = context->offset();
1016 SetResponsibilityForRange(DIRECTION_UPPER);
1017 context->set_upper_check_guarantee(this);
1018 } else if (context->is_upper_bound_satisfied() &&
1019 context->upper_check_guarantee() != this &&
1020 context->upper_check_guarantee()->block() != block() &&
1021 offset() > context->offset() &&
1022 index_can_decrease() &&
1023 !context->is_lower_bound_satisfied()) {
1024 offset_ = context->offset();
1025 SetResponsibilityForRange(DIRECTION_LOWER);
1026 context->set_lower_check_guarantee(this);
1027 }
1028 }
1029
1030
1031 void HBoundsCheck::ApplyIndexChange() {
1032 if (skip_check()) return;
1033
1034 HValue* index_base = NULL;
1035 int index_offset = 0;
1036 int index_scale = 0;
1037 bool index_is_decomposable = index()->TryDecompose(
1038 &index_base, &index_offset, &index_scale);
1039 if (index_is_decomposable) {
1040 ASSERT(index_base == base());
1041 if (index_offset == offset() && index_scale == scale()) return;
1042 } else {
1043 return;
1044 }
1045
1046 ReplaceAllUsesWith(index());
1047
1048 HValue* current_index = index_base;
1049 int actual_offset = index_offset + offset();
1050 int actual_scale = index_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 HAdd* add = new(block()->graph()->zone()) HAdd(
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 HSar* sar = new(block()->graph()->zone()) HSar(
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
888 void HBoundsCheck::AddInformativeDefinitions() { 1083 void HBoundsCheck::AddInformativeDefinitions() {
889 // TODO(mmassi): Executing this code during AddInformativeDefinitions 1084 // TODO(mmassi): Executing this code during AddInformativeDefinitions
890 // is a hack. Move it to some other HPhase. 1085 // is a hack. Move it to some other HPhase.
891 if (index()->IsRelationTrue(NumericRelation::Ge(), 1086 if (FLAG_new_abcd) {
892 block()->graph()->GetConstant0()) && 1087 if (index()->TryGuaranteeRange(length())) {
893 index()->IsRelationTrue(NumericRelation::Lt(), length())) { 1088 set_skip_check(true);
894 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 }
1096 } else {
1097 if (index()->IsRelationTrue(NumericRelation::Ge(),
1098 block()->graph()->GetConstant0()) &&
1099 index()->IsRelationTrue(NumericRelation::Lt(), length())) {
1100 set_skip_check(true);
1101 }
895 } 1102 }
896 } 1103 }
897 1104
898 1105
899 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation, 1106 bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation,
900 HValue* related_value) { 1107 HValue* related_value,
1108 int offset,
1109 int scale) {
901 if (related_value == length()) { 1110 if (related_value == length()) {
902 // A HBoundsCheck is smaller than the length it compared against. 1111 // A HBoundsCheck is smaller than the length it compared against.
903 return NumericRelation::Lt().Implies(relation); 1112 return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale);
904 } else if (related_value == block()->graph()->GetConstant0()) { 1113 } else if (related_value == block()->graph()->GetConstant0()) {
905 // A HBoundsCheck is greater than or equal to zero. 1114 // A HBoundsCheck is greater than or equal to zero.
906 return NumericRelation::Ge().Implies(relation); 1115 return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale);
907 } else { 1116 } else {
908 return false; 1117 return false;
909 } 1118 }
910 } 1119 }
911 1120
912 1121
913 void HBoundsCheck::PrintDataTo(StringStream* stream) { 1122 void HBoundsCheck::PrintDataTo(StringStream* stream) {
914 index()->PrintNameTo(stream); 1123 index()->PrintNameTo(stream);
915 stream->Add(" "); 1124 stream->Add(" ");
916 length()->PrintNameTo(stream); 1125 length()->PrintNameTo(stream);
1126 if (base() != NULL && (offset() != 0 || scale() != 0)) {
1127 stream->Add(" base: ((");
1128 if (base() != index()) {
1129 index()->PrintNameTo(stream);
1130 } else {
1131 stream->Add("index");
1132 }
1133 stream->Add(" + %d) >> %d)", offset(), scale());
1134 }
917 if (skip_check()) { 1135 if (skip_check()) {
918 stream->Add(" [DISABLED]"); 1136 stream->Add(" [DISABLED]");
919 } 1137 }
920 } 1138 }
921 1139
922 1140
923 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) { 1141 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
924 ASSERT(CheckFlag(kFlexibleRepresentation)); 1142 ASSERT(CheckFlag(kFlexibleRepresentation));
925 Representation r; 1143 Representation r;
926 if (key_mode_ == DONT_ALLOW_SMI_KEY || 1144 if (key_mode_ == DONT_ALLOW_SMI_KEY ||
927 !length()->representation().IsTagged()) { 1145 !length()->representation().IsTagged()) {
928 r = Representation::Integer32(); 1146 r = Representation::Integer32();
929 } else if (index()->representation().IsTagged() || 1147 } else if (index()->representation().IsTagged() ||
930 (index()->ActualValue()->IsConstant() && 1148 (index()->ActualValue()->IsConstant() &&
931 HConstant::cast(index()->ActualValue())->HasSmiValue())) { 1149 HConstant::cast(index()->ActualValue())->HasSmiValue())) {
932 // If the index is tagged, or a constant that holds a Smi, allow the length 1150 // If the index is tagged, or a constant that holds a Smi, allow the length
933 // to be tagged, since it is usually already tagged from loading it out of 1151 // to be tagged, since it is usually already tagged from loading it out of
934 // the length field of a JSArray. This allows for direct comparison without 1152 // the length field of a JSArray. This allows for direct comparison without
935 // untagging. 1153 // untagging.
936 r = Representation::Tagged(); 1154 r = Representation::Tagged();
937 } else { 1155 } else {
938 r = Representation::Integer32(); 1156 r = Representation::Integer32();
939 } 1157 }
940 UpdateRepresentation(r, h_infer, "boundscheck"); 1158 UpdateRepresentation(r, h_infer, "boundscheck");
941 } 1159 }
942 1160
943 1161
1162 bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal(
1163 NumericRelation relation,
1164 HValue* related_value,
1165 int offset,
1166 int scale) {
1167 if (related_value == bounds_check()->length()) {
1168 return NumericRelation::Lt().CompoundImplies(
1169 relation,
1170 bounds_check()->offset(), bounds_check()->scale(), offset, scale);
1171 } else if (related_value == block()->graph()->GetConstant0()) {
1172 return NumericRelation::Ge().CompoundImplies(
1173 relation,
1174 bounds_check()->offset(), bounds_check()->scale(), offset, scale);
1175 } else {
1176 return false;
1177 }
1178 }
1179
1180
1181 void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
1182 stream->Add("base: ");
1183 base_index()->PrintNameTo(stream);
1184 stream->Add(", check: ");
1185 base_index()->PrintNameTo(stream);
1186 }
1187
1188
944 void HCallConstantFunction::PrintDataTo(StringStream* stream) { 1189 void HCallConstantFunction::PrintDataTo(StringStream* stream) {
945 if (IsApplyFunction()) { 1190 if (IsApplyFunction()) {
946 stream->Add("optimized apply "); 1191 stream->Add("optimized apply ");
947 } else { 1192 } else {
948 stream->Add("%o ", function()->shared()->DebugName()); 1193 stream->Add("%o ", function()->shared()->DebugName());
949 } 1194 }
950 stream->Add("#%d", argument_count()); 1195 stream->Add("#%d", argument_count());
951 } 1196 }
952 1197
953 1198
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 HInductionVariableAnnotation::AddToGraph(this, 1842 HInductionVariableAnnotation::AddToGraph(this,
1598 relations[relation_index], 1843 relations[relation_index],
1599 other_operand_index); 1844 other_operand_index);
1600 } 1845 }
1601 } 1846 }
1602 } 1847 }
1603 } 1848 }
1604 } 1849 }
1605 1850
1606 1851
1607 bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) { 1852 bool HPhi::IsRelationTrueInternal(NumericRelation relation,
1853 HValue* other,
1854 int offset,
1855 int scale) {
1608 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false; 1856 if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
1609 1857
1610 SetFlag(kNumericConstraintEvaluationInProgress); 1858 SetFlag(kNumericConstraintEvaluationInProgress);
1611 bool result = true; 1859 bool result = true;
1612 for (int i = 0; i < OperandCount(); i++) { 1860 for (int i = 0; i < OperandCount(); i++) {
1613 // Skip OSR entry blocks 1861 // Skip OSR entry blocks
1614 if (OperandAt(i)->block()->is_osr_entry()) continue; 1862 if (OperandAt(i)->block()->is_osr_entry()) continue;
1615 1863
1616 if (!OperandAt(i)->IsRelationTrue(relation, other)) { 1864 if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) {
1617 result = false; 1865 result = false;
1618 break; 1866 break;
1619 } 1867 }
1620 } 1868 }
1621 ClearFlag(kNumericConstraintEvaluationInProgress); 1869 ClearFlag(kNumericConstraintEvaluationInProgress);
1622 1870
1623 return result; 1871 return result;
1624 } 1872 }
1625 1873
1626 1874
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after
3100 3348
3101 3349
3102 void HCheckFunction::Verify() { 3350 void HCheckFunction::Verify() {
3103 HInstruction::Verify(); 3351 HInstruction::Verify();
3104 ASSERT(HasNoUses()); 3352 ASSERT(HasNoUses());
3105 } 3353 }
3106 3354
3107 #endif 3355 #endif
3108 3356
3109 } } // namespace v8::internal 3357 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698