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

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

Issue 728863005: Teach LoadOptimizer to interblock multi-indirection redundancies in one pass. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | « no previous file | no next file » | 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/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 5598 matching lines...) Expand 10 before | Expand all | Expand 10 after
5609 GrowableArray<ZoneGrowableArray<Move>* > moves_; 5609 GrowableArray<ZoneGrowableArray<Move>* > moves_;
5610 }; 5610 };
5611 5611
5612 5612
5613 // A map from aliases to a set of places sharing the alias. Additionally 5613 // A map from aliases to a set of places sharing the alias. Additionally
5614 // carries a set of places that can be aliased by side-effects, essentially 5614 // carries a set of places that can be aliased by side-effects, essentially
5615 // those that are affected by calls. 5615 // those that are affected by calls.
5616 class AliasedSet : public ZoneAllocated { 5616 class AliasedSet : public ZoneAllocated {
5617 public: 5617 public:
5618 AliasedSet(Isolate* isolate, 5618 AliasedSet(Isolate* isolate,
5619 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map,
5619 ZoneGrowableArray<Place*>* places, 5620 ZoneGrowableArray<Place*>* places,
5620 PhiPlaceMoves* phi_moves) 5621 PhiPlaceMoves* phi_moves)
5621 : isolate_(isolate), 5622 : isolate_(isolate),
5623 places_map_(places_map),
5622 places_(*places), 5624 places_(*places),
5623 phi_moves_(phi_moves), 5625 phi_moves_(phi_moves),
5624 aliases_(5), 5626 aliases_(5),
5625 aliases_map_(), 5627 aliases_map_(),
5626 representatives_(), 5628 representatives_(),
5627 killed_(), 5629 killed_(),
5628 aliased_by_effects_(new(isolate) BitVector(isolate, places->length())) { 5630 aliased_by_effects_(new(isolate) BitVector(isolate, places->length())) {
5629 InsertAlias(Place::CreateAnyInstanceAnyIndexAlias(isolate_, 5631 InsertAlias(Place::CreateAnyInstanceAnyIndexAlias(isolate_,
5630 kAnyInstanceAnyIndexAlias)); 5632 kAnyInstanceAnyIndexAlias));
5631 for (intptr_t i = 0; i < places_.length(); i++) { 5633 for (intptr_t i = 0; i < places_.length(); i++) {
5632 AddRepresentative(places_[i]); 5634 AddRepresentative(places_[i]);
5633 } 5635 }
5634 ComputeKillSets(); 5636 ComputeKillSets();
5635 } 5637 }
5636 5638
5637 intptr_t LookupAliasId(const Place& alias) { 5639 intptr_t LookupAliasId(const Place& alias) {
5638 const Place* result = aliases_map_.Lookup(&alias); 5640 const Place* result = aliases_map_.Lookup(&alias);
5639 return (result != NULL) ? result->id() : static_cast<intptr_t>(kNoAlias); 5641 return (result != NULL) ? result->id() : static_cast<intptr_t>(kNoAlias);
5640 } 5642 }
5641 5643
5642 bool IsStore(Instruction* instr, BitVector** killed) { 5644 bool IsStore(Instruction* instr, BitVector** killed) {
Florian Schneider 2014/11/17 12:46:02 The name is a little misleading since this method
5643 bool is_load = false, is_store = false; 5645 bool is_load = false, is_store = false;
5644 Place place(instr, &is_load, &is_store); 5646 Place place(instr, &is_load, &is_store);
5645 if (is_store && (place.kind() != Place::kNone)) { 5647 if (is_store && (place.kind() != Place::kNone)) {
5646 const intptr_t alias_id = LookupAliasId(place.ToAlias()); 5648 const intptr_t alias_id = LookupAliasId(place.ToAlias());
5647 if (alias_id != kNoAlias) { 5649 if (alias_id != kNoAlias) {
5648 *killed = GetKilledSet(alias_id); 5650 *killed = GetKilledSet(alias_id);
5649 } else if (!place.IsFinalField()) { 5651 } else if (!place.IsFinalField()) {
5650 // We encountered unknown alias: this means intrablock load forwarding 5652 // We encountered unknown alias: this means intrablock load forwarding
5651 // refined parameter of this store, for example 5653 // refined parameter of this store, for example
5652 // 5654 //
5653 // o <- alloc() 5655 // o <- alloc()
5654 // a.f <- o 5656 // a.f <- o
5655 // u <- a.f 5657 // u <- a.f
5656 // u.x <- null ;; this store alias is *.x 5658 // u.x <- null ;; this store alias is *.x
5657 // 5659 //
5658 // after intrablock load forwarding 5660 // after intrablock load forwarding
5659 // 5661 //
5660 // o <- alloc() 5662 // o <- alloc()
5661 // a.f <- o 5663 // a.f <- o
5662 // o.x <- null ;; this store alias is o.x 5664 // o.x <- null ;; this store alias is o.x
5663 // 5665 //
5664 // In this case we fallback to using place id recorded in the 5666 // In this case we fallback to using place id recorded in the
5665 // instruction that still points to the old place with a more generic 5667 // instruction that still points to the old place with a more generic
5666 // alias. 5668 // alias.
5667 *killed = GetKilledSet( 5669 *killed = GetKilledSet(
5668 LookupAliasId(places_[instr->place_id()]->ToAlias())); 5670 LookupAliasId(places_[instr->place_id()]->ToAlias()));
5669 } 5671 }
5672 } else if (is_load && (place.kind() != Place::kNone)) {
5673 const Place* canonical = LookupCanonical(&place);
5674 if ((canonical != NULL) &&
5675 (canonical->id() != instr->AsDefinition()->place_id())) {
5676 instr->AsDefinition()->set_place_id(canonical->id());
5677 }
5670 } 5678 }
5671 return is_store; 5679 return is_store;
5672 } 5680 }
5673 5681
5674 BitVector* GetKilledSet(intptr_t alias) { 5682 BitVector* GetKilledSet(intptr_t alias) {
5675 return (alias < killed_.length()) ? killed_[alias] : NULL; 5683 return (alias < killed_.length()) ? killed_[alias] : NULL;
5676 } 5684 }
5677 5685
5678 intptr_t max_place_id() const { return places().length(); } 5686 intptr_t max_place_id() const { return places().length(); }
5679 bool IsEmpty() const { return max_place_id() == 0; } 5687 bool IsEmpty() const { return max_place_id() == 0; }
5680 5688
5681 BitVector* aliased_by_effects() const { return aliased_by_effects_; } 5689 BitVector* aliased_by_effects() const { return aliased_by_effects_; }
5682 5690
5683 const ZoneGrowableArray<Place*>& places() const { 5691 const ZoneGrowableArray<Place*>& places() const {
5684 return places_; 5692 return places_;
5685 } 5693 }
5686 5694
5695 Place* LookupCanonical(Place* place) const {
5696 return places_map_->Lookup(place);
5697 }
5698
5687 void PrintSet(BitVector* set) { 5699 void PrintSet(BitVector* set) {
5688 bool comma = false; 5700 bool comma = false;
5689 for (BitVector::Iterator it(set); 5701 for (BitVector::Iterator it(set);
5690 !it.Done(); 5702 !it.Done();
5691 it.Advance()) { 5703 it.Advance()) {
5692 if (comma) { 5704 if (comma) {
5693 OS::Print(", "); 5705 OS::Print(", ");
5694 } 5706 }
5695 OS::Print("%s", places_[it.Current()]->ToCString()); 5707 OS::Print("%s", places_[it.Current()]->ToCString());
5696 comma = true; 5708 comma = true;
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
6048 // If the allocation site is marked as aliased conservatively mark 6060 // If the allocation site is marked as aliased conservatively mark
6049 // any values stored into the object aliased too. 6061 // any values stored into the object aliased too.
6050 if (defn->Identity().IsAliased()) { 6062 if (defn->Identity().IsAliased()) {
6051 MarkStoredValuesEscaping(defn); 6063 MarkStoredValuesEscaping(defn);
6052 } 6064 }
6053 } 6065 }
6054 } 6066 }
6055 6067
6056 Isolate* isolate_; 6068 Isolate* isolate_;
6057 6069
6070 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map_;
6071
6058 const ZoneGrowableArray<Place*>& places_; 6072 const ZoneGrowableArray<Place*>& places_;
6059 6073
6060 const PhiPlaceMoves* phi_moves_; 6074 const PhiPlaceMoves* phi_moves_;
6061 6075
6062 // A list of all seen aliases and a map that allows looking up canonical 6076 // A list of all seen aliases and a map that allows looking up canonical
6063 // alias object. 6077 // alias object.
6064 GrowableArray<const Place*> aliases_; 6078 GrowableArray<const Place*> aliases_;
6065 DirectChainedHashMap<PointerKeyValueTrait<const Place> > aliases_map_; 6079 DirectChainedHashMap<PointerKeyValueTrait<const Place> > aliases_map_;
6066 6080
6067 // Maps alias id to set of ids of places representing the alias. 6081 // Maps alias id to set of ids of places representing the alias.
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
6217 if ((mode == kOptimizeLoads) && !has_loads) { 6231 if ((mode == kOptimizeLoads) && !has_loads) {
6218 return NULL; 6232 return NULL;
6219 } 6233 }
6220 if ((mode == kOptimizeStores) && !has_stores) { 6234 if ((mode == kOptimizeStores) && !has_stores) {
6221 return NULL; 6235 return NULL;
6222 } 6236 }
6223 6237
6224 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); 6238 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places);
6225 6239
6226 // Build aliasing sets mapping aliases to loads. 6240 // Build aliasing sets mapping aliases to loads.
6227 return new(isolate) AliasedSet(isolate, places, phi_moves); 6241 return new(isolate) AliasedSet(isolate, map, places, phi_moves);
6228 } 6242 }
6229 6243
6230 6244
6231 class LoadOptimizer : public ValueObject { 6245 class LoadOptimizer : public ValueObject {
6232 public: 6246 public:
6233 LoadOptimizer(FlowGraph* graph, 6247 LoadOptimizer(FlowGraph* graph, AliasedSet* aliased_set)
6234 AliasedSet* aliased_set,
6235 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map)
6236 : graph_(graph), 6248 : graph_(graph),
6237 map_(map),
6238 aliased_set_(aliased_set), 6249 aliased_set_(aliased_set),
6239 in_(graph_->preorder().length()), 6250 in_(graph_->preorder().length()),
6240 out_(graph_->preorder().length()), 6251 out_(graph_->preorder().length()),
6241 gen_(graph_->preorder().length()), 6252 gen_(graph_->preorder().length()),
6242 kill_(graph_->preorder().length()), 6253 kill_(graph_->preorder().length()),
6243 exposed_values_(graph_->preorder().length()), 6254 exposed_values_(graph_->preorder().length()),
6244 out_values_(graph_->preorder().length()), 6255 out_values_(graph_->preorder().length()),
6245 phis_(5), 6256 phis_(5),
6246 worklist_(5), 6257 worklist_(5),
6247 congruency_worklist_(6), 6258 congruency_worklist_(6),
(...skipping 25 matching lines...) Expand all
6273 6284
6274 DirectChainedHashMap<PointerKeyValueTrait<Place> > map; 6285 DirectChainedHashMap<PointerKeyValueTrait<Place> > map;
6275 AliasedSet* aliased_set = NumberPlaces(graph, &map, kOptimizeLoads); 6286 AliasedSet* aliased_set = NumberPlaces(graph, &map, kOptimizeLoads);
6276 if ((aliased_set != NULL) && !aliased_set->IsEmpty()) { 6287 if ((aliased_set != NULL) && !aliased_set->IsEmpty()) {
6277 // If any loads were forwarded return true from Optimize to run load 6288 // If any loads were forwarded return true from Optimize to run load
6278 // forwarding again. This will allow to forward chains of loads. 6289 // forwarding again. This will allow to forward chains of loads.
6279 // This is especially important for context variables as they are built 6290 // This is especially important for context variables as they are built
6280 // as loads from loaded context. 6291 // as loads from loaded context.
6281 // TODO(vegorov): renumber newly discovered congruences during the 6292 // TODO(vegorov): renumber newly discovered congruences during the
6282 // forwarding to forward chains without running whole pass twice. 6293 // forwarding to forward chains without running whole pass twice.
6283 LoadOptimizer load_optimizer(graph, aliased_set, &map); 6294 LoadOptimizer load_optimizer(graph, aliased_set);
6284 return load_optimizer.Optimize(); 6295 return load_optimizer.Optimize();
6285 } 6296 }
6286 return false; 6297 return false;
6287 } 6298 }
6288 6299
6289 private: 6300 private:
6290 bool Optimize() { 6301 bool Optimize() {
6291 ComputeInitialSets(); 6302 ComputeInitialSets();
6292 ComputeOutSets(); 6303 ComputeOutSets();
6293 ComputeOutValues(); 6304 ComputeOutValues();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6343 // may implicitly convert the value stored. 6354 // may implicitly convert the value stored.
6344 StoreIndexedInstr* array_store = instr->AsStoreIndexed(); 6355 StoreIndexedInstr* array_store = instr->AsStoreIndexed();
6345 if ((array_store == NULL) || 6356 if ((array_store == NULL) ||
6346 (array_store->class_id() == kArrayCid) || 6357 (array_store->class_id() == kArrayCid) ||
6347 (array_store->class_id() == kTypedDataFloat64ArrayCid) || 6358 (array_store->class_id() == kTypedDataFloat64ArrayCid) ||
6348 (array_store->class_id() == kTypedDataFloat32ArrayCid) || 6359 (array_store->class_id() == kTypedDataFloat32ArrayCid) ||
6349 (array_store->class_id() == kTypedDataFloat32x4ArrayCid)) { 6360 (array_store->class_id() == kTypedDataFloat32x4ArrayCid)) {
6350 bool is_load = false, is_store = false; 6361 bool is_load = false, is_store = false;
6351 Place store_place(instr, &is_load, &is_store); 6362 Place store_place(instr, &is_load, &is_store);
6352 ASSERT(!is_load && is_store); 6363 ASSERT(!is_load && is_store);
6353 Place* place = map_->Lookup(&store_place); 6364 Place* place = aliased_set_->LookupCanonical(&store_place);
6354 if (place != NULL) { 6365 if (place != NULL) {
6355 // Store has a corresponding numbered place that might have a 6366 // Store has a corresponding numbered place that might have a
6356 // load. Try forwarding stored value to it. 6367 // load. Try forwarding stored value to it.
6357 gen->Add(place->id()); 6368 gen->Add(place->id());
6358 if (out_values == NULL) out_values = CreateBlockOutValues(); 6369 if (out_values == NULL) out_values = CreateBlockOutValues();
6359 (*out_values)[place->id()] = GetStoredValue(instr); 6370 (*out_values)[place->id()] = GetStoredValue(instr);
6360 } 6371 }
6361 } 6372 }
6362 6373
6363 ASSERT(!instr->IsDefinition() || 6374 ASSERT(!instr->IsDefinition() ||
(...skipping 3649 matching lines...) Expand 10 before | Expand all | Expand 10 after
10013 10024
10014 // Insert materializations at environment uses. 10025 // Insert materializations at environment uses.
10015 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 10026 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
10016 CreateMaterializationAt( 10027 CreateMaterializationAt(
10017 exits_collector_.exits()[i], alloc, *slots); 10028 exits_collector_.exits()[i], alloc, *slots);
10018 } 10029 }
10019 } 10030 }
10020 10031
10021 10032
10022 } // namespace dart 10033 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698