 Chromium Code Reviews
 Chromium Code Reviews Issue 2734253002:
  [turbofan] Propagate minus-zero truncation in representation inference.  (Closed)
    
  
    Issue 2734253002:
  [turbofan] Propagate minus-zero truncation in representation inference.  (Closed) 
  | 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 case kExternalFloat32Array: | 81 case kExternalFloat32Array: | 
| 82 return MachineRepresentation::kFloat32; | 82 return MachineRepresentation::kFloat32; | 
| 83 case kExternalFloat64Array: | 83 case kExternalFloat64Array: | 
| 84 return MachineRepresentation::kFloat64; | 84 return MachineRepresentation::kFloat64; | 
| 85 } | 85 } | 
| 86 UNREACHABLE(); | 86 UNREACHABLE(); | 
| 87 return MachineRepresentation::kNone; | 87 return MachineRepresentation::kNone; | 
| 88 } | 88 } | 
| 89 | 89 | 
| 90 UseInfo CheckedUseInfoAsWord32FromHint( | 90 UseInfo CheckedUseInfoAsWord32FromHint( | 
| 91 NumberOperationHint hint, CheckForMinusZeroMode minus_zero_mode = | 91 NumberOperationHint hint, | 
| 92 CheckForMinusZeroMode::kCheckForMinusZero) { | 92 IdentifyZeros identify_zeros = kDistinguishZeros) { | 
| 93 switch (hint) { | 93 switch (hint) { | 
| 94 case NumberOperationHint::kSignedSmall: | 94 case NumberOperationHint::kSignedSmall: | 
| 95 return UseInfo::CheckedSignedSmallAsWord32(minus_zero_mode); | 95 return UseInfo::CheckedSignedSmallAsWord32(identify_zeros); | 
| 96 case NumberOperationHint::kSigned32: | 96 case NumberOperationHint::kSigned32: | 
| 97 return UseInfo::CheckedSigned32AsWord32(minus_zero_mode); | 97 return UseInfo::CheckedSigned32AsWord32(identify_zeros); | 
| 98 case NumberOperationHint::kNumber: | 98 case NumberOperationHint::kNumber: | 
| 99 return UseInfo::CheckedNumberAsWord32(); | 99 return UseInfo::CheckedNumberAsWord32(); | 
| 100 case NumberOperationHint::kNumberOrOddball: | 100 case NumberOperationHint::kNumberOrOddball: | 
| 101 return UseInfo::CheckedNumberOrOddballAsWord32(); | 101 return UseInfo::CheckedNumberOrOddballAsWord32(); | 
| 102 } | 102 } | 
| 103 UNREACHABLE(); | 103 UNREACHABLE(); | 
| 104 return UseInfo::None(); | 104 return UseInfo::None(); | 
| 105 } | 105 } | 
| 106 | 106 | 
| 107 UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) { | 107 UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint) { | 
| (...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1160 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | 1160 CommonOperatorBuilder* common() const { return jsgraph_->common(); } | 
| 1161 SimplifiedOperatorBuilder* simplified() const { | 1161 SimplifiedOperatorBuilder* simplified() const { | 
| 1162 return jsgraph_->simplified(); | 1162 return jsgraph_->simplified(); | 
| 1163 } | 1163 } | 
| 1164 | 1164 | 
| 1165 void LowerToCheckedInt32Mul(Node* node, Truncation truncation, | 1165 void LowerToCheckedInt32Mul(Node* node, Truncation truncation, | 
| 1166 Type* input0_type, Type* input1_type) { | 1166 Type* input0_type, Type* input1_type) { | 
| 1167 // If one of the inputs is positive and/or truncation is being applied, | 1167 // If one of the inputs is positive and/or truncation is being applied, | 
| 1168 // there is no need to return -0. | 1168 // there is no need to return -0. | 
| 1169 CheckForMinusZeroMode mz_mode = | 1169 CheckForMinusZeroMode mz_mode = | 
| 1170 truncation.IsUsedAsWord32() || | 1170 truncation.IdentifiesZeroAndMinusZero() || | 
| 1171 (input0_type->Is(Type::OrderedNumber()) && | 1171 (input0_type->Is(Type::OrderedNumber()) && | 
| 1172 input0_type->Min() > 0) || | 1172 input0_type->Min() > 0) || | 
| 1173 (input1_type->Is(Type::OrderedNumber()) && | 1173 (input1_type->Is(Type::OrderedNumber()) && | 
| 1174 input1_type->Min() > 0) | 1174 input1_type->Min() > 0) | 
| 1175 ? CheckForMinusZeroMode::kDontCheckForMinusZero | 1175 ? CheckForMinusZeroMode::kDontCheckForMinusZero | 
| 1176 : CheckForMinusZeroMode::kCheckForMinusZero; | 1176 : CheckForMinusZeroMode::kCheckForMinusZero; | 
| 1177 | 1177 | 
| 1178 NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode)); | 1178 NodeProperties::ChangeOp(node, simplified()->CheckedInt32Mul(mz_mode)); | 
| 1179 } | 1179 } | 
| 1180 | 1180 | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1219 // Handle the case when no int32 checks on inputs are necessary (but | 1219 // Handle the case when no int32 checks on inputs are necessary (but | 
| 1220 // an overflow check is needed on the output). | 1220 // an overflow check is needed on the output). | 
| 1221 // TODO(jarin) We should not look at the upper bound because the typer | 1221 // TODO(jarin) We should not look at the upper bound because the typer | 
| 1222 // could have already baked in some feedback into the upper bound. | 1222 // could have already baked in some feedback into the upper bound. | 
| 1223 if (BothInputsAre(node, Type::Signed32()) || | 1223 if (BothInputsAre(node, Type::Signed32()) || | 
| 1224 (BothInputsAre(node, Type::Signed32OrMinusZero()) && | 1224 (BothInputsAre(node, Type::Signed32OrMinusZero()) && | 
| 1225 GetUpperBound(node)->Is(type_cache_.kSafeInteger))) { | 1225 GetUpperBound(node)->Is(type_cache_.kSafeInteger))) { | 
| 1226 VisitBinop(node, UseInfo::TruncatingWord32(), | 1226 VisitBinop(node, UseInfo::TruncatingWord32(), | 
| 1227 MachineRepresentation::kWord32, Type::Signed32()); | 1227 MachineRepresentation::kWord32, Type::Signed32()); | 
| 1228 } else { | 1228 } else { | 
| 1229 UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint); | 1229 IdentifyZeros lhs_identify_zeros = truncation.identify_zeros(); | 
| 
Benedikt Meurer
2017/03/08 03:56:53
Nit: left instead of lbs for consistency.
 
Jarin
2017/03/08 05:46:51
Done.
 | |
| 1230 if (node->opcode() == IrOpcode::kSpeculativeNumberAdd && | |
| 
Benedikt Meurer
2017/03/08 03:56:53
This deserves a comment, maybe just repeating the
 
Jarin
2017/03/08 05:46:51
Done.
 | |
| 1231 !right_feedback_type->Maybe(Type::MinusZero())) { | |
| 1232 lhs_identify_zeros = kIdentifyZeros; | |
| 1233 } | |
| 1234 UseInfo left_use = | |
| 1235 CheckedUseInfoAsWord32FromHint(hint, lhs_identify_zeros); | |
| 1230 // For CheckedInt32Add and CheckedInt32Sub, we don't need to do | 1236 // For CheckedInt32Add and CheckedInt32Sub, we don't need to do | 
| 1231 // a minus zero check for the right hand side, since we already | 1237 // a minus zero check for the right hand side, since we already | 
| 1232 // know that the left hand side is a proper Signed32 value, | 1238 // know that the left hand side is a proper Signed32 value, | 
| 1233 // potentially guarded by a check. | 1239 // potentially guarded by a check. | 
| 1234 UseInfo right_use = CheckedUseInfoAsWord32FromHint( | 1240 UseInfo right_use = | 
| 1235 hint, CheckForMinusZeroMode::kDontCheckForMinusZero); | 1241 CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros); | 
| 1236 VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32, | 1242 VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32, | 
| 1237 Type::Signed32()); | 1243 Type::Signed32()); | 
| 1238 } | 1244 } | 
| 1239 if (lower()) { | 1245 if (lower()) { | 
| 1240 if (CanOverflowSigned32(node->op(), left_feedback_type, | 1246 if (CanOverflowSigned32(node->op(), left_feedback_type, | 
| 1241 right_feedback_type, graph_zone())) { | 1247 right_feedback_type, graph_zone())) { | 
| 1242 ChangeToInt32OverflowOp(node); | 1248 ChangeToInt32OverflowOp(node); | 
| 1243 } else { | 1249 } else { | 
| 1244 ChangeToPureOp(node, Int32Op(node)); | 1250 ChangeToPureOp(node, Int32Op(node)); | 
| 1245 } | 1251 } | 
| (...skipping 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2273 Type* length_type = TypeOf(node->InputAt(1)); | 2279 Type* length_type = TypeOf(node->InputAt(1)); | 
| 2274 if (index_type->Is(Type::Unsigned32())) { | 2280 if (index_type->Is(Type::Unsigned32())) { | 
| 2275 VisitBinop(node, UseInfo::TruncatingWord32(), | 2281 VisitBinop(node, UseInfo::TruncatingWord32(), | 
| 2276 MachineRepresentation::kWord32); | 2282 MachineRepresentation::kWord32); | 
| 2277 if (lower() && index_type->Max() < length_type->Min()) { | 2283 if (lower() && index_type->Max() < length_type->Min()) { | 
| 2278 // The bounds check is redundant if we already know that | 2284 // The bounds check is redundant if we already know that | 
| 2279 // the index is within the bounds of [0.0, length[. | 2285 // the index is within the bounds of [0.0, length[. | 
| 2280 DeferReplacement(node, node->InputAt(0)); | 2286 DeferReplacement(node, node->InputAt(0)); | 
| 2281 } | 2287 } | 
| 2282 } else { | 2288 } else { | 
| 2283 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(), | 2289 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(kIdentifyZeros), | 
| 2284 UseInfo::TruncatingWord32(), | 2290 UseInfo::TruncatingWord32(), | 
| 2285 MachineRepresentation::kWord32); | 2291 MachineRepresentation::kWord32); | 
| 2286 } | 2292 } | 
| 2287 return; | 2293 return; | 
| 2288 } | 2294 } | 
| 2289 case IrOpcode::kCheckHeapObject: { | 2295 case IrOpcode::kCheckHeapObject: { | 
| 2290 if (InputCannotBe(node, Type::SignedSmall())) { | 2296 if (InputCannotBe(node, Type::SignedSmall())) { | 
| 2291 VisitUnop(node, UseInfo::AnyTagged(), | 2297 VisitUnop(node, UseInfo::AnyTagged(), | 
| 2292 MachineRepresentation::kTaggedPointer); | 2298 MachineRepresentation::kTaggedPointer); | 
| 2293 } else { | 2299 } else { | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2339 MachineRepresentation::kTaggedPointer); | 2345 MachineRepresentation::kTaggedPointer); | 
| 2340 if (lower()) DeferReplacement(node, node->InputAt(0)); | 2346 if (lower()) DeferReplacement(node, node->InputAt(0)); | 
| 2341 } else { | 2347 } else { | 
| 2342 VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(), | 2348 VisitUnop(node, UseInfo::CheckedHeapObjectAsTaggedPointer(), | 
| 2343 MachineRepresentation::kTaggedPointer); | 2349 MachineRepresentation::kTaggedPointer); | 
| 2344 } | 2350 } | 
| 2345 return; | 2351 return; | 
| 2346 } | 2352 } | 
| 2347 case IrOpcode::kCheckSmi: { | 2353 case IrOpcode::kCheckSmi: { | 
| 2348 if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) { | 2354 if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) { | 
| 2349 VisitUnop(node, UseInfo::CheckedSignedSmallAsWord32(), | 2355 VisitUnop(node, | 
| 2356 UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros), | |
| 2350 MachineRepresentation::kWord32); | 2357 MachineRepresentation::kWord32); | 
| 2351 } else { | 2358 } else { | 
| 2352 VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(), | 2359 VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(), | 
| 2353 MachineRepresentation::kTaggedSigned); | 2360 MachineRepresentation::kTaggedSigned); | 
| 2354 } | 2361 } | 
| 2355 if (lower()) DeferReplacement(node, node->InputAt(0)); | 2362 if (lower()) DeferReplacement(node, node->InputAt(0)); | 
| 2356 return; | 2363 return; | 
| 2357 } | 2364 } | 
| 2358 case IrOpcode::kCheckString: { | 2365 case IrOpcode::kCheckString: { | 
| 2359 if (InputIs(node, Type::String())) { | 2366 if (InputIs(node, Type::String())) { | 
| (...skipping 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3570 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3577 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 
| 3571 Operator::kNoProperties); | 3578 Operator::kNoProperties); | 
| 3572 to_number_operator_.set(common()->Call(desc)); | 3579 to_number_operator_.set(common()->Call(desc)); | 
| 3573 } | 3580 } | 
| 3574 return to_number_operator_.get(); | 3581 return to_number_operator_.get(); | 
| 3575 } | 3582 } | 
| 3576 | 3583 | 
| 3577 } // namespace compiler | 3584 } // namespace compiler | 
| 3578 } // namespace internal | 3585 } // namespace internal | 
| 3579 } // namespace v8 | 3586 } // namespace v8 | 
| OLD | NEW |