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

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

Issue 10916155: Optimistically hoist SmiCheck through phi when the only value of unknown type coming into the phi i… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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_optimizer.h ('k') | 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) 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
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,
Florian Schneider 2012/09/07 09:37:00 You could make this a static top-level functions:
Vyacheslav Egorov (Google) 2012/09/07 12:06:00 Unfortunately I can't: it uses friendship relation
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();
srdjan 2012/09/07 07:55:26 Could you add tests that have deoptimization cause
Vyacheslav Egorov (Google) 2012/09/07 12:06:00 Done.
1181 }
1182
1183
1184 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
Florian Schneider 2012/09/07 09:37:00 You could make this a static top-level functions:
Vyacheslav Egorov (Google) 2012/09/07 12:06:00 See above.
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) {
Florian Schneider 2012/09/07 09:37:00 It should not be necessary to check for redundant
Vyacheslav Egorov (Google) 2012/09/07 12:06:00 There are might be smi checks that are not dominat
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)) {
Florian Schneider 2012/09/07 09:37:00 It's fine to have the restrict the block where the
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);
srdjan 2012/09/07 07:55:26 Could/should we run type propagation after LICM ag
Florian Schneider 2012/09/07 09:37:00 Yes, how about building worklist of changed phis
Vyacheslav Egorov (Google) 2012/09/07 12:06:00 Yes, we can. For now I would like to keep it minim
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698