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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
8 String get name; | 8 String get name; |
9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
10 } | 10 } |
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 // to the worklist. | 1146 // to the worklist. |
1147 for (final user in phi.usedBy) { | 1147 for (final user in phi.usedBy) { |
1148 if (user is HPhi) worklist.add(user); | 1148 if (user is HPhi) worklist.add(user); |
1149 } | 1149 } |
1150 phi.block.rewrite(phi, candidate); | 1150 phi.block.rewrite(phi, candidate); |
1151 phi.block.removePhi(phi); | 1151 phi.block.removePhi(phi); |
1152 } | 1152 } |
1153 } | 1153 } |
1154 } | 1154 } |
1155 | 1155 |
| 1156 class GvnWorkItem { |
| 1157 final HBasicBlock block; |
| 1158 final ValueSet valueSet; |
| 1159 GvnWorkItem(this.block, this.valueSet); |
| 1160 } |
| 1161 |
1156 class SsaGlobalValueNumberer implements OptimizationPhase { | 1162 class SsaGlobalValueNumberer implements OptimizationPhase { |
1157 final String name = "SsaGlobalValueNumberer"; | 1163 final String name = "SsaGlobalValueNumberer"; |
1158 final Compiler compiler; | 1164 final Compiler compiler; |
1159 final Set<int> visited; | 1165 final Set<int> visited; |
1160 | 1166 |
1161 List<int> blockChangesFlags; | 1167 List<int> blockChangesFlags; |
1162 List<int> loopChangesFlags; | 1168 List<int> loopChangesFlags; |
1163 | 1169 |
1164 SsaGlobalValueNumberer(this.compiler) : visited = new Set<int>(); | 1170 SsaGlobalValueNumberer(this.compiler) : visited = new Set<int>(); |
1165 | 1171 |
1166 void visitGraph(HGraph graph) { | 1172 void visitGraph(HGraph graph) { |
1167 computeChangesFlags(graph); | 1173 computeChangesFlags(graph); |
1168 moveLoopInvariantCode(graph); | 1174 moveLoopInvariantCode(graph); |
1169 visitBasicBlock(graph.entry, new ValueSet()); | 1175 List<GvnWorkItem> workQueue = |
| 1176 <GvnWorkItem>[new GvnWorkItem(graph.entry, new ValueSet())]; |
| 1177 do { |
| 1178 GvnWorkItem item = workQueue.removeLast(); |
| 1179 visitBasicBlock(item.block, item.valueSet, workQueue); |
| 1180 } while (!workQueue.isEmpty); |
1170 } | 1181 } |
1171 | 1182 |
1172 void moveLoopInvariantCode(HGraph graph) { | 1183 void moveLoopInvariantCode(HGraph graph) { |
1173 for (int i = graph.blocks.length - 1; i >= 0; i--) { | 1184 for (int i = graph.blocks.length - 1; i >= 0; i--) { |
1174 HBasicBlock block = graph.blocks[i]; | 1185 HBasicBlock block = graph.blocks[i]; |
1175 if (block.isLoopHeader()) { | 1186 if (block.isLoopHeader()) { |
1176 int changesFlags = loopChangesFlags[block.id]; | 1187 int changesFlags = loopChangesFlags[block.id]; |
1177 HLoopInformation info = block.loopInformation; | 1188 HLoopInformation info = block.loopInformation; |
1178 // Iterate over all blocks of this loop. Note that blocks in | 1189 // Iterate over all blocks of this loop. Note that blocks in |
1179 // inner loops are not visited here, but we know they | 1190 // inner loops are not visited here, but we know they |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 } | 1247 } |
1237 instruction = next; | 1248 instruction = next; |
1238 } | 1249 } |
1239 } | 1250 } |
1240 | 1251 |
1241 bool isInputDefinedAfterDominator(HInstruction input, | 1252 bool isInputDefinedAfterDominator(HInstruction input, |
1242 HBasicBlock dominator) { | 1253 HBasicBlock dominator) { |
1243 return input.block.id > dominator.id; | 1254 return input.block.id > dominator.id; |
1244 } | 1255 } |
1245 | 1256 |
1246 void visitBasicBlock(HBasicBlock block, ValueSet values) { | 1257 void visitBasicBlock( |
| 1258 HBasicBlock block, ValueSet values, List<GvnWorkItem> workQueue) { |
1247 HInstruction instruction = block.first; | 1259 HInstruction instruction = block.first; |
1248 if (block.isLoopHeader()) { | 1260 if (block.isLoopHeader()) { |
1249 int flags = loopChangesFlags[block.id]; | 1261 int flags = loopChangesFlags[block.id]; |
1250 values.kill(flags); | 1262 values.kill(flags); |
1251 } | 1263 } |
1252 while (instruction != null) { | 1264 while (instruction != null) { |
1253 HInstruction next = instruction.next; | 1265 HInstruction next = instruction.next; |
1254 int flags = instruction.sideEffects.getChangesFlags(); | 1266 int flags = instruction.sideEffects.getChangesFlags(); |
1255 assert(flags == 0 || !instruction.useGvn()); | 1267 assert(flags == 0 || !instruction.useGvn()); |
1256 values.kill(flags); | 1268 values.kill(flags); |
(...skipping 16 matching lines...) Expand all Loading... |
1273 // No need to copy the value set for the last child. | 1285 // No need to copy the value set for the last child. |
1274 ValueSet successorValues = (i == length - 1) ? values : values.copy(); | 1286 ValueSet successorValues = (i == length - 1) ? values : values.copy(); |
1275 // If we have no values in our set, we do not have to kill | 1287 // If we have no values in our set, we do not have to kill |
1276 // anything. Also, if the range of block ids from the current | 1288 // anything. Also, if the range of block ids from the current |
1277 // block to the dominated block is empty, there is no blocks on | 1289 // block to the dominated block is empty, there is no blocks on |
1278 // any path from the current block to the dominated block so we | 1290 // any path from the current block to the dominated block so we |
1279 // don't have to do anything either. | 1291 // don't have to do anything either. |
1280 assert(block.id < dominated.id); | 1292 assert(block.id < dominated.id); |
1281 if (!successorValues.isEmpty && block.id + 1 < dominated.id) { | 1293 if (!successorValues.isEmpty && block.id + 1 < dominated.id) { |
1282 visited.clear(); | 1294 visited.clear(); |
1283 int changesFlags = getChangesFlagsForDominatedBlock(block, dominated); | 1295 List<HBasicBlock> workQueue = <HBasicBlock>[dominated]; |
| 1296 int changesFlags = 0; |
| 1297 do { |
| 1298 HBasicBlock current = workQueue.removeLast(); |
| 1299 changesFlags |= |
| 1300 getChangesFlagsForDominatedBlock(block, current, workQueue); |
| 1301 } while (!workQueue.isEmpty); |
1284 successorValues.kill(changesFlags); | 1302 successorValues.kill(changesFlags); |
1285 } | 1303 } |
1286 visitBasicBlock(dominated, successorValues); | 1304 workQueue.add(new GvnWorkItem(dominated, successorValues)); |
1287 } | 1305 } |
1288 } | 1306 } |
1289 | 1307 |
1290 void computeChangesFlags(HGraph graph) { | 1308 void computeChangesFlags(HGraph graph) { |
1291 // Create the changes flags lists. Make sure to initialize the | 1309 // Create the changes flags lists. Make sure to initialize the |
1292 // loop changes flags list to zero so we can use bitwise or when | 1310 // loop changes flags list to zero so we can use bitwise or when |
1293 // propagating loop changes upwards. | 1311 // propagating loop changes upwards. |
1294 final int length = graph.blocks.length; | 1312 final int length = graph.blocks.length; |
1295 blockChangesFlags = new List<int>(length); | 1313 blockChangesFlags = new List<int>(length); |
1296 loopChangesFlags = new List<int>(length); | 1314 loopChangesFlags = new List<int>(length); |
(...skipping 25 matching lines...) Expand all Loading... |
1322 HBasicBlock parentLoopHeader = block.parentLoopHeader; | 1340 HBasicBlock parentLoopHeader = block.parentLoopHeader; |
1323 if (parentLoopHeader != null) { | 1341 if (parentLoopHeader != null) { |
1324 loopChangesFlags[parentLoopHeader.id] |= (block.isLoopHeader()) | 1342 loopChangesFlags[parentLoopHeader.id] |= (block.isLoopHeader()) |
1325 ? loopChangesFlags[id] | 1343 ? loopChangesFlags[id] |
1326 : changesFlags; | 1344 : changesFlags; |
1327 } | 1345 } |
1328 } | 1346 } |
1329 } | 1347 } |
1330 | 1348 |
1331 int getChangesFlagsForDominatedBlock(HBasicBlock dominator, | 1349 int getChangesFlagsForDominatedBlock(HBasicBlock dominator, |
1332 HBasicBlock dominated) { | 1350 HBasicBlock dominated, |
| 1351 List<HBasicBlock> workQueue) { |
1333 int changesFlags = 0; | 1352 int changesFlags = 0; |
1334 List<HBasicBlock> predecessors = dominated.predecessors; | 1353 List<HBasicBlock> predecessors = dominated.predecessors; |
1335 for (int i = 0, length = predecessors.length; i < length; i++) { | 1354 for (int i = 0, length = predecessors.length; i < length; i++) { |
1336 HBasicBlock block = predecessors[i]; | 1355 HBasicBlock block = predecessors[i]; |
1337 int id = block.id; | 1356 int id = block.id; |
1338 // If the current predecessor block is on the path from the | 1357 // If the current predecessor block is on the path from the |
1339 // dominator to the dominated, it must have an id that is in the | 1358 // dominator to the dominated, it must have an id that is in the |
1340 // range from the dominator to the dominated. | 1359 // range from the dominator to the dominated. |
1341 if (dominator.id < id && id < dominated.id && !visited.contains(id)) { | 1360 if (dominator.id < id && id < dominated.id && !visited.contains(id)) { |
1342 visited.add(id); | 1361 visited.add(id); |
1343 changesFlags |= blockChangesFlags[id]; | 1362 changesFlags |= blockChangesFlags[id]; |
1344 // Loop bodies might not be on the path from dominator to dominated, | 1363 // Loop bodies might not be on the path from dominator to dominated, |
1345 // but they can invalidate values. | 1364 // but they can invalidate values. |
1346 changesFlags |= loopChangesFlags[id]; | 1365 changesFlags |= loopChangesFlags[id]; |
1347 changesFlags |= getChangesFlagsForDominatedBlock(dominator, block); | 1366 workQueue.add(block); |
1348 } | 1367 } |
1349 } | 1368 } |
1350 return changesFlags; | 1369 return changesFlags; |
1351 } | 1370 } |
1352 } | 1371 } |
1353 | 1372 |
1354 // This phase merges equivalent instructions on different paths into | 1373 // This phase merges equivalent instructions on different paths into |
1355 // one instruction in a dominator block. It runs through the graph | 1374 // one instruction in a dominator block. It runs through the graph |
1356 // post dominator order and computes a ValueSet for each block of | 1375 // post dominator order and computes a ValueSet for each block of |
1357 // instructions that can be moved to a dominator block. These | 1376 // instructions that can be moved to a dominator block. These |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 // that knows it is not of a specific Type. | 1523 // that knows it is not of a specific Type. |
1505 } | 1524 } |
1506 | 1525 |
1507 for (HIf ifUser in notIfUsers) { | 1526 for (HIf ifUser in notIfUsers) { |
1508 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); | 1527 changeUsesDominatedBy(ifUser.elseBlock, input, convertedType); |
1509 // TODO(ngeoffray): Also change uses for the then block on a HType | 1528 // TODO(ngeoffray): Also change uses for the then block on a HType |
1510 // that knows it is not of a specific Type. | 1529 // that knows it is not of a specific Type. |
1511 } | 1530 } |
1512 } | 1531 } |
1513 } | 1532 } |
OLD | NEW |