Chromium Code Reviews

Side by Side Diff: src/hydrogen.cc

Issue 23503058: Hydrogen binop improvements (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 7634 matching lines...)
7645 return false; 7645 return false;
7646 } 7646 }
7647 return (sub->right() == sa); 7647 return (sub->right() == sa);
7648 } 7648 }
7649 7649
7650 7650
7651 // Checks if the left and the right are shift instructions with the oposite 7651 // Checks if the left and the right are shift instructions with the oposite
7652 // directions that can be replaced by one rotate right instruction or not. 7652 // directions that can be replaced by one rotate right instruction or not.
7653 // Returns the operand and the shift amount for the rotate instruction in the 7653 // Returns the operand and the shift amount for the rotate instruction in the
7654 // former case. 7654 // former case.
7655 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, 7655 bool HGraphBuilder::MatchRotateRight(HValue* left,
7656 HValue* right, 7656 HValue* right,
7657 HValue** operand, 7657 HValue** operand,
7658 HValue** shift_amount) { 7658 HValue** shift_amount) {
7659 HShl* shl; 7659 HShl* shl;
7660 HShr* shr; 7660 HShr* shr;
7661 if (left->IsShl() && right->IsShr()) { 7661 if (left->IsShl() && right->IsShr()) {
7662 shl = HShl::cast(left); 7662 shl = HShl::cast(left);
7663 shr = HShr::cast(right); 7663 shr = HShr::cast(right);
7664 } else if (left->IsShr() && right->IsShl()) { 7664 } else if (left->IsShr() && right->IsShl()) {
7665 shl = HShl::cast(right); 7665 shl = HShl::cast(right);
7666 shr = HShr::cast(left); 7666 shr = HShr::cast(left);
7667 } else { 7667 } else {
7668 return false; 7668 return false;
(...skipping 15 matching lines...)
7684 HConstant* right_const = HConstant::cast(right); 7684 HConstant* right_const = HConstant::cast(right);
7685 if (right_const->HasInteger32Value() && 7685 if (right_const->HasInteger32Value() &&
7686 (right_const->Integer32Value() & 0x1f) != 0) { 7686 (right_const->Integer32Value() & 0x1f) != 0) {
7687 return false; 7687 return false;
7688 } 7688 }
7689 } 7689 }
7690 return true; 7690 return true;
7691 } 7691 }
7692 7692
7693 7693
7694 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
7695 Handle<Type> expected) {
7696 if (expected->Is(Type::Smi())) {
7697 return Add<HForceRepresentation>(number, Representation::Smi());
7698 } else if (expected->Is(Type::Signed32())) {
Sven Panne 2013/09/16 13:38:09 Just drop the "else", it's cleaner... :-)
7699 return Add<HForceRepresentation>(number, Representation::Integer32());
7700 }
7701
7702 return number;
7703 }
7704
7705
7694 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { 7706 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) {
7695 if (value->IsConstant()) { 7707 if (value->IsConstant()) {
7696 HConstant* constant = HConstant::cast(value); 7708 HConstant* constant = HConstant::cast(value);
7697 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); 7709 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
7698 if (number.has_value) { 7710 if (number.has_value) {
7699 *expected = handle(Type::Number(), isolate()); 7711 *expected = handle(Type::Number(), isolate());
7700 return AddInstruction(number.value); 7712 return AddInstruction(number.value);
7701 } 7713 }
7702 } 7714 }
7703 7715
7716 NoObservableSideEffectsScope no_effects(this);
7717 Handle<Type> expected_type = *expected;
7718
7719 // Separate the number type from the rest.
7720 Handle<Type> expected_obj = handle(Type::Intersect(
7721 expected_type, handle(Type::NonNumber(), isolate())), isolate());
7722 Handle<Type> expected_number = handle(Type::Intersect(
7723 expected_type, handle(Type::Number(), isolate())), isolate());
7724
7725 // We expect to get a number.
7726 // (We need to check first, since Type::None->Is(Type::Any()) == true.
7727 if (expected_obj->Is(Type::None())) {
7728 ASSERT(!expected_number->Is(Type::None()));
7729 return value;
7730 }
7731
7732 if (expected_obj->Is(Type::Undefined())) {
7733 // This is already done by HChange.
7734 *expected = handle(Type::Union(
7735 expected_number, handle(Type::Double(), isolate())), isolate());
7736 return value;
7737 }
7738
7739 if (expected_obj->Is(Type::Null())) {
7740 *expected = handle(Type::Union(
7741 expected_number, handle(Type::Smi(), isolate())), isolate());
7742 IfBuilder if_null(this);
7743 if_null.If<HCompareObjectEqAndBranch>(value,
7744 graph()->GetConstantNull());
7745 if_null.Then();
7746 Push(graph()->GetConstant0());
7747 if_null.Else();
7748 Push(value);
7749 if_null.End();
7750 return Pop();
7751 }
7752
7753 if (expected_obj->Is(Type::Boolean())) {
7754 *expected = handle(Type::Union(
7755 expected_number, handle(Type::Smi(), isolate())), isolate());
7756 IfBuilder if_true(this);
7757 if_true.If<HCompareObjectEqAndBranch>(value,
7758 graph()->GetConstantTrue());
7759 if_true.Then();
7760 Push(graph()->GetConstant1());
7761 if_true.Else();
7762 IfBuilder if_false(this);
7763 if_false.If<HCompareObjectEqAndBranch>(value,
7764 graph()->GetConstantFalse());
7765 if_false.Then();
7766 Push(graph()->GetConstant0());
7767 if_false.Else();
7768 Push(value);
7769 if_false.End();
7770 if_true.End();
7771 return Pop();
7772 }
7773
7704 return value; 7774 return value;
7705 } 7775 }
7706 7776
7707 7777
7708 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 7778 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
7709 BinaryOperation* expr, 7779 BinaryOperation* expr,
7710 HValue* left, 7780 HValue* left,
7711 HValue* right) { 7781 HValue* right) {
7712 HValue* context = environment()->context(); 7782 HValue* context = environment()->context();
7713 Handle<Type> left_type = expr->left()->bounds().lower; 7783 Handle<Type> left_type = expr->left()->bounds().lower;
7714 Handle<Type> right_type = expr->right()->bounds().lower; 7784 Handle<Type> right_type = expr->right()->bounds().lower;
7715 Handle<Type> result_type = expr->bounds().lower; 7785 Handle<Type> result_type = expr->bounds().lower;
7716 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 7786 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
7787
7788 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right,
7789 left_type, right_type, result_type, fixed_right_arg, context);
7790 }
7791
7792
7793 HInstruction* HGraphBuilder::BuildBinaryOperation(
7794 Token::Value op,
7795 HValue* left,
7796 HValue* right,
7797 Handle<Type> left_type,
7798 Handle<Type> right_type,
7799 Handle<Type> result_type,
7800 Maybe<int> fixed_right_arg,
7801 HValue* context) {
7802
7717 Representation left_rep = Representation::FromType(left_type); 7803 Representation left_rep = Representation::FromType(left_type);
7718 Representation right_rep = Representation::FromType(right_type); 7804 Representation right_rep = Representation::FromType(right_type);
7805
7806 if (left_type->Is(Type::None()) || right_type->Is(Type::None())) {
7807 if (left_type->Is(Type::None())) {
7808 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
7809 Deoptimizer::SOFT);
7810 // TODO(rossberg): we should be able to get rid of non-continuous
7811 // defaults.
7812 left_type = handle(Type::Any(), isolate());
7813 } else {
7814 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
7815 Deoptimizer::SOFT);
7816 right_type = handle(Type::Any(), isolate());
7817 }
7818 } else {
7819 bool maybe_string_add = op == Token::ADD &&
7820 (left_type->Maybe(Type::String()) ||
7821 right_type->Maybe(Type::String()));
7822
7823 if (!maybe_string_add) {
7824 left = TruncateToNumber(left, &left_type);
7825 right = TruncateToNumber(right, &right_type);
7826 }
7827
7828 left_rep = Representation::FromType(left_type);
7829 right_rep = Representation::FromType(right_type);
7830 }
7831
7719 Representation result_rep = Representation::FromType(result_type); 7832 Representation result_rep = Representation::FromType(result_type);
7720 7833
7721 if (expr->op() != Token::ADD || 7834 bool is_tagged = left_rep.IsTagged() || right_rep.IsTagged();
7722 (left->type().IsNonString() && right->type().IsNonString())) { 7835 bool is_string_add = op == Token::ADD && is_tagged &&
7723 // For addition we can only truncate the arguments to number if we can 7836 (left_type->Is(Type::String()) ||
7724 // prove that we will not end up in string concatenation mode. 7837 right_type->Is(Type::String()));
7725 left = TruncateToNumber(left, &left_type);
7726 right = TruncateToNumber(right, &right_type);
7727 }
7728 7838
7729 if (left_type->Is(Type::None())) {
7730 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
7731 Deoptimizer::SOFT);
7732 // TODO(rossberg): we should be able to get rid of non-continuous defaults.
7733 left_type = handle(Type::Any(), isolate());
7734 }
7735 if (right_type->Is(Type::None())) {
7736 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
7737 Deoptimizer::SOFT);
7738 right_type = handle(Type::Any(), isolate());
7739 }
7740 HInstruction* instr = NULL; 7839 HInstruction* instr = NULL;
7741 switch (expr->op()) { 7840 switch (op) {
7742 case Token::ADD: 7841 case Token::ADD:
7743 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { 7842 if (is_string_add) {
7744 BuildCheckHeapObject(left); 7843 StringAddFlags flags = STRING_ADD_CHECK_BOTH;
7745 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 7844 if (left_type->Is(Type::String())) {
7746 BuildCheckHeapObject(right); 7845 BuildCheckHeapObject(left);
7747 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); 7846 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
7748 instr = HStringAdd::New(zone(), context, left, right); 7847 flags = STRING_ADD_CHECK_RIGHT;
7848 }
7849 if (right_type->Is(Type::String())) {
7850 BuildCheckHeapObject(right);
7851 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
7852 flags = (flags == STRING_ADD_CHECK_BOTH)
7853 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE;
7854 }
7855 instr = HStringAdd::New(zone(), context, left, right, flags);
7749 } else { 7856 } else {
7750 instr = HAdd::New(zone(), context, left, right); 7857 instr = HAdd::New(zone(), context, left, right);
7751 } 7858 }
7752 break; 7859 break;
7753 case Token::SUB: 7860 case Token::SUB:
7754 instr = HSub::New(zone(), context, left, right); 7861 instr = HSub::New(zone(), context, left, right);
7755 break; 7862 break;
7756 case Token::MUL: 7863 case Token::MUL:
7757 instr = HMul::New(zone(), context, left, right); 7864 instr = HMul::New(zone(), context, left, right);
7758 break; 7865 break;
7759 case Token::MOD: 7866 case Token::MOD:
7760 instr = HMod::New(zone(), context, left, right, fixed_right_arg); 7867 instr = HMod::New(zone(), context, left, right, fixed_right_arg);
7761 break; 7868 break;
7762 case Token::DIV: 7869 case Token::DIV:
7763 instr = HDiv::New(zone(), context, left, right); 7870 instr = HDiv::New(zone(), context, left, right);
7764 break; 7871 break;
7765 case Token::BIT_XOR: 7872 case Token::BIT_XOR:
7766 case Token::BIT_AND: 7873 case Token::BIT_AND:
7767 instr = NewUncasted<HBitwise>(expr->op(), left, right); 7874 instr = NewUncasted<HBitwise>(op, left, right);
7768 break; 7875 break;
7769 case Token::BIT_OR: { 7876 case Token::BIT_OR: {
7770 HValue* operand, *shift_amount; 7877 HValue* operand, *shift_amount;
7771 if (left_type->Is(Type::Signed32()) && 7878 if (left_type->Is(Type::Signed32()) &&
7772 right_type->Is(Type::Signed32()) && 7879 right_type->Is(Type::Signed32()) &&
7773 MatchRotateRight(left, right, &operand, &shift_amount)) { 7880 MatchRotateRight(left, right, &operand, &shift_amount)) {
7774 instr = new(zone()) HRor(context, operand, shift_amount); 7881 instr = new(zone()) HRor(context, operand, shift_amount);
7775 } else { 7882 } else {
7776 instr = NewUncasted<HBitwise>(expr->op(), left, right); 7883 instr = NewUncasted<HBitwise>(op, left, right);
7777 } 7884 }
7778 break; 7885 break;
7779 } 7886 }
7780 case Token::SAR: 7887 case Token::SAR:
7781 instr = HSar::New(zone(), context, left, right); 7888 instr = HSar::New(zone(), context, left, right);
7782 break; 7889 break;
7783 case Token::SHR: 7890 case Token::SHR:
7784 instr = HShr::New(zone(), context, left, right); 7891 instr = HShr::New(zone(), context, left, right);
7785 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && 7892 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
7786 CanBeZero(right)) { 7893 CanBeZero(right)) {
(...skipping 1917 matching lines...)
9704 if (ShouldProduceTraceOutput()) { 9811 if (ShouldProduceTraceOutput()) {
9705 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9812 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9706 } 9813 }
9707 9814
9708 #ifdef DEBUG 9815 #ifdef DEBUG
9709 graph_->Verify(false); // No full verify. 9816 graph_->Verify(false); // No full verify.
9710 #endif 9817 #endif
9711 } 9818 }
9712 9819
9713 } } // namespace v8::internal 9820 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine