| Index: runtime/vm/redundancy_elimination.cc
|
| diff --git a/runtime/vm/redundancy_elimination.cc b/runtime/vm/redundancy_elimination.cc
|
| index 06df06ab4b404d088efff525ccdeed9f594dd401..707eedc9b38d2b8e6a6caea35c6cf060968c55c4 100644
|
| --- a/runtime/vm/redundancy_elimination.cc
|
| +++ b/runtime/vm/redundancy_elimination.cc
|
| @@ -13,7 +13,6 @@
|
|
|
| namespace dart {
|
|
|
| -
|
| DEFINE_FLAG(bool, dead_store_elimination, true, "Eliminate dead stores");
|
| DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
|
| DEFINE_FLAG(bool,
|
| @@ -24,7 +23,6 @@ DEFINE_FLAG(bool,
|
| // Quick access to the current zone.
|
| #define Z (zone())
|
|
|
| -
|
| class CSEInstructionMap : public ValueObject {
|
| public:
|
| // Right now CSE and LICM track a single effect: possible externalization of
|
| @@ -71,7 +69,6 @@ class CSEInstructionMap : public ValueObject {
|
| Map dependent_;
|
| };
|
|
|
| -
|
| // Place describes an abstract location (e.g. field) that IR can load
|
| // from or store to.
|
| //
|
| @@ -331,7 +328,6 @@ class Place : public ValueObject {
|
| RoundByteOffset(to, index_constant_));
|
| }
|
|
|
| -
|
| intptr_t id() const { return id_; }
|
|
|
| Kind kind() const { return KindBits::decode(flags_); }
|
| @@ -583,7 +579,6 @@ class Place : public ValueObject {
|
| intptr_t id_;
|
| };
|
|
|
| -
|
| class ZonePlace : public ZoneAllocated {
|
| public:
|
| explicit ZonePlace(const Place& place) : place_(place) {}
|
| @@ -594,14 +589,12 @@ class ZonePlace : public ZoneAllocated {
|
| Place place_;
|
| };
|
|
|
| -
|
| Place* Place::Wrap(Zone* zone, const Place& place, intptr_t id) {
|
| Place* wrapped = (new (zone) ZonePlace(place))->place();
|
| wrapped->id_ = id;
|
| return wrapped;
|
| }
|
|
|
| -
|
| // Correspondence between places connected through outgoing phi moves on the
|
| // edge that targets join.
|
| class PhiPlaceMoves : public ZoneAllocated {
|
| @@ -647,7 +640,6 @@ class PhiPlaceMoves : public ZoneAllocated {
|
| GrowableArray<ZoneGrowableArray<Move>*> moves_;
|
| };
|
|
|
| -
|
| // A map from aliases to a set of places sharing the alias. Additionally
|
| // carries a set of places that can be aliased by side-effects, essentially
|
| // those that are affected by calls.
|
| @@ -1136,7 +1128,6 @@ class AliasedSet : public ZoneAllocated {
|
| GrowableArray<Definition*> identity_rollback_;
|
| };
|
|
|
| -
|
| static Definition* GetStoredValue(Instruction* instr) {
|
| if (instr->IsStoreIndexed()) {
|
| return instr->AsStoreIndexed()->value()->definition();
|
| @@ -1156,14 +1147,12 @@ static Definition* GetStoredValue(Instruction* instr) {
|
| return NULL;
|
| }
|
|
|
| -
|
| static bool IsPhiDependentPlace(Place* place) {
|
| return ((place->kind() == Place::kField) ||
|
| (place->kind() == Place::kVMField)) &&
|
| (place->instance() != NULL) && place->instance()->IsPhi();
|
| }
|
|
|
| -
|
| // For each place that depends on a phi ensure that equivalent places
|
| // corresponding to phi input are numbered and record outgoing phi moves
|
| // for each block which establish correspondence between phi dependent place
|
| @@ -1209,10 +1198,8 @@ static PhiPlaceMoves* ComputePhiMoves(
|
| return phi_moves;
|
| }
|
|
|
| -
|
| enum CSEMode { kOptimizeLoads, kOptimizeStores };
|
|
|
| -
|
| static AliasedSet* NumberPlaces(
|
| FlowGraph* graph,
|
| DirectChainedHashMap<PointerKeyValueTrait<Place> >* map,
|
| @@ -1265,14 +1252,12 @@ static AliasedSet* NumberPlaces(
|
| return new (zone) AliasedSet(zone, map, places, phi_moves);
|
| }
|
|
|
| -
|
| // Load instructions handled by load elimination.
|
| static bool IsLoadEliminationCandidate(Instruction* instr) {
|
| return instr->IsLoadField() || instr->IsLoadIndexed() ||
|
| instr->IsLoadStaticField();
|
| }
|
|
|
| -
|
| static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets,
|
| intptr_t loop_header_index,
|
| Instruction* instr) {
|
| @@ -1281,12 +1266,10 @@ static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets,
|
| (*sets)[loop_header_index]->Contains(instr->place_id());
|
| }
|
|
|
| -
|
| LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) {
|
| ASSERT(flow_graph->is_licm_allowed());
|
| }
|
|
|
| -
|
| void LICM::Hoist(ForwardInstructionIterator* it,
|
| BlockEntryInstr* pre_header,
|
| Instruction* current) {
|
| @@ -1319,7 +1302,6 @@ void LICM::Hoist(ForwardInstructionIterator* it,
|
| current->CopyDeoptIdFrom(*last);
|
| }
|
|
|
| -
|
| void LICM::TrySpecializeSmiPhi(PhiInstr* phi,
|
| BlockEntryInstr* header,
|
| BlockEntryInstr* pre_header) {
|
| @@ -1369,7 +1351,6 @@ void LICM::TrySpecializeSmiPhi(PhiInstr* phi,
|
| phi->UpdateType(CompileType::FromCid(kSmiCid));
|
| }
|
|
|
| -
|
| void LICM::OptimisticallySpecializeSmiPhis() {
|
| if (!flow_graph()->function().allows_hoisting_check_class() ||
|
| FLAG_precompiled_mode) {
|
| @@ -1394,7 +1375,6 @@ void LICM::OptimisticallySpecializeSmiPhis() {
|
| }
|
| }
|
|
|
| -
|
| void LICM::Optimize() {
|
| if (!flow_graph()->function().allows_hoisting_check_class()) {
|
| // Do not hoist any.
|
| @@ -1443,7 +1423,6 @@ void LICM::Optimize() {
|
| }
|
| }
|
|
|
| -
|
| class LoadOptimizer : public ValueObject {
|
| public:
|
| LoadOptimizer(FlowGraph* graph, AliasedSet* aliased_set)
|
| @@ -1839,7 +1818,6 @@ class LoadOptimizer : public ValueObject {
|
| ZoneGrowableArray<Definition*>* block_out_values =
|
| out_values_[preorder_number];
|
|
|
| -
|
| // If OUT set has changed then we have new values available out of
|
| // the block. Compute these values creating phi where necessary.
|
| for (BitVector::Iterator it(out_[preorder_number]); !it.Done();
|
| @@ -2352,14 +2330,12 @@ class LoadOptimizer : public ValueObject {
|
| GrowableArray<Definition*> congruency_worklist_;
|
| BitVector* in_worklist_;
|
|
|
| -
|
| // True if any load was eliminated.
|
| bool forwarded_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(LoadOptimizer);
|
| };
|
|
|
| -
|
| bool DominatorBasedCSE::Optimize(FlowGraph* graph) {
|
| bool changed = false;
|
| if (FLAG_load_cse) {
|
| @@ -2372,7 +2348,6 @@ bool DominatorBasedCSE::Optimize(FlowGraph* graph) {
|
| return changed;
|
| }
|
|
|
| -
|
| bool DominatorBasedCSE::OptimizeRecursive(FlowGraph* graph,
|
| BlockEntryInstr* block,
|
| CSEInstructionMap* map) {
|
| @@ -2419,7 +2394,6 @@ bool DominatorBasedCSE::OptimizeRecursive(FlowGraph* graph,
|
| return changed;
|
| }
|
|
|
| -
|
| class StoreOptimizer : public LivenessAnalysis {
|
| public:
|
| StoreOptimizer(FlowGraph* graph,
|
| @@ -2626,14 +2600,12 @@ class StoreOptimizer : public LivenessAnalysis {
|
| DISALLOW_COPY_AND_ASSIGN(StoreOptimizer);
|
| };
|
|
|
| -
|
| void DeadStoreElimination::Optimize(FlowGraph* graph) {
|
| if (FLAG_dead_store_elimination) {
|
| StoreOptimizer::OptimizeGraph(graph);
|
| }
|
| }
|
|
|
| -
|
| enum SafeUseCheck { kOptimisticCheck, kStrictCheck };
|
|
|
| // Check if the use is safe for allocation sinking. Allocation sinking
|
| @@ -2675,7 +2647,6 @@ static bool IsSafeUse(Value* use, SafeUseCheck check_type) {
|
| return false;
|
| }
|
|
|
| -
|
| // Right now we are attempting to sink allocation only into
|
| // deoptimization exit. So candidate should only be used in StoreInstanceField
|
| // instructions that write into fields of the allocated object.
|
| @@ -2696,7 +2667,6 @@ static bool IsAllocationSinkingCandidate(Definition* alloc,
|
| return true;
|
| }
|
|
|
| -
|
| // If the given use is a store into an object then return an object we are
|
| // storing into.
|
| static Definition* StoreInto(Value* use) {
|
| @@ -2708,7 +2678,6 @@ static Definition* StoreInto(Value* use) {
|
| return NULL;
|
| }
|
|
|
| -
|
| // Remove the given allocation from the graph. It is not observable.
|
| // If deoptimization occurs the object will be materialized.
|
| void AllocationSinking::EliminateAllocation(Definition* alloc) {
|
| @@ -2743,7 +2712,6 @@ void AllocationSinking::EliminateAllocation(Definition* alloc) {
|
| }
|
| }
|
|
|
| -
|
| // Find allocation instructions that can be potentially eliminated and
|
| // rematerialized at deoptimization exits if needed. See IsSafeUse
|
| // for the description of algorithm used below.
|
| @@ -2807,7 +2775,6 @@ void AllocationSinking::CollectCandidates() {
|
| candidates_.TruncateTo(j);
|
| }
|
|
|
| -
|
| // If materialization references an allocation sinking candidate then replace
|
| // this reference with a materialization which should have been computed for
|
| // this side-exit. CollectAllExits should have collected this exit.
|
| @@ -2825,7 +2792,6 @@ void AllocationSinking::NormalizeMaterializations() {
|
| }
|
| }
|
|
|
| -
|
| // We transitively insert materializations at each deoptimization exit that
|
| // might see the given allocation (see ExitsCollector). Some of this
|
| // materializations are not actually used and some fail to compute because
|
| @@ -2859,7 +2825,6 @@ void AllocationSinking::RemoveUnusedMaterializations() {
|
| materializations_.TruncateTo(j);
|
| }
|
|
|
| -
|
| // Some candidates might stop being eligible for allocation sinking after
|
| // the load forwarding because they flow into phis that load forwarding
|
| // inserts. Discover such allocations and remove them from the list
|
| @@ -2945,7 +2910,6 @@ void AllocationSinking::DiscoverFailedCandidates() {
|
| candidates_.TruncateTo(j);
|
| }
|
|
|
| -
|
| void AllocationSinking::Optimize() {
|
| CollectCandidates();
|
|
|
| @@ -2998,7 +2962,6 @@ void AllocationSinking::Optimize() {
|
| }
|
| }
|
|
|
| -
|
| // Remove materializations from the graph. Register allocator will treat them
|
| // as part of the environment not as a real instruction.
|
| void AllocationSinking::DetachMaterializations() {
|
| @@ -3007,7 +2970,6 @@ void AllocationSinking::DetachMaterializations() {
|
| }
|
| }
|
|
|
| -
|
| // Add a field/offset to the list of fields if it is not yet present there.
|
| static bool AddSlot(ZoneGrowableArray<const Object*>* slots,
|
| const Object& slot) {
|
| @@ -3022,7 +2984,6 @@ static bool AddSlot(ZoneGrowableArray<const Object*>* slots,
|
| return true;
|
| }
|
|
|
| -
|
| // Find deoptimization exit for the given materialization assuming that all
|
| // materializations are emitted right before the instruction which is a
|
| // deoptimization exit.
|
| @@ -3033,7 +2994,6 @@ static Instruction* ExitForMaterialization(MaterializeObjectInstr* mat) {
|
| return mat->next();
|
| }
|
|
|
| -
|
| // Given the deoptimization exit find first materialization that was inserted
|
| // before it.
|
| static Instruction* FirstMaterializationAt(Instruction* exit) {
|
| @@ -3043,7 +3003,6 @@ static Instruction* FirstMaterializationAt(Instruction* exit) {
|
| return exit;
|
| }
|
|
|
| -
|
| // Given the allocation and deoptimization exit try to find MaterializeObject
|
| // instruction corresponding to this allocation at this exit.
|
| MaterializeObjectInstr* AllocationSinking::MaterializationFor(
|
| @@ -3063,7 +3022,6 @@ MaterializeObjectInstr* AllocationSinking::MaterializationFor(
|
| return NULL;
|
| }
|
|
|
| -
|
| // Insert MaterializeObject instruction for the given allocation before
|
| // the given instruction that can deoptimize.
|
| void AllocationSinking::CreateMaterializationAt(
|
| @@ -3129,7 +3087,6 @@ void AllocationSinking::CreateMaterializationAt(
|
| materializations_.Add(mat);
|
| }
|
|
|
| -
|
| // Add given instruction to the list of the instructions if it is not yet
|
| // present there.
|
| template <typename T>
|
| @@ -3143,7 +3100,6 @@ void AddInstruction(GrowableArray<T*>* list, T* value) {
|
| list->Add(value);
|
| }
|
|
|
| -
|
| // Transitively collect all deoptimization exits that might need this allocation
|
| // rematerialized. It is not enough to collect only environment uses of this
|
| // allocation because it can flow into other objects that will be
|
| @@ -3172,7 +3128,6 @@ void AllocationSinking::ExitsCollector::Collect(Definition* alloc) {
|
| }
|
| }
|
|
|
| -
|
| void AllocationSinking::ExitsCollector::CollectTransitively(Definition* alloc) {
|
| exits_.TruncateTo(0);
|
| worklist_.TruncateTo(0);
|
| @@ -3189,7 +3144,6 @@ void AllocationSinking::ExitsCollector::CollectTransitively(Definition* alloc) {
|
| }
|
| }
|
|
|
| -
|
| void AllocationSinking::InsertMaterializations(Definition* alloc) {
|
| // Collect all fields that are written for this instance.
|
| ZoneGrowableArray<const Object*>* slots =
|
| @@ -3224,7 +3178,6 @@ void AllocationSinking::InsertMaterializations(Definition* alloc) {
|
| }
|
| }
|
|
|
| -
|
| void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) {
|
| // For every catch-block: Iterate over all call instructions inside the
|
| // corresponding try-block and figure out for each environment value if it
|
| @@ -3297,7 +3250,6 @@ void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) {
|
| }
|
| }
|
|
|
| -
|
| // Returns true iff this definition is used in a non-phi instruction.
|
| static bool HasRealUse(Definition* def) {
|
| // Environment uses are real (non-phi) uses.
|
| @@ -3309,7 +3261,6 @@ static bool HasRealUse(Definition* def) {
|
| return false;
|
| }
|
|
|
| -
|
| void DeadCodeElimination::EliminateDeadPhis(FlowGraph* flow_graph) {
|
| GrowableArray<PhiInstr*> live_phis;
|
| for (BlockIterator b = flow_graph->postorder_iterator(); !b.Done();
|
| @@ -3382,5 +3333,4 @@ void DeadCodeElimination::EliminateDeadPhis(FlowGraph* flow_graph) {
|
| }
|
| }
|
|
|
| -
|
| } // namespace dart
|
|
|