| 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/base/ieee754.h" | 9 #include "src/base/ieee754.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| 11 #include "src/compiler/diamond.h" | 11 #include "src/compiler/diamond.h" |
| 12 #include "src/compiler/graph.h" | 12 #include "src/compiler/graph.h" |
| 13 #include "src/compiler/js-graph.h" | 13 #include "src/compiler/js-graph.h" |
| 14 #include "src/compiler/node-matchers.h" | 14 #include "src/compiler/node-matchers.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 namespace compiler { | 18 namespace compiler { |
| 19 | 19 |
| 20 MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph) | 20 MachineOperatorReducer::MachineOperatorReducer(JSGraph* jsgraph, |
| 21 : jsgraph_(jsgraph) {} | 21 bool allow_signalling_nan) |
| 22 | 22 : jsgraph_(jsgraph), allow_signalling_nan_(allow_signalling_nan) {} |
| 23 | 23 |
| 24 MachineOperatorReducer::~MachineOperatorReducer() {} | 24 MachineOperatorReducer::~MachineOperatorReducer() {} |
| 25 | 25 |
| 26 | 26 |
| 27 Node* MachineOperatorReducer::Float32Constant(volatile float value) { | 27 Node* MachineOperatorReducer::Float32Constant(volatile float value) { |
| 28 return graph()->NewNode(common()->Float32Constant(value)); | 28 return graph()->NewNode(common()->Float32Constant(value)); |
| 29 } | 29 } |
| 30 | 30 |
| 31 | 31 |
| 32 Node* MachineOperatorReducer::Float64Constant(volatile double value) { | 32 Node* MachineOperatorReducer::Float64Constant(volatile double value) { |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true | 309 if (m.left().Is(0)) return ReplaceBool(true); // 0 <= x => true |
| 310 if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true | 310 if (m.right().Is(kMaxUInt32)) return ReplaceBool(true); // x <= M => true |
| 311 if (m.IsFoldable()) { // K <= K => K | 311 if (m.IsFoldable()) { // K <= K => K |
| 312 return ReplaceBool(m.left().Value() <= m.right().Value()); | 312 return ReplaceBool(m.left().Value() <= m.right().Value()); |
| 313 } | 313 } |
| 314 if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true | 314 if (m.LeftEqualsRight()) return ReplaceBool(true); // x <= x => true |
| 315 break; | 315 break; |
| 316 } | 316 } |
| 317 case IrOpcode::kFloat32Sub: { | 317 case IrOpcode::kFloat32Sub: { |
| 318 Float32BinopMatcher m(node); | 318 Float32BinopMatcher m(node); |
| 319 // TODO(ahaas): We could do x - 0.0 = x if we knew that x is not an sNaN. | 319 if (allow_signalling_nan_ && m.right().Is(0) && |
| 320 (copysign(1.0, m.right().Value()) > 0)) { |
| 321 return Replace(m.left().node()); // x - 0 => x |
| 322 } |
| 320 if (m.right().IsNaN()) { // x - NaN => NaN | 323 if (m.right().IsNaN()) { // x - NaN => NaN |
| 321 // Do some calculation to make a signalling NaN quiet. | 324 // Do some calculation to make a signalling NaN quiet. |
| 322 return ReplaceFloat32(m.right().Value() - m.right().Value()); | 325 return ReplaceFloat32(m.right().Value() - m.right().Value()); |
| 323 } | 326 } |
| 324 if (m.left().IsNaN()) { // NaN - x => NaN | 327 if (m.left().IsNaN()) { // NaN - x => NaN |
| 325 // Do some calculation to make a signalling NaN quiet. | 328 // Do some calculation to make a signalling NaN quiet. |
| 326 return ReplaceFloat32(m.left().Value() - m.left().Value()); | 329 return ReplaceFloat32(m.left().Value() - m.left().Value()); |
| 327 } | 330 } |
| 328 if (m.IsFoldable()) { // L - R => (L - R) | 331 if (m.IsFoldable()) { // L - R => (L - R) |
| 329 return ReplaceFloat32(m.left().Value() - m.right().Value()); | 332 return ReplaceFloat32(m.left().Value() - m.right().Value()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 353 // Do some calculation to make a signalling NaN quiet. | 356 // Do some calculation to make a signalling NaN quiet. |
| 354 return ReplaceFloat64(m.right().Value() - m.right().Value()); | 357 return ReplaceFloat64(m.right().Value() - m.right().Value()); |
| 355 } | 358 } |
| 356 if (m.IsFoldable()) { // K + K => K | 359 if (m.IsFoldable()) { // K + K => K |
| 357 return ReplaceFloat64(m.left().Value() + m.right().Value()); | 360 return ReplaceFloat64(m.left().Value() + m.right().Value()); |
| 358 } | 361 } |
| 359 break; | 362 break; |
| 360 } | 363 } |
| 361 case IrOpcode::kFloat64Sub: { | 364 case IrOpcode::kFloat64Sub: { |
| 362 Float64BinopMatcher m(node); | 365 Float64BinopMatcher m(node); |
| 363 // TODO(ahaas): We could do x - 0.0 = x if we knew that x is not an sNaN. | 366 if (allow_signalling_nan_ && m.right().Is(0) && |
| 367 (Double(m.right().Value()).Sign() > 0)) { |
| 368 return Replace(m.left().node()); // x - 0 => x |
| 369 } |
| 364 if (m.right().IsNaN()) { // x - NaN => NaN | 370 if (m.right().IsNaN()) { // x - NaN => NaN |
| 365 // Do some calculation to make a signalling NaN quiet. | 371 // Do some calculation to make a signalling NaN quiet. |
| 366 return ReplaceFloat64(m.right().Value() - m.right().Value()); | 372 return ReplaceFloat64(m.right().Value() - m.right().Value()); |
| 367 } | 373 } |
| 368 if (m.left().IsNaN()) { // NaN - x => NaN | 374 if (m.left().IsNaN()) { // NaN - x => NaN |
| 369 // Do some calculation to make a signalling NaN quiet. | 375 // Do some calculation to make a signalling NaN quiet. |
| 370 return ReplaceFloat64(m.left().Value() - m.left().Value()); | 376 return ReplaceFloat64(m.left().Value() - m.left().Value()); |
| 371 } | 377 } |
| 372 if (m.IsFoldable()) { // L - R => (L - R) | 378 if (m.IsFoldable()) { // L - R => (L - R) |
| 373 return ReplaceFloat64(m.left().Value() - m.right().Value()); | 379 return ReplaceFloat64(m.left().Value() - m.right().Value()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 386 } | 392 } |
| 387 // -0.0 - R => -R | 393 // -0.0 - R => -R |
| 388 node->RemoveInput(0); | 394 node->RemoveInput(0); |
| 389 NodeProperties::ChangeOp(node, machine()->Float64Neg()); | 395 NodeProperties::ChangeOp(node, machine()->Float64Neg()); |
| 390 return Changed(node); | 396 return Changed(node); |
| 391 } | 397 } |
| 392 break; | 398 break; |
| 393 } | 399 } |
| 394 case IrOpcode::kFloat64Mul: { | 400 case IrOpcode::kFloat64Mul: { |
| 395 Float64BinopMatcher m(node); | 401 Float64BinopMatcher m(node); |
| 396 // TODO(ahaas): We could do x * 1.0 = x if we knew that x is not an sNaN. | 402 if (allow_signalling_nan_ && m.right().Is(1)) |
| 403 return Replace(m.left().node()); // x * 1.0 => x |
| 397 if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x | 404 if (m.right().Is(-1)) { // x * -1.0 => -0.0 - x |
| 398 node->ReplaceInput(0, Float64Constant(-0.0)); | 405 node->ReplaceInput(0, Float64Constant(-0.0)); |
| 399 node->ReplaceInput(1, m.left().node()); | 406 node->ReplaceInput(1, m.left().node()); |
| 400 NodeProperties::ChangeOp(node, machine()->Float64Sub()); | 407 NodeProperties::ChangeOp(node, machine()->Float64Sub()); |
| 401 return Changed(node); | 408 return Changed(node); |
| 402 } | 409 } |
| 403 if (m.right().IsNaN()) { // x * NaN => NaN | 410 if (m.right().IsNaN()) { // x * NaN => NaN |
| 404 // Do some calculation to make a signalling NaN quiet. | 411 // Do some calculation to make a signalling NaN quiet. |
| 405 return ReplaceFloat64(m.right().Value() - m.right().Value()); | 412 return ReplaceFloat64(m.right().Value() - m.right().Value()); |
| 406 } | 413 } |
| 407 if (m.IsFoldable()) { // K * K => K | 414 if (m.IsFoldable()) { // K * K => K |
| 408 return ReplaceFloat64(m.left().Value() * m.right().Value()); | 415 return ReplaceFloat64(m.left().Value() * m.right().Value()); |
| 409 } | 416 } |
| 410 if (m.right().Is(2)) { // x * 2.0 => x + x | 417 if (m.right().Is(2)) { // x * 2.0 => x + x |
| 411 node->ReplaceInput(1, m.left().node()); | 418 node->ReplaceInput(1, m.left().node()); |
| 412 NodeProperties::ChangeOp(node, machine()->Float64Add()); | 419 NodeProperties::ChangeOp(node, machine()->Float64Add()); |
| 413 return Changed(node); | 420 return Changed(node); |
| 414 } | 421 } |
| 415 break; | 422 break; |
| 416 } | 423 } |
| 417 case IrOpcode::kFloat64Div: { | 424 case IrOpcode::kFloat64Div: { |
| 418 Float64BinopMatcher m(node); | 425 Float64BinopMatcher m(node); |
| 426 if (allow_signalling_nan_ && m.right().Is(1)) |
| 427 return Replace(m.left().node()); // x / 1.0 => x |
| 419 // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN. | 428 // TODO(ahaas): We could do x / 1.0 = x if we knew that x is not an sNaN. |
| 420 if (m.right().IsNaN()) { // x / NaN => NaN | 429 if (m.right().IsNaN()) { // x / NaN => NaN |
| 421 // Do some calculation to make a signalling NaN quiet. | 430 // Do some calculation to make a signalling NaN quiet. |
| 422 return ReplaceFloat64(m.right().Value() - m.right().Value()); | 431 return ReplaceFloat64(m.right().Value() - m.right().Value()); |
| 423 } | 432 } |
| 424 if (m.left().IsNaN()) { // NaN / x => NaN | 433 if (m.left().IsNaN()) { // NaN / x => NaN |
| 425 // Do some calculation to make a signalling NaN quiet. | 434 // Do some calculation to make a signalling NaN quiet. |
| 426 return ReplaceFloat64(m.left().Value() - m.left().Value()); | 435 return ReplaceFloat64(m.left().Value() - m.left().Value()); |
| 427 } | 436 } |
| 428 if (m.IsFoldable()) { // K / K => K | 437 if (m.IsFoldable()) { // K / K => K |
| (...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 MachineOperatorBuilder* MachineOperatorReducer::machine() const { | 1423 MachineOperatorBuilder* MachineOperatorReducer::machine() const { |
| 1415 return jsgraph()->machine(); | 1424 return jsgraph()->machine(); |
| 1416 } | 1425 } |
| 1417 | 1426 |
| 1418 | 1427 |
| 1419 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } | 1428 Graph* MachineOperatorReducer::graph() const { return jsgraph()->graph(); } |
| 1420 | 1429 |
| 1421 } // namespace compiler | 1430 } // namespace compiler |
| 1422 } // namespace internal | 1431 } // namespace internal |
| 1423 } // namespace v8 | 1432 } // namespace v8 |
| OLD | NEW |