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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 14268019: Basic support for LICM of fully invariant loads. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: review ready Created 7 years, 7 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 | « runtime/vm/flow_graph.cc ('k') | runtime/vm/intermediate_language.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 (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 3328 matching lines...) Expand 10 before | Expand all | Expand 10 after
3339 // Host CheckSmi instruction and make this phi smi one. 3339 // Host CheckSmi instruction and make this phi smi one.
3340 Hoist(it, pre_header, current); 3340 Hoist(it, pre_header, current);
3341 3341
3342 // Replace value we are checking with phi's input. 3342 // Replace value we are checking with phi's input.
3343 current->value()->BindTo(phi->InputAt(non_smi_input)->definition()); 3343 current->value()->BindTo(phi->InputAt(non_smi_input)->definition());
3344 3344
3345 phi->UpdateType(CompileType::FromCid(kSmiCid)); 3345 phi->UpdateType(CompileType::FromCid(kSmiCid));
3346 } 3346 }
3347 3347
3348 3348
3349 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets,
3350 intptr_t loop_header_index,
3351 Instruction* instr) {
3352 return (sets != NULL) &&
3353 instr->HasExprId() &&
3354 ((*sets)[loop_header_index] != NULL) &&
3355 (*sets)[loop_header_index]->Contains(instr->expr_id());
3356 }
3357
3358
3349 void LICM::Optimize() { 3359 void LICM::Optimize() {
3350 GrowableArray<BlockEntryInstr*> loop_headers; 3360 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
3351 flow_graph()->ComputeLoops(&loop_headers); 3361 flow_graph()->loop_headers();
3362
3363 ZoneGrowableArray<BitVector*>* loop_invariant_loads =
3364 flow_graph()->loop_invariant_loads();
3365
3366 BlockEffects* block_effects = flow_graph()->block_effects();
3352 3367
3353 for (intptr_t i = 0; i < loop_headers.length(); ++i) { 3368 for (intptr_t i = 0; i < loop_headers.length(); ++i) {
3354 BlockEntryInstr* header = loop_headers[i]; 3369 BlockEntryInstr* header = loop_headers[i];
3355 // Skip loop that don't have a pre-header block. 3370 // Skip loop that don't have a pre-header block.
3356 BlockEntryInstr* pre_header = FindPreHeader(header); 3371 BlockEntryInstr* pre_header = FindPreHeader(header);
3357 if (pre_header == NULL) continue; 3372 if (pre_header == NULL) continue;
3358 3373
3359 for (BitVector::Iterator loop_it(header->loop_info()); 3374 for (BitVector::Iterator loop_it(header->loop_info());
3360 !loop_it.Done(); 3375 !loop_it.Done();
3361 loop_it.Advance()) { 3376 loop_it.Advance()) {
3362 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()]; 3377 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()];
3363 for (ForwardInstructionIterator it(block); 3378 for (ForwardInstructionIterator it(block);
3364 !it.Done(); 3379 !it.Done();
3365 it.Advance()) { 3380 it.Advance()) {
3366 Instruction* current = it.Current(); 3381 Instruction* current = it.Current();
3367 if (current->AllowsCSE() && 3382 if ((current->AllowsCSE() &&
3368 flow_graph()->block_effects()->CanBeMovedTo(current, pre_header)) { 3383 block_effects->CanBeMovedTo(current, pre_header)) ||
3384 IsLoopInvariantLoad(loop_invariant_loads, i, current)) {
3369 bool inputs_loop_invariant = true; 3385 bool inputs_loop_invariant = true;
3370 for (int i = 0; i < current->InputCount(); ++i) { 3386 for (int i = 0; i < current->InputCount(); ++i) {
3371 Definition* input_def = current->InputAt(i)->definition(); 3387 Definition* input_def = current->InputAt(i)->definition();
3372 if (!input_def->GetBlock()->Dominates(pre_header)) { 3388 if (!input_def->GetBlock()->Dominates(pre_header)) {
3373 inputs_loop_invariant = false; 3389 inputs_loop_invariant = false;
3374 break; 3390 break;
3375 } 3391 }
3376 } 3392 }
3377 if (inputs_loop_invariant && 3393 if (inputs_loop_invariant &&
3378 !current->IsAssertAssignable() && 3394 !current->IsAssertAssignable() &&
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
3884 continue; 3900 continue;
3885 } 3901 }
3886 Definition* result = map->Lookup(defn); 3902 Definition* result = map->Lookup(defn);
3887 if (result == NULL) { 3903 if (result == NULL) {
3888 map->Insert(defn); 3904 map->Insert(defn);
3889 defn->set_expr_id(expr_id++); 3905 defn->set_expr_id(expr_id++);
3890 loads.Add(defn); 3906 loads.Add(defn);
3891 } else { 3907 } else {
3892 defn->set_expr_id(result->expr_id()); 3908 defn->set_expr_id(result->expr_id());
3893 } 3909 }
3910
3911 if (FLAG_trace_optimization) {
3912 OS::Print("load v%"Pd" is numbered as %"Pd"\n",
3913 defn->ssa_temp_index(),
3914 defn->expr_id());
3915 }
3894 } 3916 }
3895 } 3917 }
3896 3918
3897 // Build aliasing sets mapping aliases to loads. 3919 // Build aliasing sets mapping aliases to loads.
3898 AliasedSet* aliased_set = new AliasedSet(expr_id); 3920 AliasedSet* aliased_set = new AliasedSet(expr_id);
3899 for (intptr_t i = 0; i < loads.length(); i++) { 3921 for (intptr_t i = 0; i < loads.length(); i++) {
3900 Definition* defn = loads[i]; 3922 Definition* defn = loads[i];
3901 aliased_set->AddRepresentative(defn); 3923 aliased_set->AddRepresentative(defn);
3902 } 3924 }
3903 return aliased_set; 3925 return aliased_set;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3949 LoadOptimizer load_optimizer(graph, aliased_set, &map); 3971 LoadOptimizer load_optimizer(graph, aliased_set, &map);
3950 return load_optimizer.Optimize(); 3972 return load_optimizer.Optimize();
3951 } 3973 }
3952 return false; 3974 return false;
3953 } 3975 }
3954 3976
3955 private: 3977 private:
3956 bool Optimize() { 3978 bool Optimize() {
3957 ComputeInitialSets(); 3979 ComputeInitialSets();
3958 ComputeOutValues(); 3980 ComputeOutValues();
3981 if (graph_->is_licm_allowed()) {
3982 MarkLoopInvariantLoads();
3983 }
3959 ForwardLoads(); 3984 ForwardLoads();
3960 EmitPhis(); 3985 EmitPhis();
3961 return forwarded_; 3986 return forwarded_;
3962 } 3987 }
3963 3988
3964 // Compute sets of loads generated and killed by each block. 3989 // Compute sets of loads generated and killed by each block.
3965 // Additionally compute upwards exposed and generated loads for each block. 3990 // Additionally compute upwards exposed and generated loads for each block.
3966 // Exposed loads are those that can be replaced if a corresponding 3991 // Exposed loads are those that can be replaced if a corresponding
3967 // reaching load will be found. 3992 // reaching load will be found.
3968 // Loads that are locally redundant will be replaced as we go through 3993 // Loads that are locally redundant will be replaced as we go through
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
4204 block_in->Print(); 4229 block_in->Print();
4205 block_out->Print(); 4230 block_out->Print();
4206 block_kill->Print(); 4231 block_kill->Print();
4207 block_gen->Print(); 4232 block_gen->Print();
4208 OS::Print("\n"); 4233 OS::Print("\n");
4209 } 4234 }
4210 } 4235 }
4211 } 4236 }
4212 } 4237 }
4213 4238
4239 void MarkLoopInvariantLoads() {
4240 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
4241 graph_->loop_headers();
4242
4243 ZoneGrowableArray<BitVector*>* invariant_loads =
4244 new ZoneGrowableArray<BitVector*>(loop_headers.length());
4245
4246 for (intptr_t i = 0; i < loop_headers.length(); i++) {
4247 BlockEntryInstr* header = loop_headers[i];
4248 BlockEntryInstr* pre_header = FindPreHeader(header);
4249 if (pre_header == NULL) {
4250 invariant_loads->Add(NULL);
4251 continue;
4252 }
4253
4254 BitVector* loop_gen = new BitVector(aliased_set_->max_expr_id());
4255 for (BitVector::Iterator loop_it(header->loop_info());
4256 !loop_it.Done();
4257 loop_it.Advance()) {
4258 const intptr_t preorder_number = loop_it.Current();
4259 loop_gen->AddAll(gen_[preorder_number]);
4260 }
4261
4262 for (BitVector::Iterator loop_it(header->loop_info());
4263 !loop_it.Done();
4264 loop_it.Advance()) {
4265 const intptr_t preorder_number = loop_it.Current();
4266 loop_gen->RemoveAll(kill_[preorder_number]);
4267 }
4268
4269 if (FLAG_trace_optimization) {
4270 for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) {
4271 OS::Print("load %"Pd" is loop invariant for B%"Pd"\n",
4272 it.Current(),
4273 header->block_id());
4274 }
4275 }
4276
4277 invariant_loads->Add(loop_gen);
4278 }
4279
4280 graph_->set_loop_invariant_loads(invariant_loads);
4281 }
4282
4214 // Compute incoming value for the given expression id. 4283 // Compute incoming value for the given expression id.
4215 // Will create a phi if different values are incoming from multiple 4284 // Will create a phi if different values are incoming from multiple
4216 // predecessors. 4285 // predecessors.
4217 Definition* MergeIncomingValues(BlockEntryInstr* block, intptr_t expr_id) { 4286 Definition* MergeIncomingValues(BlockEntryInstr* block, intptr_t expr_id) {
4218 // First check if the same value is coming in from all predecessors. 4287 // First check if the same value is coming in from all predecessors.
4219 Definition* incoming = NULL; 4288 Definition* incoming = NULL;
4220 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { 4289 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
4221 BlockEntryInstr* pred = block->PredecessorAt(i); 4290 BlockEntryInstr* pred = block->PredecessorAt(i);
4222 ZoneGrowableArray<Definition*>* pred_out_values = 4291 ZoneGrowableArray<Definition*>* pred_out_values =
4223 out_values_[pred->preorder_number()]; 4292 out_values_[pred->preorder_number()];
(...skipping 2034 matching lines...) Expand 10 before | Expand all | Expand 10 after
6258 6327
6259 // Insert materializations at environment uses. 6328 // Insert materializations at environment uses.
6260 const Class& cls = Class::Handle(alloc->constructor().Owner()); 6329 const Class& cls = Class::Handle(alloc->constructor().Owner());
6261 for (intptr_t i = 0; i < exits.length(); i++) { 6330 for (intptr_t i = 0; i < exits.length(); i++) {
6262 CreateMaterializationAt(exits[i], alloc, cls, *fields); 6331 CreateMaterializationAt(exits[i], alloc, cls, *fields);
6263 } 6332 }
6264 } 6333 }
6265 6334
6266 6335
6267 } // namespace dart 6336 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698