OLD | NEW |
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 19 matching lines...) Expand all Loading... |
30 #include <algorithm> | 30 #include <algorithm> |
31 | 31 |
32 #include "v8.h" | 32 #include "v8.h" |
33 #include "codegen.h" | 33 #include "codegen.h" |
34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
35 #include "hashmap.h" | 35 #include "hashmap.h" |
36 #include "hydrogen-environment-liveness.h" | 36 #include "hydrogen-environment-liveness.h" |
37 #include "hydrogen-escape-analysis.h" | 37 #include "hydrogen-escape-analysis.h" |
38 #include "hydrogen-infer-representation.h" | 38 #include "hydrogen-infer-representation.h" |
39 #include "hydrogen-gvn.h" | 39 #include "hydrogen-gvn.h" |
| 40 #include "hydrogen-uint32-analysis.h" |
40 #include "lithium-allocator.h" | 41 #include "lithium-allocator.h" |
41 #include "parser.h" | 42 #include "parser.h" |
42 #include "scopeinfo.h" | 43 #include "scopeinfo.h" |
43 #include "scopes.h" | 44 #include "scopes.h" |
44 #include "stub-cache.h" | 45 #include "stub-cache.h" |
45 #include "typing.h" | 46 #include "typing.h" |
46 | 47 |
47 #if V8_TARGET_ARCH_IA32 | 48 #if V8_TARGET_ARCH_IA32 |
48 #include "ia32/lithium-codegen-ia32.h" | 49 #include "ia32/lithium-codegen-ia32.h" |
49 #elif V8_TARGET_ARCH_X64 | 50 #elif V8_TARGET_ARCH_X64 |
(...skipping 3021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3071 HValue* use_value = it.value(); | 3072 HValue* use_value = it.value(); |
3072 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { | 3073 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { |
3073 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); | 3074 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
3074 break; | 3075 break; |
3075 } | 3076 } |
3076 } | 3077 } |
3077 } | 3078 } |
3078 } | 3079 } |
3079 | 3080 |
3080 | 3081 |
3081 // Discover instructions that can be marked with kUint32 flag allowing | |
3082 // them to produce full range uint32 values. | |
3083 class Uint32Analysis BASE_EMBEDDED { | |
3084 public: | |
3085 explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { } | |
3086 | |
3087 void Analyze(HInstruction* current); | |
3088 | |
3089 void UnmarkUnsafePhis(); | |
3090 | |
3091 private: | |
3092 bool IsSafeUint32Use(HValue* val, HValue* use); | |
3093 bool Uint32UsesAreSafe(HValue* uint32val); | |
3094 bool CheckPhiOperands(HPhi* phi); | |
3095 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist); | |
3096 | |
3097 Zone* zone_; | |
3098 ZoneList<HPhi*> phis_; | |
3099 }; | |
3100 | |
3101 | |
3102 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) { | |
3103 // Operations that operatate on bits are safe. | |
3104 if (use->IsBitwise() || | |
3105 use->IsShl() || | |
3106 use->IsSar() || | |
3107 use->IsShr() || | |
3108 use->IsBitNot()) { | |
3109 return true; | |
3110 } else if (use->IsChange() || use->IsSimulate()) { | |
3111 // Conversions and deoptimization have special support for unt32. | |
3112 return true; | |
3113 } else if (use->IsStoreKeyed()) { | |
3114 HStoreKeyed* store = HStoreKeyed::cast(use); | |
3115 if (store->is_external()) { | |
3116 // Storing a value into an external integer array is a bit level | |
3117 // operation. | |
3118 if (store->value() == val) { | |
3119 // Clamping or a conversion to double should have beed inserted. | |
3120 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS); | |
3121 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS); | |
3122 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS); | |
3123 return true; | |
3124 } | |
3125 } | |
3126 } | |
3127 | |
3128 return false; | |
3129 } | |
3130 | |
3131 | |
3132 // Iterate over all uses and verify that they are uint32 safe: either don't | |
3133 // distinguish between int32 and uint32 due to their bitwise nature or | |
3134 // have special support for uint32 values. | |
3135 // Encountered phis are optimisitically treated as safe uint32 uses, | |
3136 // marked with kUint32 flag and collected in the phis_ list. A separate | |
3137 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from | |
3138 // phis that are not actually uint32-safe (it requries fix point iteration). | |
3139 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) { | |
3140 bool collect_phi_uses = false; | |
3141 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | |
3142 HValue* use = it.value(); | |
3143 | |
3144 if (use->IsPhi()) { | |
3145 if (!use->CheckFlag(HInstruction::kUint32)) { | |
3146 // There is a phi use of this value from a phis that is not yet | |
3147 // collected in phis_ array. Separate pass is required. | |
3148 collect_phi_uses = true; | |
3149 } | |
3150 | |
3151 // Optimistically treat phis as uint32 safe. | |
3152 continue; | |
3153 } | |
3154 | |
3155 if (!IsSafeUint32Use(uint32val, use)) { | |
3156 return false; | |
3157 } | |
3158 } | |
3159 | |
3160 if (collect_phi_uses) { | |
3161 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) { | |
3162 HValue* use = it.value(); | |
3163 | |
3164 // There is a phi use of this value from a phis that is not yet | |
3165 // collected in phis_ array. Separate pass is required. | |
3166 if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) { | |
3167 use->SetFlag(HInstruction::kUint32); | |
3168 phis_.Add(HPhi::cast(use), zone_); | |
3169 } | |
3170 } | |
3171 } | |
3172 | |
3173 return true; | |
3174 } | |
3175 | |
3176 | |
3177 // Analyze instruction and mark it with kUint32 if all its uses are uint32 | |
3178 // safe. | |
3179 void Uint32Analysis::Analyze(HInstruction* current) { | |
3180 if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32); | |
3181 } | |
3182 | |
3183 | |
3184 // Check if all operands to the given phi are marked with kUint32 flag. | |
3185 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) { | |
3186 if (!phi->CheckFlag(HInstruction::kUint32)) { | |
3187 // This phi is not uint32 safe. No need to check operands. | |
3188 return false; | |
3189 } | |
3190 | |
3191 for (int j = 0; j < phi->OperandCount(); j++) { | |
3192 HValue* operand = phi->OperandAt(j); | |
3193 if (!operand->CheckFlag(HInstruction::kUint32)) { | |
3194 // Lazyly mark constants that fit into uint32 range with kUint32 flag. | |
3195 if (operand->IsInteger32Constant() && | |
3196 operand->GetInteger32Constant() >= 0) { | |
3197 operand->SetFlag(HInstruction::kUint32); | |
3198 continue; | |
3199 } | |
3200 | |
3201 // This phi is not safe, some operands are not uint32 values. | |
3202 return false; | |
3203 } | |
3204 } | |
3205 | |
3206 return true; | |
3207 } | |
3208 | |
3209 | |
3210 // Remove kUint32 flag from the phi itself and its operands. If any operand | |
3211 // was a phi marked with kUint32 place it into a worklist for | |
3212 // transitive clearing of kUint32 flag. | |
3213 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) { | |
3214 phi->ClearFlag(HInstruction::kUint32); | |
3215 for (int j = 0; j < phi->OperandCount(); j++) { | |
3216 HValue* operand = phi->OperandAt(j); | |
3217 if (operand->CheckFlag(HInstruction::kUint32)) { | |
3218 operand->ClearFlag(HInstruction::kUint32); | |
3219 if (operand->IsPhi()) { | |
3220 worklist->Add(HPhi::cast(operand), zone_); | |
3221 } | |
3222 } | |
3223 } | |
3224 } | |
3225 | |
3226 | |
3227 void Uint32Analysis::UnmarkUnsafePhis() { | |
3228 // No phis were collected. Nothing to do. | |
3229 if (phis_.length() == 0) return; | |
3230 | |
3231 // Worklist used to transitively clear kUint32 from phis that | |
3232 // are used as arguments to other phis. | |
3233 ZoneList<HPhi*> worklist(phis_.length(), zone_); | |
3234 | |
3235 // Phi can be used as a uint32 value if and only if | |
3236 // all its operands are uint32 values and all its | |
3237 // uses are uint32 safe. | |
3238 | |
3239 // Iterate over collected phis and unmark those that | |
3240 // are unsafe. When unmarking phi unmark its operands | |
3241 // and add it to the worklist if it is a phi as well. | |
3242 // Phis that are still marked as safe are shifted down | |
3243 // so that all safe phis form a prefix of the phis_ array. | |
3244 int phi_count = 0; | |
3245 for (int i = 0; i < phis_.length(); i++) { | |
3246 HPhi* phi = phis_[i]; | |
3247 | |
3248 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) { | |
3249 phis_[phi_count++] = phi; | |
3250 } else { | |
3251 UnmarkPhi(phi, &worklist); | |
3252 } | |
3253 } | |
3254 | |
3255 // Now phis array contains only those phis that have safe | |
3256 // non-phi uses. Start transitively clearing kUint32 flag | |
3257 // from phi operands of discovered non-safe phies until | |
3258 // only safe phies are left. | |
3259 while (!worklist.is_empty()) { | |
3260 while (!worklist.is_empty()) { | |
3261 HPhi* phi = worklist.RemoveLast(); | |
3262 UnmarkPhi(phi, &worklist); | |
3263 } | |
3264 | |
3265 // Check if any operands to safe phies were unmarked | |
3266 // turning a safe phi into unsafe. The same value | |
3267 // can flow into several phis. | |
3268 int new_phi_count = 0; | |
3269 for (int i = 0; i < phi_count; i++) { | |
3270 HPhi* phi = phis_[i]; | |
3271 | |
3272 if (CheckPhiOperands(phi)) { | |
3273 phis_[new_phi_count++] = phi; | |
3274 } else { | |
3275 UnmarkPhi(phi, &worklist); | |
3276 } | |
3277 } | |
3278 phi_count = new_phi_count; | |
3279 } | |
3280 } | |
3281 | |
3282 | |
3283 void HGraph::ComputeSafeUint32Operations() { | |
3284 HPhase phase("H_Compute safe UInt32 operations", this); | |
3285 if (uint32_instructions_ == NULL) return; | |
3286 | |
3287 Uint32Analysis analysis(zone()); | |
3288 for (int i = 0; i < uint32_instructions_->length(); ++i) { | |
3289 HInstruction* current = uint32_instructions_->at(i); | |
3290 if (current->IsLinked() && current->representation().IsInteger32()) { | |
3291 analysis.Analyze(current); | |
3292 } | |
3293 } | |
3294 | |
3295 // Some phis might have been optimistically marked with kUint32 flag. | |
3296 // Remove this flag from those phis that are unsafe and propagate | |
3297 // this information transitively potentially clearing kUint32 flag | |
3298 // from some non-phi operations that are used as operands to unsafe phis. | |
3299 analysis.UnmarkUnsafePhis(); | |
3300 } | |
3301 | |
3302 | |
3303 void HGraph::ComputeMinusZeroChecks() { | 3082 void HGraph::ComputeMinusZeroChecks() { |
3304 HPhase phase("H_Compute minus zero checks", this); | 3083 HPhase phase("H_Compute minus zero checks", this); |
3305 BitVector visited(GetMaximumValueID(), zone()); | 3084 BitVector visited(GetMaximumValueID(), zone()); |
3306 for (int i = 0; i < blocks_.length(); ++i) { | 3085 for (int i = 0; i < blocks_.length(); ++i) { |
3307 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) { | 3086 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) { |
3308 HInstruction* current = it.Current(); | 3087 HInstruction* current = it.Current(); |
3309 if (current->IsChange()) { | 3088 if (current->IsChange()) { |
3310 HChange* change = HChange::cast(current); | 3089 HChange* change = HChange::cast(current); |
3311 // Propagate flags for negative zero checks upwards from conversions | 3090 // Propagate flags for negative zero checks upwards from conversions |
3312 // int32-to-tagged and int32-to-double. | 3091 // int32-to-tagged and int32-to-double. |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3804 MergeRemovableSimulates(); | 3583 MergeRemovableSimulates(); |
3805 | 3584 |
3806 MarkDeoptimizeOnUndefined(); | 3585 MarkDeoptimizeOnUndefined(); |
3807 InsertRepresentationChanges(); | 3586 InsertRepresentationChanges(); |
3808 | 3587 |
3809 InitializeInferredTypes(); | 3588 InitializeInferredTypes(); |
3810 | 3589 |
3811 // Must be performed before canonicalization to ensure that Canonicalize | 3590 // Must be performed before canonicalization to ensure that Canonicalize |
3812 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 3591 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
3813 // zero. | 3592 // zero. |
3814 if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations(); | 3593 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); |
3815 | 3594 |
3816 if (FLAG_use_canonicalizing) Canonicalize(); | 3595 if (FLAG_use_canonicalizing) Canonicalize(); |
3817 | 3596 |
3818 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); | 3597 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); |
3819 | 3598 |
3820 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 3599 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
3821 | 3600 |
3822 if (FLAG_use_range) { | 3601 if (FLAG_use_range) { |
3823 HRangeAnalysis range_analysis(this); | 3602 HRangeAnalysis range_analysis(this); |
3824 range_analysis.Analyze(); | 3603 range_analysis.Analyze(); |
(...skipping 7416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11241 if (ShouldProduceTraceOutput()) { | 11020 if (ShouldProduceTraceOutput()) { |
11242 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11021 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11243 } | 11022 } |
11244 | 11023 |
11245 #ifdef DEBUG | 11024 #ifdef DEBUG |
11246 graph_->Verify(false); // No full verify. | 11025 graph_->Verify(false); // No full verify. |
11247 #endif | 11026 #endif |
11248 } | 11027 } |
11249 | 11028 |
11250 } } // namespace v8::internal | 11029 } } // namespace v8::internal |
OLD | NEW |