| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/hash_map.h" | 10 #include "vm/hash_map.h" |
| (...skipping 1139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { | 1150 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { |
| 1151 BlockEntryInstr* candidate = header->PredecessorAt(j); | 1151 BlockEntryInstr* candidate = header->PredecessorAt(j); |
| 1152 if (header->dominator() == candidate) { | 1152 if (header->dominator() == candidate) { |
| 1153 return candidate; | 1153 return candidate; |
| 1154 } | 1154 } |
| 1155 } | 1155 } |
| 1156 return NULL; | 1156 return NULL; |
| 1157 } | 1157 } |
| 1158 | 1158 |
| 1159 | 1159 |
| 1160 void LICM::Hoist(ForwardInstructionIterator* it, |
| 1161 BlockEntryInstr* pre_header, |
| 1162 Definition* current) { |
| 1163 // TODO(fschneider): Avoid repeated deoptimization when |
| 1164 // speculatively hoisting checks. |
| 1165 if (FLAG_trace_optimization) { |
| 1166 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", |
| 1167 current->DebugName(), |
| 1168 current->deopt_id(), |
| 1169 current->GetBlock()->block_id(), |
| 1170 pre_header->block_id()); |
| 1171 } |
| 1172 // Move the instruction out of the loop. |
| 1173 it->RemoveCurrentFromGraph(); |
| 1174 GotoInstr* last = pre_header->last_instruction()->AsGoto(); |
| 1175 current->InsertBefore(last); |
| 1176 // Attach the environment of the Goto instruction to the hoisted |
| 1177 // instruction and set the correct deopt_id. |
| 1178 ASSERT(last->env() != NULL); |
| 1179 last->env()->CopyTo(current); |
| 1180 current->deopt_id_ = last->GetDeoptId(); |
| 1181 } |
| 1182 |
| 1183 |
| 1184 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, |
| 1185 BlockEntryInstr* header, |
| 1186 BlockEntryInstr* pre_header, |
| 1187 Definition* current) { |
| 1188 PhiInstr* phi = current->InputAt(0)->definition()->AsPhi(); |
| 1189 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { |
| 1190 return; |
| 1191 } |
| 1192 |
| 1193 if (phi->GetPropagatedCid() == kSmiCid) { |
| 1194 it->RemoveCurrentFromGraph(); |
| 1195 return; |
| 1196 } |
| 1197 |
| 1198 // Check if there is only a single kDynamicCid input to the phi that |
| 1199 // comes from the pre-header. |
| 1200 const intptr_t kNotFound = -1; |
| 1201 intptr_t non_smi_input = kNotFound; |
| 1202 for (intptr_t i = 0; i < phi->InputCount(); ++i) { |
| 1203 Value* input = phi->InputAt(i); |
| 1204 if (input->ResultCid() != kSmiCid) { |
| 1205 if ((non_smi_input != kNotFound) || (input->ResultCid() != kDynamicCid)) { |
| 1206 // There are multiple kDynamicCid inputs or there is an input that is |
| 1207 // known to be non-smi. |
| 1208 return; |
| 1209 } else { |
| 1210 non_smi_input = i; |
| 1211 } |
| 1212 } |
| 1213 } |
| 1214 |
| 1215 if ((non_smi_input == kNotFound) || |
| 1216 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { |
| 1217 return; |
| 1218 } |
| 1219 |
| 1220 // Host CheckSmi instruction and make this phi smi one. |
| 1221 Hoist(it, pre_header, current); |
| 1222 current->SetInputAt(non_smi_input, phi->InputAt(non_smi_input)); |
| 1223 phi->SetPropagatedCid(kSmiCid); |
| 1224 } |
| 1225 |
| 1226 |
| 1160 void LICM::Optimize(FlowGraph* flow_graph) { | 1227 void LICM::Optimize(FlowGraph* flow_graph) { |
| 1161 GrowableArray<BlockEntryInstr*> loop_headers; | 1228 GrowableArray<BlockEntryInstr*> loop_headers; |
| 1162 flow_graph->ComputeLoops(&loop_headers); | 1229 flow_graph->ComputeLoops(&loop_headers); |
| 1163 | 1230 |
| 1164 for (intptr_t i = 0; i < loop_headers.length(); ++i) { | 1231 for (intptr_t i = 0; i < loop_headers.length(); ++i) { |
| 1165 BlockEntryInstr* header = loop_headers[i]; | 1232 BlockEntryInstr* header = loop_headers[i]; |
| 1166 // Skip loop that don't have a pre-header block. | 1233 // Skip loop that don't have a pre-header block. |
| 1167 BlockEntryInstr* pre_header = FindPreHeader(header); | 1234 BlockEntryInstr* pre_header = FindPreHeader(header); |
| 1168 if (pre_header == NULL) continue; | 1235 if (pre_header == NULL) continue; |
| 1169 | 1236 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1180 !current->HasSideEffect()) { | 1247 !current->HasSideEffect()) { |
| 1181 bool inputs_loop_invariant = true; | 1248 bool inputs_loop_invariant = true; |
| 1182 for (int i = 0; i < current->InputCount(); ++i) { | 1249 for (int i = 0; i < current->InputCount(); ++i) { |
| 1183 Definition* input_def = current->InputAt(i)->definition(); | 1250 Definition* input_def = current->InputAt(i)->definition(); |
| 1184 if (!input_def->GetBlock()->Dominates(pre_header)) { | 1251 if (!input_def->GetBlock()->Dominates(pre_header)) { |
| 1185 inputs_loop_invariant = false; | 1252 inputs_loop_invariant = false; |
| 1186 break; | 1253 break; |
| 1187 } | 1254 } |
| 1188 } | 1255 } |
| 1189 if (inputs_loop_invariant) { | 1256 if (inputs_loop_invariant) { |
| 1190 // TODO(fschneider): Avoid repeated deoptimization when | 1257 Hoist(&it, pre_header, current); |
| 1191 // speculatively hoisting checks. | 1258 } else if (current->IsCheckSmi() && |
| 1192 if (FLAG_trace_optimization) { | 1259 current->InputAt(0)->definition()->IsPhi()) { |
| 1193 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", | 1260 TryHoistCheckSmiThroughPhi(&it, header, pre_header, current); |
| 1194 current->DebugName(), | |
| 1195 current->deopt_id(), | |
| 1196 current->GetBlock()->block_id(), | |
| 1197 pre_header->block_id()); | |
| 1198 } | |
| 1199 // Move the instruction out of the loop. | |
| 1200 it.RemoveCurrentFromGraph(); | |
| 1201 GotoInstr* last = pre_header->last_instruction()->AsGoto(); | |
| 1202 current->InsertBefore(last); | |
| 1203 // Attach the environment of the Goto instruction to the hoisted | |
| 1204 // instruction and set the correct deopt_id. | |
| 1205 ASSERT(last->env() != NULL); | |
| 1206 last->env()->CopyTo(current); | |
| 1207 current->deopt_id_ = last->GetDeoptId(); | |
| 1208 } | 1261 } |
| 1209 } | 1262 } |
| 1210 } | 1263 } |
| 1211 } | 1264 } |
| 1212 } | 1265 } |
| 1213 } | 1266 } |
| 1214 | 1267 |
| 1215 | 1268 |
| 1216 void DominatorBasedCSE::Optimize(BlockEntryInstr* graph_entry) { | 1269 void DominatorBasedCSE::Optimize(BlockEntryInstr* graph_entry) { |
| 1217 ASSERT(graph_entry->IsGraphEntry()); | 1270 ASSERT(graph_entry->IsGraphEntry()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. | 1302 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. |
| 1250 OptimizeRecursive(child, &child_map); | 1303 OptimizeRecursive(child, &child_map); |
| 1251 } else { | 1304 } else { |
| 1252 OptimizeRecursive(child, map); // Reuse map for the last child. | 1305 OptimizeRecursive(child, map); // Reuse map for the last child. |
| 1253 } | 1306 } |
| 1254 } | 1307 } |
| 1255 } | 1308 } |
| 1256 | 1309 |
| 1257 | 1310 |
| 1258 } // namespace dart | 1311 } // namespace dart |
| OLD | NEW |