Chromium Code Reviews| 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/machine-operator-reducer.h" | 5 #include "src/compiler/machine-operator-reducer.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/compiler/diamond.h" | 10 #include "src/compiler/diamond.h" |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 NodeProperties::ChangeOp(node, machine()->Float64Sub()); | 343 NodeProperties::ChangeOp(node, machine()->Float64Sub()); |
| 344 return Changed(node); | 344 return Changed(node); |
| 345 } | 345 } |
| 346 if (m.right().Is(1)) return Replace(m.left().node()); // x * 1.0 => x | 346 if (m.right().Is(1)) return Replace(m.left().node()); // x * 1.0 => x |
| 347 if (m.right().IsNaN()) { // x * NaN => NaN | 347 if (m.right().IsNaN()) { // x * NaN => NaN |
| 348 return Replace(m.right().node()); | 348 return Replace(m.right().node()); |
| 349 } | 349 } |
| 350 if (m.IsFoldable()) { // K * K => K | 350 if (m.IsFoldable()) { // K * K => K |
| 351 return ReplaceFloat64(m.left().Value() * m.right().Value()); | 351 return ReplaceFloat64(m.left().Value() * m.right().Value()); |
| 352 } | 352 } |
| 353 break; | 353 return ReduceFloat52Mul(node); |
| 354 } | 354 } |
| 355 case IrOpcode::kFloat64Div: { | 355 case IrOpcode::kFloat64Div: { |
| 356 Float64BinopMatcher m(node); | 356 Float64BinopMatcher m(node); |
| 357 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1.0 => x | 357 if (m.right().Is(1)) return Replace(m.left().node()); // x / 1.0 => x |
| 358 if (m.right().IsNaN()) { // x / NaN => NaN | 358 if (m.right().IsNaN()) { // x / NaN => NaN |
| 359 return Replace(m.right().node()); | 359 return Replace(m.right().node()); |
| 360 } | 360 } |
| 361 if (m.left().IsNaN()) { // NaN / x => NaN | 361 if (m.left().IsNaN()) { // NaN / x => NaN |
| 362 return Replace(m.left().node()); | 362 return Replace(m.left().node()); |
| 363 } | 363 } |
| 364 if (m.IsFoldable()) { // K / K => K | 364 if (m.IsFoldable()) { // K / K => K |
| 365 return ReplaceFloat64(m.left().Value() / m.right().Value()); | 365 return ReplaceFloat64(m.left().Value() / m.right().Value()); |
| 366 } | 366 } |
| 367 break; | 367 return ReduceFloat52Div(node); |
| 368 } | 368 } |
| 369 case IrOpcode::kFloat64Mod: { | 369 case IrOpcode::kFloat64Mod: { |
| 370 Float64BinopMatcher m(node); | 370 Float64BinopMatcher m(node); |
| 371 if (m.right().Is(0)) { // x % 0 => NaN | 371 if (m.right().Is(0)) { // x % 0 => NaN |
| 372 return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN()); | 372 return ReplaceFloat64(std::numeric_limits<double>::quiet_NaN()); |
| 373 } | 373 } |
| 374 if (m.right().IsNaN()) { // x % NaN => NaN | 374 if (m.right().IsNaN()) { // x % NaN => NaN |
| 375 return Replace(m.right().node()); | 375 return Replace(m.right().node()); |
| 376 } | 376 } |
| 377 if (m.left().IsNaN()) { // NaN % x => NaN | 377 if (m.left().IsNaN()) { // NaN % x => NaN |
| (...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1073 node->ReplaceInput( | 1073 node->ReplaceInput( |
| 1074 1, m.right().HasValue() | 1074 1, m.right().HasValue() |
| 1075 ? Float32Constant(static_cast<float>(m.right().Value())) | 1075 ? Float32Constant(static_cast<float>(m.right().Value())) |
| 1076 : m.right().InputAt(0)); | 1076 : m.right().InputAt(0)); |
| 1077 return Changed(node); | 1077 return Changed(node); |
| 1078 } | 1078 } |
| 1079 return NoChange(); | 1079 return NoChange(); |
| 1080 } | 1080 } |
| 1081 | 1081 |
| 1082 | 1082 |
| 1083 Reduction MachineOperatorReducer::ReduceFloat52Mul(Node* node) { | |
| 1084 if (!machine()->Is64()) return NoChange(); | |
| 1085 | |
| 1086 Float64BinopMatcher m(node); | |
| 1087 if (!m.left().IsChangeInt32ToFloat64() || | |
| 1088 !m.right().IsChangeInt32ToFloat64()) { | |
| 1089 return NoChange(); | |
| 1090 } | |
| 1091 | |
| 1092 Type* type = NodeProperties::GetType(node); | |
|
Benedikt Meurer
2015/11/25 20:09:10
The MachineOperatorReducer must not look at the ty
| |
| 1093 Type::RangeType* range = type->GetRange(); | |
| 1094 | |
| 1095 // JavaScript has 52 bit precision in multiplication | |
| 1096 if (range == nullptr || range->Min() < 0.0 || | |
| 1097 range->Max() > 0xFFFFFFFFFFFFFULL) { | |
| 1098 return NoChange(); | |
| 1099 } | |
| 1100 | |
| 1101 Node* mul = graph()->NewNode(machine()->Int64Mul(), m.left().InputAt(0), | |
| 1102 m.right().InputAt(0)); | |
| 1103 | |
| 1104 Type* range_type = Type::Range(range->Min(), range->Max(), graph()->zone()); | |
| 1105 | |
| 1106 // TODO(indutny): Is Type::Number() a proper thing here? It looks like | |
| 1107 // every other place is using Type:Internal() for int64 values. | |
| 1108 // Should we off-load range propagation to Typer? | |
| 1109 NodeProperties::SetType( | |
| 1110 mul, Type::Intersect(range_type, Type::Number(), graph()->zone())); | |
| 1111 | |
| 1112 Node* out = graph()->NewNode(machine()->RoundInt64ToFloat64(), mul); | |
| 1113 return Replace(out); | |
| 1114 } | |
| 1115 | |
| 1116 | |
| 1117 Reduction MachineOperatorReducer::ReduceFloat52Div(Node* node) { | |
| 1118 if (!machine()->Is64()) return NoChange(); | |
| 1119 | |
| 1120 Float64BinopMatcher m(node); | |
| 1121 if (!m.left().IsRoundInt64ToFloat64()) return NoChange(); | |
| 1122 | |
| 1123 // Right value should be positive... | |
| 1124 if (!m.right().HasValue() || m.right().Value() <= 0) return NoChange(); | |
| 1125 | |
| 1126 // ...integer... | |
| 1127 int64_t value = static_cast<int64_t>(m.right().Value()); | |
| 1128 if (value != static_cast<int64_t>(m.right().Value())) return NoChange(); | |
| 1129 | |
| 1130 // ...and should be a power of two. | |
| 1131 if (!base::bits::IsPowerOfTwo64(value)) return NoChange(); | |
| 1132 | |
| 1133 Node* left = m.left().InputAt(0); | |
| 1134 Type::RangeType* range = NodeProperties::GetType(left)->GetRange(); | |
| 1135 | |
| 1136 // The RoundInt64ToFloat64 input should fit into 52bit integer | |
| 1137 if (range == nullptr || range->Min() < 0 || | |
| 1138 range->Max() > 0xFFFFFFFFFFFFFULL) { | |
| 1139 return NoChange(); | |
| 1140 } | |
| 1141 | |
| 1142 // The result should fit into 32bit word | |
| 1143 int64_t min = static_cast<int64_t>(range->Min()) / value; | |
| 1144 int64_t max = static_cast<int64_t>(range->Max()) / value; | |
| 1145 if (min < 0 || max > 0xFFFFFFFLL) { | |
| 1146 return NoChange(); | |
| 1147 } | |
| 1148 | |
| 1149 int64_t shift = WhichPowerOf2_64(static_cast<int64_t>(m.right().Value())); | |
| 1150 | |
| 1151 // Replace division with 64bit right shift | |
| 1152 Node* shr = | |
| 1153 graph()->NewNode(machine()->Word64Shr(), left, | |
| 1154 graph()->NewNode(common()->Int64Constant(shift))); | |
| 1155 | |
| 1156 Type* range_type = Type::Range(min, max, graph()->zone()); | |
| 1157 NodeProperties::SetType( | |
| 1158 shr, Type::Intersect(range_type, Type::Number(), graph()->zone())); | |
| 1159 | |
| 1160 Node* out = graph()->NewNode(machine()->RoundInt64ToFloat64(), shr); | |
| 1161 return Replace(out); | |
| 1162 } | |
| 1163 | |
| 1164 | |
| 1083 CommonOperatorBuilder* MachineOperatorReducer::common() const { | 1165 CommonOperatorBuilder* MachineOperatorReducer::common() const { |
| 1084 return jsgraph()->common(); | 1166 return jsgraph()->common(); |
| 1085 } | 1167 } |
| 1086 | 1168 |
| 1087 | 1169 |
| 1088 MachineOperatorBuilder* MachineOperatorReducer::machine() const { | 1170 MachineOperatorBuilder* MachineOperatorReducer::machine() const { |
| 1089 return jsgraph()->machine(); | 1171 return jsgraph()->machine(); |
| 1090 } | 1172 } |
| 1091 | 1173 |
| 1092 | 1174 |
| 1093 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } | 1175 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
| 1094 | 1176 |
| 1095 } // namespace compiler | 1177 } // namespace compiler |
| 1096 } // namespace internal | 1178 } // namespace internal |
| 1097 } // namespace v8 | 1179 } // namespace v8 |
| OLD | NEW |