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

Side by Side Diff: src/hydrogen.cc

Issue 18487003: Turn UInt32 analysis into a proper HPhase. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix typos. Created 7 years, 5 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
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-uint32-analysis.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 19 matching lines...) Expand all
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-uint32-analysis.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698