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

Side by Side Diff: src/hydrogen.cc

Issue 10778029: Allow uint32 value on optimized frames if they are consumed by safe operations. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: arm and x64 ports Created 8 years, 4 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 676 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 } 687 }
688 688
689 689
690 HGraph::HGraph(CompilationInfo* info) 690 HGraph::HGraph(CompilationInfo* info)
691 : isolate_(info->isolate()), 691 : isolate_(info->isolate()),
692 next_block_id_(0), 692 next_block_id_(0),
693 entry_block_(NULL), 693 entry_block_(NULL),
694 blocks_(8, info->zone()), 694 blocks_(8, info->zone()),
695 values_(16, info->zone()), 695 values_(16, info->zone()),
696 phi_list_(NULL), 696 phi_list_(NULL),
697 uint32_instructions_(NULL),
697 info_(info), 698 info_(info),
698 zone_(info->zone()), 699 zone_(info->zone()),
699 is_recursive_(false) { 700 is_recursive_(false) {
700 start_environment_ = 701 start_environment_ =
701 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 702 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
702 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 703 start_environment_->set_ast_id(BailoutId::FunctionEntry());
703 entry_block_ = CreateBasicBlock(); 704 entry_block_ = CreateBasicBlock();
704 entry_block_->SetInitialEnvironment(start_environment_); 705 entry_block_->SetInitialEnvironment(start_environment_);
705 } 706 }
706 707
(...skipping 2009 matching lines...) Expand 10 before | Expand all | Expand 10 after
2716 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) { 2717 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
2717 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); 2718 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
2718 break; 2719 break;
2719 } 2720 }
2720 } 2721 }
2721 } 2722 }
2722 } 2723 }
2723 } 2724 }
2724 2725
2725 2726
2727 // Discover instructions that can be marked with kUint32 flag allowing
2728 // them to produce full range uint32 values.
2729 class Uint32Analysis BASE_EMBEDDED {
2730 public:
2731 explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { }
2732
2733 void Analyze(HInstruction* current);
2734
2735 void UnmarkUnsafePhis();
2736
2737 private:
2738 bool IsSafeUint32Use(HValue* val, HValue* use);
2739 bool Uint32UsesAreSafe(HValue* uint32val);
2740 bool CheckPhiOperands(HPhi* phi);
2741 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist);
2742
2743 Zone* zone_;
2744 ZoneList<HPhi*> phis_;
2745 };
2746
2747
2748 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
2749 // Operations that operatate on bits are safe.
2750 if (use->IsBitwise() ||
2751 use->IsShl() ||
2752 use->IsSar() ||
2753 use->IsShr() ||
2754 use->IsBitNot()) {
2755 return true;
2756 } else if (use->IsChange() || use->IsSimulate()) {
2757 // Conversions and deoptimization have special support for unt32.
2758 return true;
2759 } else if (use->IsStoreKeyedSpecializedArrayElement()) {
2760 // Storing a value into an external integer array is a bit level operation.
2761 HStoreKeyedSpecializedArrayElement* store =
2762 HStoreKeyedSpecializedArrayElement::cast(use);
2763
2764 if (store->value() == val) {
2765 // Clamping or a conversion to double should have beed inserted.
2766 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
2767 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
2768 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
2769 return true;
2770 }
2771 }
2772
2773 return false;
2774 }
2775
2776
2777 // Iterate over all uses and verify that they are uint32 safe: either don't
2778 // distinguish between int32 and uint32 due to their bitwise nature or
2779 // have special support for uint32 values.
2780 // Encountered phis are optimisitically treated as safe uint32 uses,
2781 // marked with kUint32 flag and collected in the phis_ list. A separate
2782 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from
2783 // phis that are not actually uint32-safe (it requries fix point iteration).
2784 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) {
2785 bool collect_phi_uses = false;
2786 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
2787 HValue* use = it.value();
2788
2789 if (use->IsPhi()) {
2790 if (!use->CheckFlag(HInstruction::kUint32)) {
2791 // There is a phi use of this value from a phis that is not yet
2792 // collected in phis_ array. Separate pass is required.
2793 collect_phi_uses = true;
2794 }
2795
2796 // Optimistically treat phis as uint32 safe.
2797 continue;
2798 }
2799
2800 if (!IsSafeUint32Use(uint32val, use)) {
2801 return false;
2802 }
2803 }
2804
2805 if (collect_phi_uses) {
2806 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
2807 HValue* use = it.value();
2808
2809 // There is a phi use of this value from a phis that is not yet
2810 // collected in phis_ array. Separate pass is required.
2811 if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) {
2812 use->SetFlag(HInstruction::kUint32);
2813 phis_.Add(HPhi::cast(use), zone_);
2814 }
2815 }
2816 }
2817
2818 return true;
2819 }
2820
2821
2822 // Analyze instruction and mark it with kUint32 if all its uses are uint32
2823 // safe.
2824 void Uint32Analysis::Analyze(HInstruction* current) {
2825 if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32);
2826 }
2827
2828
2829 // Check if all operands to the given phi are marked with kUint32 flag.
2830 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) {
2831 if (!phi->CheckFlag(HInstruction::kUint32)) {
2832 // This phi is not uint32 safe. No need to check operands.
2833 return false;
2834 }
2835
2836 for (int j = 0; j < phi->OperandCount(); j++) {
2837 HValue* operand = phi->OperandAt(j);
2838 if (!operand->CheckFlag(HInstruction::kUint32)) {
2839 // Lazyly mark constants that fit into uint32 range with kUint32 flag.
2840 if (operand->IsConstant() &&
2841 HConstant::cast(operand)->IsUint32()) {
2842 operand->SetFlag(HInstruction::kUint32);
2843 continue;
2844 }
2845
2846 // This phi is not safe, some operands are not uint32 values.
2847 return false;
2848 }
2849 }
2850
2851 return true;
2852 }
2853
2854
2855 // Remove kUint32 flag from the phi itself and its operands. If any operand
2856 // was a phi marked with kUint32 place it into a worklist for
2857 // transitive clearing of kUint32 flag.
2858 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) {
2859 phi->ClearFlag(HInstruction::kUint32);
2860 for (int j = 0; j < phi->OperandCount(); j++) {
2861 HValue* operand = phi->OperandAt(j);
2862 if (operand->CheckFlag(HInstruction::kUint32)) {
2863 operand->ClearFlag(HInstruction::kUint32);
2864 if (operand->IsPhi()) {
2865 worklist->Add(HPhi::cast(operand), zone_);
2866 }
2867 }
2868 }
2869 }
2870
2871
2872 void Uint32Analysis::UnmarkUnsafePhis() {
2873 // No phis were collected. Nothing to do.
2874 if (phis_.length() == 0) return;
2875
2876 // Worklist used to transitively clear kUint32 from phis that
2877 // are used as arguments to other phis.
2878 ZoneList<HPhi*> worklist(phis_.length(), zone_);
2879
2880 // Phi can be used as a uint32 value if and only if
2881 // all its operands are uint32 values and all its
2882 // uses are uint32 safe.
2883
2884 // Iterate over collected phis and unmark those that
2885 // are unsafe. When unmarking phi unmark its operands
2886 // and add it to the worklist if it is a phi as well.
2887 // Phis that are still marked as safe are shifted down
2888 // so that all safe phis form a prefix of the phis_ array.
2889 int phi_count = 0;
2890 for (int i = 0; i < phis_.length(); i++) {
2891 HPhi* phi = phis_[i];
2892
2893 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) {
2894 phis_[phi_count++] = phi;
2895 } else {
2896 UnmarkPhi(phi, &worklist);
2897 }
2898 }
2899
2900 // Now phis array contains only those phis that have safe
2901 // non-phi uses. Start transitively clearing kUint32 flag
2902 // from phi operands of discovered non-safe phies until
2903 // only safe phies are left.
2904 while (!worklist.is_empty()) {
2905 while (!worklist.is_empty()) {
2906 HPhi* phi = worklist.RemoveLast();
2907 UnmarkPhi(phi, &worklist);
2908 }
2909
2910 // Check if any operands to safe phies were unmarked
2911 // turning a safe phi into unsafe. The same value
2912 // can flow into several phis.
2913 int new_phi_count = 0;
2914 for (int i = 0; i < phi_count; i++) {
2915 HPhi* phi = phis_[i];
2916
2917 if (CheckPhiOperands(phi)) {
2918 phis_[new_phi_count++] = phi;
2919 } else {
2920 UnmarkPhi(phi, &worklist);
2921 }
2922 }
2923 phi_count = new_phi_count;
2924 }
2925 }
2926
2927
2928 void HGraph::ComputeSafeUint32Operations() {
2929 if (!FLAG_opt_safe_uint32_operations || uint32_instructions_ == NULL) {
2930 return;
2931 }
2932
2933 Uint32Analysis analysis(zone());
2934 for (int i = 0; i < uint32_instructions_->length(); ++i) {
2935 HInstruction* current = uint32_instructions_->at(i);
2936 if (current->IsLinked()) analysis.Analyze(current);
2937 }
2938
2939 // Some phis might have been optimistically marked with kUint32 flag.
2940 // Remove this flag from those phis that are unsafe and propagate
2941 // this information transitively potentially clearing kUint32 flag
2942 // from some non-phi operations that are used as operands to unsafe phis.
2943 analysis.UnmarkUnsafePhis();
2944 }
2945
2946
2726 void HGraph::ComputeMinusZeroChecks() { 2947 void HGraph::ComputeMinusZeroChecks() {
2727 BitVector visited(GetMaximumValueID(), zone()); 2948 BitVector visited(GetMaximumValueID(), zone());
2728 for (int i = 0; i < blocks_.length(); ++i) { 2949 for (int i = 0; i < blocks_.length(); ++i) {
2729 for (HInstruction* current = blocks_[i]->first(); 2950 for (HInstruction* current = blocks_[i]->first();
2730 current != NULL; 2951 current != NULL;
2731 current = current->next()) { 2952 current = current->next()) {
2732 if (current->IsChange()) { 2953 if (current->IsChange()) {
2733 HChange* change = HChange::cast(current); 2954 HChange* change = HChange::cast(current);
2734 // Propagate flags for negative zero checks upwards from conversions 2955 // Propagate flags for negative zero checks upwards from conversions
2735 // int32-to-tagged and int32-to-double. 2956 // int32-to-tagged and int32-to-double.
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
3124 } 3345 }
3125 } 3346 }
3126 3347
3127 HInferRepresentation rep(this); 3348 HInferRepresentation rep(this);
3128 rep.Analyze(); 3349 rep.Analyze();
3129 3350
3130 MarkDeoptimizeOnUndefined(); 3351 MarkDeoptimizeOnUndefined();
3131 InsertRepresentationChanges(); 3352 InsertRepresentationChanges();
3132 3353
3133 InitializeInferredTypes(); 3354 InitializeInferredTypes();
3355
3356 // Must be performed before canonicalization to ensure that Canonicalize
3357 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
3358 // zero.
3359 ComputeSafeUint32Operations();
3360
3134 Canonicalize(); 3361 Canonicalize();
3135 3362
3136 // Perform common subexpression elimination and loop-invariant code motion. 3363 // Perform common subexpression elimination and loop-invariant code motion.
3137 if (FLAG_use_gvn) { 3364 if (FLAG_use_gvn) {
3138 HPhase phase("H_Global value numbering", this); 3365 HPhase phase("H_Global value numbering", this);
3139 HGlobalValueNumberer gvn(this, info()); 3366 HGlobalValueNumberer gvn(this, info());
3140 bool removed_side_effects = gvn.Analyze(); 3367 bool removed_side_effects = gvn.Analyze();
3141 // Trigger a second analysis pass to further eliminate duplicate values that 3368 // Trigger a second analysis pass to further eliminate duplicate values that
3142 // could only be discovered by removing side-effect-generating instructions 3369 // could only be discovered by removing side-effect-generating instructions
3143 // during the first pass. 3370 // during the first pass.
(...skipping 2673 matching lines...) Expand 10 before | Expand all | Expand 10 after
5817 case FAST_HOLEY_DOUBLE_ELEMENTS: 6044 case FAST_HOLEY_DOUBLE_ELEMENTS:
5818 case DICTIONARY_ELEMENTS: 6045 case DICTIONARY_ELEMENTS:
5819 case NON_STRICT_ARGUMENTS_ELEMENTS: 6046 case NON_STRICT_ARGUMENTS_ELEMENTS:
5820 UNREACHABLE(); 6047 UNREACHABLE();
5821 break; 6048 break;
5822 } 6049 }
5823 return new(zone()) HStoreKeyedSpecializedArrayElement( 6050 return new(zone()) HStoreKeyedSpecializedArrayElement(
5824 external_elements, checked_key, val, elements_kind); 6051 external_elements, checked_key, val, elements_kind);
5825 } else { 6052 } else {
5826 ASSERT(val == NULL); 6053 ASSERT(val == NULL);
5827 return new(zone()) HLoadKeyedSpecializedArrayElement( 6054 HLoadKeyedSpecializedArrayElement* load =
5828 external_elements, checked_key, dependency, elements_kind); 6055 new(zone()) HLoadKeyedSpecializedArrayElement(
6056 external_elements, checked_key, dependency, elements_kind);
6057 if (FLAG_opt_safe_uint32_operations &&
6058 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
6059 graph()->RecordUint32Instruction(load);
6060 }
6061 return load;
5829 } 6062 }
5830 } 6063 }
5831 6064
5832 6065
5833 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, 6066 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
5834 HValue* checked_key, 6067 HValue* checked_key,
5835 HValue* val, 6068 HValue* val,
5836 HValue* load_dependency, 6069 HValue* load_dependency,
5837 ElementsKind elements_kind, 6070 ElementsKind elements_kind,
5838 bool is_store) { 6071 bool is_store) {
(...skipping 2164 matching lines...) Expand 10 before | Expand all | Expand 10 after
8003 case Token::BIT_XOR: 8236 case Token::BIT_XOR:
8004 case Token::BIT_AND: 8237 case Token::BIT_AND:
8005 case Token::BIT_OR: 8238 case Token::BIT_OR:
8006 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); 8239 instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
8007 break; 8240 break;
8008 case Token::SAR: 8241 case Token::SAR:
8009 instr = HSar::NewHSar(zone(), context, left, right); 8242 instr = HSar::NewHSar(zone(), context, left, right);
8010 break; 8243 break;
8011 case Token::SHR: 8244 case Token::SHR:
8012 instr = HShr::NewHShr(zone(), context, left, right); 8245 instr = HShr::NewHShr(zone(), context, left, right);
8246 if (FLAG_opt_safe_uint32_operations && instr->IsShr()) {
8247 graph()->RecordUint32Instruction(instr);
8248 }
8013 break; 8249 break;
8014 case Token::SHL: 8250 case Token::SHL:
8015 instr = HShl::NewHShl(zone(), context, left, right); 8251 instr = HShl::NewHShl(zone(), context, left, right);
8016 break; 8252 break;
8017 default: 8253 default:
8018 UNREACHABLE(); 8254 UNREACHABLE();
8019 } 8255 }
8020 8256
8021 // If we hit an uninitialized binary op stub we will get type info 8257 // If we hit an uninitialized binary op stub we will get type info
8022 // for a smi operation. If one of the operands is a constant string 8258 // for a smi operation. If one of the operands is a constant string
(...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after
9673 } 9909 }
9674 } 9910 }
9675 9911
9676 #ifdef DEBUG 9912 #ifdef DEBUG
9677 if (graph_ != NULL) graph_->Verify(false); // No full verify. 9913 if (graph_ != NULL) graph_->Verify(false); // No full verify.
9678 if (allocator_ != NULL) allocator_->Verify(); 9914 if (allocator_ != NULL) allocator_->Verify();
9679 #endif 9915 #endif
9680 } 9916 }
9681 9917
9682 } } // namespace v8::internal 9918 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698