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

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 620553008: Lower NumberMultiply, NumberDivide, and NumberModulus to Int32Mul, Int32[U]Div, and Int32[U]Mod whe… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add mjsunit and cctests. Created 6 years, 2 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 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 "src/base/bits.h" 7 #include "src/base/bits.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/compiler/common-operator.h" 9 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph-inl.h" 10 #include "src/compiler/graph-inl.h"
11 #include "src/compiler/node-matchers.h"
11 #include "src/compiler/node-properties-inl.h" 12 #include "src/compiler/node-properties-inl.h"
12 #include "src/compiler/representation-change.h" 13 #include "src/compiler/representation-change.h"
13 #include "src/compiler/simplified-lowering.h" 14 #include "src/compiler/simplified-lowering.h"
14 #include "src/compiler/simplified-operator.h" 15 #include "src/compiler/simplified-operator.h"
15 #include "src/objects.h" 16 #include "src/objects.h"
16 17
17 namespace v8 { 18 namespace v8 {
18 namespace internal { 19 namespace internal {
19 namespace compiler { 20 namespace compiler {
20 21
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 } 345 }
345 346
346 const Operator* Uint32Op(Node* node) { 347 const Operator* Uint32Op(Node* node) {
347 return changer_->Uint32OperatorFor(node->opcode()); 348 return changer_->Uint32OperatorFor(node->opcode());
348 } 349 }
349 350
350 const Operator* Float64Op(Node* node) { 351 const Operator* Float64Op(Node* node) {
351 return changer_->Float64OperatorFor(node->opcode()); 352 return changer_->Float64OperatorFor(node->opcode());
352 } 353 }
353 354
355 bool CanBeInt32Binop(Node* node, MachineTypeUnion use) {
Michael Starzinger 2014/10/08 09:01:28 Please address my previous comment about the "CanB
titzer 2014/10/08 09:12:29 Done.
356 return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use);
357 }
358
359 bool CanBeUint32Binop(Node* node, MachineTypeUnion use) {
360 return BothInputsAre(node, Type::Unsigned32()) && !CanObserveNonUint32(use);
361 }
362
363 bool CanObserveNonInt32(MachineTypeUnion use) {
364 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0;
365 }
366
367 bool CanObserveMinusZero(MachineTypeUnion use) {
368 // TODO(turbofan): technically Uint32 cannot observe minus zero either.
369 return (use & (kTypeUint32 | kTypeNumber | kTypeAny)) != 0;
370 }
371
372 bool CanObserveNonUint32(MachineTypeUnion use) {
373 return (use & (kTypeInt32 | kTypeNumber | kTypeAny)) != 0;
374 }
375
354 // Dispatching routine for visiting the node {node} with the usage {use}. 376 // Dispatching routine for visiting the node {node} with the usage {use}.
355 // Depending on the operator, propagate new usage info to the inputs. 377 // Depending on the operator, propagate new usage info to the inputs.
356 void VisitNode(Node* node, MachineTypeUnion use, 378 void VisitNode(Node* node, MachineTypeUnion use,
357 SimplifiedLowering* lowering) { 379 SimplifiedLowering* lowering) {
358 switch (node->opcode()) { 380 switch (node->opcode()) {
359 //------------------------------------------------------------------ 381 //------------------------------------------------------------------
360 // Common operators. 382 // Common operators.
361 //------------------------------------------------------------------ 383 //------------------------------------------------------------------
362 case IrOpcode::kStart: 384 case IrOpcode::kStart:
363 case IrOpcode::kDead: 385 case IrOpcode::kDead:
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 // => Float64Cmp 490 // => Float64Cmp
469 VisitFloat64Cmp(node); 491 VisitFloat64Cmp(node);
470 if (lower()) node->set_op(Float64Op(node)); 492 if (lower()) node->set_op(Float64Op(node));
471 } 493 }
472 break; 494 break;
473 } 495 }
474 case IrOpcode::kNumberAdd: 496 case IrOpcode::kNumberAdd:
475 case IrOpcode::kNumberSubtract: { 497 case IrOpcode::kNumberSubtract: {
476 // Add and subtract reduce to Int32Add/Sub if the inputs 498 // Add and subtract reduce to Int32Add/Sub if the inputs
477 // are already integers and all uses are truncating. 499 // are already integers and all uses are truncating.
478 if (BothInputsAre(node, Type::Signed32()) && 500 if (CanBeInt32Binop(node, use)) {
479 (use & (kTypeUint32 | kTypeNumber | kTypeAny)) == 0) {
480 // => signed Int32Add/Sub 501 // => signed Int32Add/Sub
481 VisitInt32Binop(node); 502 VisitInt32Binop(node);
482 if (lower()) node->set_op(Int32Op(node)); 503 if (lower()) node->set_op(Int32Op(node));
483 } else if (BothInputsAre(node, Type::Unsigned32()) && 504 } else if (CanBeUint32Binop(node, use)) {
484 (use & (kTypeInt32 | kTypeNumber | kTypeAny)) == 0) {
485 // => unsigned Int32Add/Sub 505 // => unsigned Int32Add/Sub
486 VisitUint32Binop(node); 506 VisitUint32Binop(node);
487 if (lower()) node->set_op(Uint32Op(node)); 507 if (lower()) node->set_op(Uint32Op(node));
488 } else { 508 } else {
489 // => Float64Add/Sub 509 // => Float64Add/Sub
490 VisitFloat64Binop(node); 510 VisitFloat64Binop(node);
491 if (lower()) node->set_op(Float64Op(node)); 511 if (lower()) node->set_op(Float64Op(node));
492 } 512 }
493 break; 513 break;
494 } 514 }
495 case IrOpcode::kNumberMultiply: 515 case IrOpcode::kNumberMultiply: {
496 case IrOpcode::kNumberDivide: 516 NumberMatcher right(node->InputAt(1));
497 case IrOpcode::kNumberModulus: { 517 if (right.IsInRange(-1048576, 1048576)) { // must fit double mantissa.
498 // Float64Mul/Div/Mod 518 if (CanBeInt32Binop(node, use)) {
519 // => signed Int32Mul
520 VisitInt32Binop(node);
521 if (lower()) node->set_op(Int32Op(node));
522 break;
523 }
524 }
525 // => Float64Mul
499 VisitFloat64Binop(node); 526 VisitFloat64Binop(node);
500 if (lower()) node->set_op(Float64Op(node)); 527 if (lower()) node->set_op(Float64Op(node));
501 break; 528 break;
529 }
530 case IrOpcode::kNumberDivide: {
531 NumberMatcher right(node->InputAt(1));
532 if (right.HasValue() && !right.Is(0) && !right.Is(-1)) {
533 if (CanBeInt32Binop(node, use)) {
534 // => signed Int32Div
535 VisitInt32Binop(node);
536 if (lower()) node->set_op(Int32Op(node));
537 break;
538 } else if (CanBeUint32Binop(node, use)) {
539 // => unsigned Uint32Div
540 VisitUint32Binop(node);
541 if (lower()) node->set_op(Uint32Op(node));
542 break;
543 }
544 }
545 // => Float64Div
546 VisitFloat64Binop(node);
547 if (lower()) node->set_op(Float64Op(node));
548 break;
549 }
550 case IrOpcode::kNumberModulus: {
551 NumberMatcher right(node->InputAt(1));
552 if (right.HasValue() && !right.Is(0) && !right.Is(-1)) {
553 if (BothInputsAre(node, Type::Signed32()) &&
554 !CanObserveMinusZero(use)) {
555 // => signed Int32Mod
556 VisitInt32Binop(node);
557 if (lower()) node->set_op(Int32Op(node));
558 break;
559 } else if (BothInputsAre(node, Type::Unsigned32())) {
560 // => unsigned Uint32Mod
561 VisitUint32Binop(node);
562 if (lower()) node->set_op(Uint32Op(node));
563 break;
564 }
565 }
566 // => Float64Mod
567 VisitFloat64Binop(node);
568 if (lower()) node->set_op(Float64Op(node));
569 break;
502 } 570 }
503 case IrOpcode::kNumberToInt32: { 571 case IrOpcode::kNumberToInt32: {
504 MachineTypeUnion use_rep = use & kRepMask; 572 MachineTypeUnion use_rep = use & kRepMask;
505 Node* input = node->InputAt(0); 573 Node* input = node->InputAt(0);
506 MachineTypeUnion in = GetInfo(input)->output; 574 MachineTypeUnion in = GetInfo(input)->output;
507 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32()) || 575 if (NodeProperties::GetBounds(input).upper->Is(Type::Signed32())) {
508 (in & kTypeMask) == kTypeInt32 || (in & kRepMask) == kRepWord32) { 576 // If the input has type int32, pass through representation.
509 // If the input has type int32, or is already a word32, just change
510 // representation if necessary.
511 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); 577 VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep);
512 if (lower()) DeferReplacement(node, node->InputAt(0)); 578 if (lower()) DeferReplacement(node, node->InputAt(0));
579 } else if ((in & kTypeMask) == kTypeUint32 ||
580 (in & kTypeMask) == kTypeInt32 ||
581 (in & kRepMask) == kRepWord32) {
582 // Just change representation if necessary.
583 VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32);
584 if (lower()) DeferReplacement(node, node->InputAt(0));
513 } else { 585 } else {
514 // Require the input in float64 format and perform truncation. 586 // Require the input in float64 format and perform truncation.
515 // TODO(turbofan): avoid a truncation with a smi check. 587 // TODO(turbofan): avoid a truncation with a smi check.
516 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); 588 VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32);
517 if (lower()) 589 if (lower())
518 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); 590 node->set_op(lowering->machine()->TruncateFloat64ToInt32());
519 } 591 }
520 break; 592 break;
521 } 593 }
522 case IrOpcode::kNumberToUint32: { 594 case IrOpcode::kNumberToUint32: {
523 MachineTypeUnion use_rep = use & kRepMask; 595 MachineTypeUnion use_rep = use & kRepMask;
524 Node* input = node->InputAt(0); 596 Node* input = node->InputAt(0);
525 MachineTypeUnion in = GetInfo(input)->output; 597 MachineTypeUnion in = GetInfo(input)->output;
526 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32()) || 598 if (NodeProperties::GetBounds(input).upper->Is(Type::Unsigned32())) {
527 (in & kTypeMask) == kTypeUint32) { 599 // If the input has type uint32, pass through representation.
528 // If the input has type uint32, just change representation.
529 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); 600 VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep);
530 if (lower()) DeferReplacement(node, node->InputAt(0)); 601 if (lower()) DeferReplacement(node, node->InputAt(0));
602 } else if ((in & kTypeMask) == kTypeUint32 ||
603 (in & kTypeMask) == kTypeInt32 ||
604 (in & kRepMask) == kRepWord32) {
605 // Just change representation if necessary.
606 VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32);
607 if (lower()) DeferReplacement(node, node->InputAt(0));
531 } else { 608 } else {
532 // Require the input in float64 format and perform truncation. 609 // Require the input in float64 format and perform truncation.
533 // TODO(turbofan): avoid a truncation with a smi check. 610 // TODO(turbofan): avoid a truncation with a smi check.
534 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); 611 VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32);
535 if (lower()) 612 if (lower())
536 node->set_op(lowering->machine()->TruncateFloat64ToInt32()); 613 node->set_op(lowering->machine()->TruncateFloat64ToInt32());
537 } 614 }
538 break; 615 break;
539 } 616 }
540 case IrOpcode::kReferenceEqual: { 617 case IrOpcode::kReferenceEqual: {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 return VisitFloat64Cmp(node); 805 return VisitFloat64Cmp(node);
729 case IrOpcode::kLoadStackPointer: 806 case IrOpcode::kLoadStackPointer:
730 return VisitLeaf(node, kMachPtr); 807 return VisitLeaf(node, kMachPtr);
731 default: 808 default:
732 VisitInputs(node); 809 VisitInputs(node);
733 break; 810 break;
734 } 811 }
735 } 812 }
736 813
737 void DeferReplacement(Node* node, Node* replacement) { 814 void DeferReplacement(Node* node, Node* replacement) {
815 if (FLAG_trace_representation) {
816 TRACE(("defer replacement #%d:%s with #%d:%s\n", node->id(),
817 node->op()->mnemonic(), replacement->id(),
818 replacement->op()->mnemonic()));
819 }
738 if (replacement->id() < count_) { 820 if (replacement->id() < count_) {
739 // Replace with a previously existing node eagerly. 821 // Replace with a previously existing node eagerly.
740 node->ReplaceUses(replacement); 822 node->ReplaceUses(replacement);
741 } else { 823 } else {
742 // Otherwise, we are replacing a node with a representation change. 824 // Otherwise, we are replacing a node with a representation change.
743 // Such a substitution must be done after all lowering is done, because 825 // Such a substitution must be done after all lowering is done, because
744 // new nodes do not have {NodeInfo} entries, and that would confuse 826 // new nodes do not have {NodeInfo} entries, and that would confuse
745 // the representation change insertion for uses of it. 827 // the representation change insertion for uses of it.
746 replacements_.push_back(node); 828 replacements_.push_back(node);
747 replacements_.push_back(replacement); 829 replacements_.push_back(replacement);
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { 1046 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
965 node->set_op(machine()->IntLessThanOrEqual()); 1047 node->set_op(machine()->IntLessThanOrEqual());
966 node->ReplaceInput(0, StringComparison(node, true)); 1048 node->ReplaceInput(0, StringComparison(node, true));
967 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); 1049 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
968 } 1050 }
969 1051
970 1052
971 } // namespace compiler 1053 } // namespace compiler
972 } // namespace internal 1054 } // namespace internal
973 } // namespace v8 1055 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/compiler/test-simplified-lowering.cc » ('j') | test/cctest/compiler/test-simplified-lowering.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698