| OLD | NEW |
| 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 4053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4064 GrowableArray<PhiInstr*> redundant_phis(10); | 4064 GrowableArray<PhiInstr*> redundant_phis(10); |
| 4065 | 4065 |
| 4066 // We will recompute dominators, block ordering, block ids, block last | 4066 // We will recompute dominators, block ordering, block ids, block last |
| 4067 // instructions, previous pointers, predecessors, etc. after eliminating | 4067 // instructions, previous pointers, predecessors, etc. after eliminating |
| 4068 // unreachable code. We do not maintain those properties during the | 4068 // unreachable code. We do not maintain those properties during the |
| 4069 // transformation. | 4069 // transformation. |
| 4070 for (BlockIterator b = graph_->reverse_postorder_iterator(); | 4070 for (BlockIterator b = graph_->reverse_postorder_iterator(); |
| 4071 !b.Done(); | 4071 !b.Done(); |
| 4072 b.Advance()) { | 4072 b.Advance()) { |
| 4073 BlockEntryInstr* block = b.Current(); | 4073 BlockEntryInstr* block = b.Current(); |
| 4074 JoinEntryInstr* join = block->AsJoinEntry(); | |
| 4075 if (!reachable_->Contains(block->preorder_number())) { | 4074 if (!reachable_->Contains(block->preorder_number())) { |
| 4076 if (FLAG_trace_constant_propagation) { | 4075 if (FLAG_trace_constant_propagation) { |
| 4077 OS::Print("Unreachable B%"Pd"\n", block->block_id()); | 4076 OS::Print("Unreachable B%"Pd"\n", block->block_id()); |
| 4078 } | 4077 } |
| 4079 // Remove all uses in unreachable blocks. | |
| 4080 if (join != NULL) { | |
| 4081 for (PhiIterator it(join); !it.Done(); it.Advance()) { | |
| 4082 it.Current()->UnuseAllInputs(); | |
| 4083 } | |
| 4084 } | |
| 4085 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
| 4086 it.Current()->UnuseAllInputs(); | |
| 4087 } | |
| 4088 continue; | 4078 continue; |
| 4089 } | 4079 } |
| 4090 | 4080 |
| 4081 JoinEntryInstr* join = block->AsJoinEntry(); |
| 4091 if (join != NULL) { | 4082 if (join != NULL) { |
| 4092 // Remove phi inputs corresponding to unreachable predecessor blocks. | 4083 // Remove phi inputs corresponding to unreachable predecessor blocks. |
| 4093 // Predecessors will be recomputed (in block id order) after removing | 4084 // Predecessors will be recomputed (in block id order) after removing |
| 4094 // unreachable code so we merely have to keep the phi inputs in order. | 4085 // unreachable code so we merely have to keep the phi inputs in order. |
| 4095 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); | 4086 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); |
| 4096 if (phis != NULL) { | 4087 if (phis != NULL) { |
| 4097 intptr_t pred_count = join->PredecessorCount(); | 4088 intptr_t pred_count = join->PredecessorCount(); |
| 4098 intptr_t live_count = 0; | 4089 intptr_t live_count = 0; |
| 4099 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { | 4090 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { |
| 4100 if (reachable_->Contains( | 4091 if (reachable_->Contains( |
| 4101 join->PredecessorAt(pred_idx)->preorder_number())) { | 4092 join->PredecessorAt(pred_idx)->preorder_number())) { |
| 4102 if (live_count < pred_idx) { | 4093 if (live_count < pred_idx) { |
| 4103 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { | 4094 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { |
| 4104 PhiInstr* phi = (*phis)[phi_idx]; | 4095 PhiInstr* phi = (*phis)[phi_idx]; |
| 4105 if (phi == NULL) continue; | 4096 if (phi == NULL) continue; |
| 4106 Value* input = phi->inputs_[pred_idx]; | 4097 phi->inputs_[live_count] = phi->inputs_[pred_idx]; |
| 4107 input->set_use_index(live_count); | |
| 4108 phi->inputs_[live_count] = input; | |
| 4109 } | 4098 } |
| 4110 } | 4099 } |
| 4111 ++live_count; | 4100 ++live_count; |
| 4112 } else { | |
| 4113 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { | |
| 4114 PhiInstr* phi = (*phis)[phi_idx]; | |
| 4115 if (phi == NULL) continue; | |
| 4116 phi->inputs_[pred_idx]->RemoveFromUseList(); | |
| 4117 } | |
| 4118 } | 4101 } |
| 4119 } | 4102 } |
| 4120 if (live_count < pred_count) { | 4103 if (live_count < pred_count) { |
| 4121 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { | 4104 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { |
| 4122 PhiInstr* phi = (*phis)[phi_idx]; | 4105 PhiInstr* phi = (*phis)[phi_idx]; |
| 4123 if (phi == NULL) continue; | 4106 if (phi == NULL) continue; |
| 4124 if (FLAG_remove_redundant_phis && (live_count == 1)) { | 4107 phi->inputs_.TruncateTo(live_count); |
| 4125 Value* input = phi->InputAt(0); | 4108 if (live_count == 1) redundant_phis.Add(phi); |
| 4126 phi->ReplaceUsesWith(input->definition()); | |
| 4127 input->RemoveFromUseList(); | |
| 4128 (*phis)[phi_idx] = NULL; | |
| 4129 } else { | |
| 4130 phi->inputs_.TruncateTo(live_count); | |
| 4131 } | |
| 4132 } | 4109 } |
| 4133 } | 4110 } |
| 4134 } | 4111 } |
| 4135 } | 4112 } |
| 4136 | 4113 |
| 4137 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { | 4114 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { |
| 4138 Definition* defn = i.Current()->AsDefinition(); | 4115 Definition* defn = i.Current()->AsDefinition(); |
| 4139 // Replace constant-valued instructions without observable side | 4116 // Replace constant-valued instructions without observable side |
| 4140 // effects. Do this for smis only to avoid having to copy other | 4117 // effects. Do this for smis only to avoid having to copy other |
| 4141 // objects into the heap's old generation. | 4118 // objects into the heap's old generation. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4183 // Drop the comparison, which does not have side effects as long | 4160 // Drop the comparison, which does not have side effects as long |
| 4184 // as it is a strict compare (the only one we can determine is | 4161 // as it is a strict compare (the only one we can determine is |
| 4185 // constant with the current analysis). | 4162 // constant with the current analysis). |
| 4186 GotoInstr* jump = new GotoInstr(join); | 4163 GotoInstr* jump = new GotoInstr(join); |
| 4187 Instruction* previous = branch->previous(); | 4164 Instruction* previous = branch->previous(); |
| 4188 branch->set_previous(NULL); | 4165 branch->set_previous(NULL); |
| 4189 previous->LinkTo(jump); | 4166 previous->LinkTo(jump); |
| 4190 // Replace the false target entry with the new join entry. We will | 4167 // Replace the false target entry with the new join entry. We will |
| 4191 // recompute the dominators after this pass. | 4168 // recompute the dominators after this pass. |
| 4192 join->LinkTo(next); | 4169 join->LinkTo(next); |
| 4193 branch->UnuseAllInputs(); | |
| 4194 } | 4170 } |
| 4195 } | 4171 } |
| 4196 } | 4172 } |
| 4197 | 4173 |
| 4198 graph_->DiscoverBlocks(); | 4174 graph_->DiscoverBlocks(); |
| 4199 GrowableArray<BitVector*> dominance_frontier; | 4175 GrowableArray<BitVector*> dominance_frontier; |
| 4200 graph_->ComputeDominators(&dominance_frontier); | 4176 graph_->ComputeDominators(&dominance_frontier); |
| 4177 graph_->ComputeUseLists(); |
| 4178 |
| 4179 if (FLAG_remove_redundant_phis) { |
| 4180 for (intptr_t i = 0; i < redundant_phis.length(); i++) { |
| 4181 PhiInstr* phi = redundant_phis[i]; |
| 4182 phi->ReplaceUsesWith(phi->InputAt(0)->definition()); |
| 4183 phi->mark_dead(); |
| 4184 } |
| 4185 } |
| 4201 | 4186 |
| 4202 if (FLAG_trace_constant_propagation) { | 4187 if (FLAG_trace_constant_propagation) { |
| 4203 OS::Print("\n==== After constant propagation ====\n"); | 4188 OS::Print("\n==== After constant propagation ====\n"); |
| 4204 FlowGraphPrinter printer(*graph_); | 4189 FlowGraphPrinter printer(*graph_); |
| 4205 printer.PrintBlocks(); | 4190 printer.PrintBlocks(); |
| 4206 } | 4191 } |
| 4207 } | 4192 } |
| 4208 | 4193 |
| 4209 | 4194 |
| 4210 } // namespace dart | 4195 } // namespace dart |
| OLD | NEW |