| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/address-map.h" | 9 #include "src/address-map.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 private: | 202 private: |
| 203 ZoneVector<UseInfo> input_use_infos_; | 203 ZoneVector<UseInfo> input_use_infos_; |
| 204 | 204 |
| 205 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { | 205 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { |
| 206 return use1.truncation().IsLessGeneralThan(use2.truncation()); | 206 return use1.truncation().IsLessGeneralThan(use2.truncation()); |
| 207 } | 207 } |
| 208 }; | 208 }; |
| 209 | 209 |
| 210 #endif // DEBUG | 210 #endif // DEBUG |
| 211 | 211 |
| 212 bool CanOverflowSigned32(const Operator* op, Type* left, Type* right, |
| 213 Zone* type_zone) { |
| 214 // We assume the inputs are checked Signed32 (or known statically |
| 215 // to be Signed32). Technically, theinputs could also be minus zero, but |
| 216 // that cannot cause overflow. |
| 217 left = Type::Intersect(left, Type::Signed32(), type_zone); |
| 218 right = Type::Intersect(right, Type::Signed32(), type_zone); |
| 219 if (!left->IsInhabited() || !right->IsInhabited()) return false; |
| 220 switch (op->opcode()) { |
| 221 case IrOpcode::kSpeculativeNumberAdd: |
| 222 return (left->Max() + right->Max() > kMaxInt) || |
| 223 (left->Min() + right->Min() < kMinInt); |
| 224 |
| 225 case IrOpcode::kSpeculativeNumberSubtract: |
| 226 return (left->Max() - right->Min() > kMaxInt) || |
| 227 (left->Min() - right->Max() < kMinInt); |
| 228 |
| 229 default: |
| 230 UNREACHABLE(); |
| 231 } |
| 232 return true; |
| 233 } |
| 234 |
| 212 } // namespace | 235 } // namespace |
| 213 | 236 |
| 214 | |
| 215 class RepresentationSelector { | 237 class RepresentationSelector { |
| 216 public: | 238 public: |
| 217 // Information for each node tracked during the fixpoint. | 239 // Information for each node tracked during the fixpoint. |
| 218 class NodeInfo final { | 240 class NodeInfo final { |
| 219 public: | 241 public: |
| 220 // Adds new use to the node. Returns true if something has changed | 242 // Adds new use to the node. Returns true if something has changed |
| 221 // and the node has to be requeued. | 243 // and the node has to be requeued. |
| 222 bool AddUse(UseInfo info) { | 244 bool AddUse(UseInfo info) { |
| 223 Truncation old_truncation = truncation_; | 245 Truncation old_truncation = truncation_; |
| 224 truncation_ = Truncation::Generalize(truncation_, info.truncation()); | 246 truncation_ = Truncation::Generalize(truncation_, info.truncation()); |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 | 1179 |
| 1158 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, | 1180 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation, |
| 1159 SimplifiedLowering* lowering) { | 1181 SimplifiedLowering* lowering) { |
| 1160 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can | 1182 // ToNumber(x) can throw if x is either a Receiver or a Symbol, so we can |
| 1161 // only eliminate an unused speculative number operation if we know that | 1183 // only eliminate an unused speculative number operation if we know that |
| 1162 // the inputs are PlainPrimitive, which excludes everything that's might | 1184 // the inputs are PlainPrimitive, which excludes everything that's might |
| 1163 // have side effects or throws during a ToNumber conversion. | 1185 // have side effects or throws during a ToNumber conversion. |
| 1164 if (BothInputsAre(node, Type::PlainPrimitive())) { | 1186 if (BothInputsAre(node, Type::PlainPrimitive())) { |
| 1165 if (truncation.IsUnused()) return VisitUnused(node); | 1187 if (truncation.IsUnused()) return VisitUnused(node); |
| 1166 } | 1188 } |
| 1189 |
| 1167 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && | 1190 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && |
| 1168 (GetUpperBound(node)->Is(Type::Signed32()) || | 1191 (GetUpperBound(node)->Is(Type::Signed32()) || |
| 1169 GetUpperBound(node)->Is(Type::Unsigned32()) || | 1192 GetUpperBound(node)->Is(Type::Unsigned32()) || |
| 1170 truncation.IsUsedAsWord32())) { | 1193 truncation.IsUsedAsWord32())) { |
| 1171 // => Int32Add/Sub | 1194 // => Int32Add/Sub |
| 1172 VisitWord32TruncatingBinop(node); | 1195 VisitWord32TruncatingBinop(node); |
| 1173 if (lower()) ChangeToPureOp(node, Int32Op(node)); | 1196 if (lower()) ChangeToPureOp(node, Int32Op(node)); |
| 1174 return; | 1197 return; |
| 1175 } | 1198 } |
| 1176 | 1199 |
| 1177 // Try to use type feedback. | 1200 // Try to use type feedback. |
| 1178 NumberOperationHint hint = NumberOperationHintOf(node->op()); | 1201 NumberOperationHint hint = NumberOperationHintOf(node->op()); |
| 1179 | 1202 |
| 1180 // Handle the case when no int32 checks on inputs are necessary | 1203 if (hint == NumberOperationHint::kSignedSmall || |
| 1181 // (but an overflow check is needed on the output). | 1204 hint == NumberOperationHint::kSigned32) { |
| 1182 if (BothInputsAre(node, Type::Signed32()) || | 1205 Type* left_feedback_type = TypeOf(node->InputAt(0)); |
| 1183 (BothInputsAre(node, Type::Signed32OrMinusZero()) && | 1206 Type* right_feedback_type = TypeOf(node->InputAt(1)); |
| 1184 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) { | 1207 // Handle the case when no int32 checks on inputs are necessary (but |
| 1185 // If both the inputs the feedback are int32, use the overflow op. | 1208 // an overflow check is needed on the output). |
| 1186 if (hint == NumberOperationHint::kSignedSmall || | 1209 // TODO(jarin) We should not look at the upper bound because the typer |
| 1187 hint == NumberOperationHint::kSigned32) { | 1210 // could have already baked in some feedback into the upper bound. |
| 1211 if (BothInputsAre(node, Type::Signed32()) || |
| 1212 (BothInputsAre(node, Type::Signed32OrMinusZero()) && |
| 1213 GetUpperBound(node)->Is(type_cache_.kSafeInteger))) { |
| 1188 VisitBinop(node, UseInfo::TruncatingWord32(), | 1214 VisitBinop(node, UseInfo::TruncatingWord32(), |
| 1189 MachineRepresentation::kWord32, Type::Signed32()); | 1215 MachineRepresentation::kWord32, Type::Signed32()); |
| 1190 if (lower()) ChangeToInt32OverflowOp(node); | 1216 } else { |
| 1191 return; | 1217 UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint); |
| 1218 // For CheckedInt32Add and CheckedInt32Sub, we don't need to do |
| 1219 // a minus zero check for the right hand side, since we already |
| 1220 // know that the left hand side is a proper Signed32 value, |
| 1221 // potentially guarded by a check. |
| 1222 UseInfo right_use = CheckedUseInfoAsWord32FromHint( |
| 1223 hint, CheckForMinusZeroMode::kDontCheckForMinusZero); |
| 1224 VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32, |
| 1225 Type::Signed32()); |
| 1192 } | 1226 } |
| 1193 } | 1227 if (lower()) { |
| 1194 | 1228 if (CanOverflowSigned32(node->op(), left_feedback_type, |
| 1195 if (hint == NumberOperationHint::kSignedSmall || | 1229 right_feedback_type, graph_zone())) { |
| 1196 hint == NumberOperationHint::kSigned32) { | 1230 ChangeToInt32OverflowOp(node); |
| 1197 UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint); | 1231 } else { |
| 1198 // For CheckedInt32Add and CheckedInt32Sub, we don't need to do | 1232 ChangeToPureOp(node, Int32Op(node)); |
| 1199 // a minus zero check for the right hand side, since we already | 1233 } |
| 1200 // know that the left hand side is a proper Signed32 value, | 1234 } |
| 1201 // potentially guarded by a check. | |
| 1202 UseInfo right_use = CheckedUseInfoAsWord32FromHint( | |
| 1203 hint, CheckForMinusZeroMode::kDontCheckForMinusZero); | |
| 1204 VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32, | |
| 1205 Type::Signed32()); | |
| 1206 if (lower()) ChangeToInt32OverflowOp(node); | |
| 1207 return; | 1235 return; |
| 1208 } | 1236 } |
| 1209 | 1237 |
| 1210 // default case => Float64Add/Sub | 1238 // default case => Float64Add/Sub |
| 1211 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), | 1239 VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(), |
| 1212 MachineRepresentation::kFloat64, Type::Number()); | 1240 MachineRepresentation::kFloat64, Type::Number()); |
| 1213 if (lower()) { | 1241 if (lower()) { |
| 1214 ChangeToPureOp(node, Float64Op(node)); | 1242 ChangeToPureOp(node, Float64Op(node)); |
| 1215 } | 1243 } |
| 1216 return; | 1244 return; |
| (...skipping 2194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3411 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3439 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3412 Operator::kNoProperties); | 3440 Operator::kNoProperties); |
| 3413 to_number_operator_.set(common()->Call(desc)); | 3441 to_number_operator_.set(common()->Call(desc)); |
| 3414 } | 3442 } |
| 3415 return to_number_operator_.get(); | 3443 return to_number_operator_.get(); |
| 3416 } | 3444 } |
| 3417 | 3445 |
| 3418 } // namespace compiler | 3446 } // namespace compiler |
| 3419 } // namespace internal | 3447 } // namespace internal |
| 3420 } // namespace v8 | 3448 } // namespace v8 |
| OLD | NEW |