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

Side by Side Diff: pkg/compiler/lib/src/ssa/nodes.dart

Issue 2755353003: dart2js: Insert HTypeKnown refinement nodes on dominated edges of HPhi nodes. (Closed)
Patch Set: Created 3 years, 9 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
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 import '../closure.dart'; 5 import '../closure.dart';
6 import '../common.dart'; 6 import '../common.dart';
7 import '../common/backend_api.dart' show BackendClasses; 7 import '../common/backend_api.dart' show BackendClasses;
8 import '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
9 import '../constants/constant_system.dart'; 9 import '../constants/constant_system.dart';
10 import '../constants/values.dart'; 10 import '../constants/values.dart';
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 } else { 811 } else {
812 bool res = dominatesCache[other]; 812 bool res = dominatesCache[other];
813 if (res != null) return res; 813 if (res != null) return res;
814 } 814 }
815 do { 815 do {
816 if (identical(this, other)) return dominatesCache[other] = true; 816 if (identical(this, other)) return dominatesCache[other] = true;
817 other = other.dominator; 817 other = other.dominator;
818 } while (other != null && other.id >= id); 818 } while (other != null && other.id >= id);
819 return dominatesCache[other] = false; 819 return dominatesCache[other] = false;
820 } 820 }
821
822 toString() => 'HBasicBlock($id)';
821 } 823 }
822 824
823 abstract class HInstruction implements Spannable { 825 abstract class HInstruction implements Spannable {
824 Entity sourceElement; 826 Entity sourceElement;
825 SourceInformation sourceInformation; 827 SourceInformation sourceInformation;
826 828
827 final int id; 829 final int id;
828 static int idCounter; 830 static int idCounter;
829 831
830 final List<HInstruction> inputs; 832 final List<HInstruction> inputs;
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 assert(newInput != null && !identical(oldInput, newInput)); 1224 assert(newInput != null && !identical(oldInput, newInput));
1223 for (int i = 0; i < inputs.length; i++) { 1225 for (int i = 0; i < inputs.length; i++) {
1224 if (identical(inputs[i], oldInput)) { 1226 if (identical(inputs[i], oldInput)) {
1225 inputs[i] = newInput; 1227 inputs[i] = newInput;
1226 newInput.usedBy.add(this); 1228 newInput.usedBy.add(this);
1227 } 1229 }
1228 } 1230 }
1229 removeFromList(oldInput.usedBy, this); 1231 removeFromList(oldInput.usedBy, this);
1230 } 1232 }
1231 1233
1232 // Compute the set of users of this instruction that is dominated by
1233 // [other]. If [other] is a user of [this], it is included in the
1234 // returned set.
1235 Setlet<HInstruction> dominatedUsers(HInstruction other) {
1236 // Keep track of all instructions that we have to deal with later
1237 // and count the number of them that are in the current block.
1238 Setlet<HInstruction> users = new Setlet<HInstruction>();
1239 int usersInCurrentBlock = 0;
1240
1241 // Run through all the users and see if they are dominated or
1242 // potentially dominated by [other].
1243 HBasicBlock otherBlock = other.block;
1244 for (int i = 0, length = usedBy.length; i < length; i++) {
1245 HInstruction current = usedBy[i];
1246 HBasicBlock currentBlock = current.block;
1247 if (otherBlock.dominates(currentBlock)) {
1248 if (identical(currentBlock, otherBlock)) usersInCurrentBlock++;
1249 users.add(current);
1250 }
1251 }
1252
1253 // Run through all the phis in the same block as [other] and remove them
1254 // from the users set.
1255 if (usersInCurrentBlock > 0) {
1256 for (HPhi phi = otherBlock.phis.first; phi != null; phi = phi.next) {
1257 if (users.contains(phi)) {
1258 users.remove(phi);
1259 if (--usersInCurrentBlock == 0) break;
1260 }
1261 }
1262 }
1263
1264 // Run through all the instructions before [other] and remove them
1265 // from the users set.
1266 if (usersInCurrentBlock > 0) {
1267 HInstruction current = otherBlock.first;
1268 while (!identical(current, other)) {
1269 if (users.contains(current)) {
1270 users.remove(current);
1271 if (--usersInCurrentBlock == 0) break;
1272 }
1273 current = current.next;
1274 }
1275 }
1276
1277 return users;
1278 }
1279
1280 void replaceAllUsersDominatedBy( 1234 void replaceAllUsersDominatedBy(
1281 HInstruction cursor, HInstruction newInstruction) { 1235 HInstruction cursor, HInstruction newInstruction) {
1282 Setlet<HInstruction> users = dominatedUsers(cursor); 1236 DominatedUses.of(this, cursor).replaceWith(newInstruction);
1283 for (HInstruction user in users) {
1284 user.changeUse(this, newInstruction);
1285 }
1286 } 1237 }
1287 1238
1288 void moveBefore(HInstruction other) { 1239 void moveBefore(HInstruction other) {
1289 assert(this is! HControlFlow); 1240 assert(this is! HControlFlow);
1290 assert(this is! HPhi); 1241 assert(this is! HPhi);
1291 assert(other is! HPhi); 1242 assert(other is! HPhi);
1292 block.detach(this); 1243 block.detach(this);
1293 other.block.internalAddBefore(other, this); 1244 other.block.internalAddBefore(other, this);
1294 block = other.block; 1245 block = other.block;
1295 } 1246 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 1313
1363 /** 1314 /**
1364 * Return whether the instructions do not belong to a loop or 1315 * Return whether the instructions do not belong to a loop or
1365 * belong to the same loop. 1316 * belong to the same loop.
1366 */ 1317 */
1367 bool hasSameLoopHeaderAs(HInstruction other) { 1318 bool hasSameLoopHeaderAs(HInstruction other) {
1368 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; 1319 return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
1369 } 1320 }
1370 } 1321 }
1371 1322
1323 /// The set of uses of [source] that are dominated by [dominator].
1324 class DominatedUses {
1325 final HInstruction _source;
1326 final HInstruction _dominator;
1327
1328 // Two list of matching length holding (instruction, input-index) pairs for
1329 // the dominated uses.
1330 final List<HInstruction> _instructions = <HInstruction>[];
1331 final List<int> _indexes = <int>[];
1332
1333 DominatedUses._(this._source, this._dominator);
1334
1335 /// The uses of [source] that are dominated by [dominator].
1336 ///
1337 /// The uses by [dominator] are included in the result, unless
1338 /// [excludeDominator] is `true`, so `true` selects uses following
1339 /// [dominator].
1340 ///
1341 /// The uses include the in-edges of a HPhi node that corresponds to a
1342 /// dominated block. (There can be many such edges on a single phi at the exit
1343 /// of a loop with many break statements). If [excludePhiOutEdges] is `true`
1344 /// then these edge uses are not included.
1345 static of(HInstruction source, HInstruction dominator,
1346 {bool excludeDominator: false, bool excludePhiOutEdges: false}) {
1347 return new DominatedUses._(source, dominator)
1348 .._compute(source, dominator, excludeDominator, excludePhiOutEdges);
1349 }
1350
1351 bool get isEmpty => _instructions.isEmpty;
1352 bool get isNotEmpty => !isEmpty;
1353
1354 /// Changes all the uses in the set to [newInstruction].
1355 void replaceWith(HInstruction newInstruction) {
1356 assert(!identical(newInstruction, _source));
1357 if (isEmpty) return;
1358 for (int i = 0; i < _instructions.length; i++) {
1359 HInstruction user = _instructions[i];
1360 int index = _indexes[i];
1361 HInstruction oldInstruction = user.inputs[index];
1362 assert(
1363 identical(oldInstruction, _source),
1364 'Input ${index} of ${user} changed.'
1365 '\n Found: ${oldInstruction}\n Expected: ${_source}');
1366 user.inputs[index] = newInstruction;
1367 oldInstruction.usedBy.remove(user);
1368 newInstruction.usedBy.add(user);
1369 }
1370 }
1371
1372 void _addUse(HInstruction user, int inputIndex) {
1373 _instructions.add(user);
1374 _indexes.add(inputIndex);
1375 }
1376
1377 void _compute(HInstruction source, HInstruction dominator,
1378 bool excludeDominator, bool excludePhiOutEdges) {
1379 // Keep track of all instructions that we have to deal with later and count
1380 // the number of them that are in the current block.
1381 Set<HInstruction> users = new Setlet<HInstruction>();
1382 Set<HInstruction> seen = new Setlet<HInstruction>();
1383 int usersInCurrentBlock = 0;
1384
1385 HBasicBlock dominatorBlock = dominator.block;
1386
1387 // Run through all the users and see if they are dominated, or potentially
1388 // dominated, or partially dominated by [dominator]. It is easier to
1389 // de-duplicate [usedBy] and process all inputs of an instruction than to
1390 // track the repeated elements of usedBy and match them up by index.
1391 for (HInstruction current in source.usedBy) {
1392 if (!seen.add(current)) continue;
1393 HBasicBlock currentBlock = current.block;
1394 if (dominatorBlock.dominates(currentBlock)) {
1395 users.add(current);
1396 if (identical(currentBlock, dominatorBlock)) usersInCurrentBlock++;
1397 } else if (!excludePhiOutEdges && current is HPhi) {
1398 // A non-dominated HPhi.
1399 // See if there a dominated edge into the phi. The input must be
1400 // [source] and the position must correspond to a dominated block.
1401 List<HBasicBlock> predecessors = currentBlock.predecessors;
1402 for (int i = 0; i < predecessors.length; i++) {
1403 if (current.inputs[i] != source) continue;
1404 HBasicBlock predecessor = predecessors[i];
1405 if (dominatorBlock.dominates(predecessor)) {
1406 _addUse(current, i);
1407 }
1408 }
1409 }
1410 }
1411
1412 // Run through all the phis in the same block as [dominator] and remove them
1413 // from the users set. These come before [dominator].
1414 // TODO(sra): Could we simply not add them in the first place?
1415 if (usersInCurrentBlock > 0) {
1416 for (HPhi phi = dominatorBlock.phis.first; phi != null; phi = phi.next) {
1417 if (users.remove(phi)) {
1418 if (--usersInCurrentBlock == 0) break;
Emily Fortuna 2017/04/03 20:48:46 small preference for doing the decrement in a sepa
1419 }
1420 }
1421 }
1422
1423 // Run through all the instructions before [dominator] and remove them from
1424 // the users set.
1425 if (usersInCurrentBlock > 0) {
1426 HInstruction current = dominatorBlock.first;
1427 while (!identical(current, dominator)) {
1428 if (users.remove(current)) {
1429 if (--usersInCurrentBlock == 0) break;
1430 }
1431 current = current.next;
1432 }
1433 if (excludeDominator) {
1434 users.remove(dominator);
1435 }
1436 }
1437
1438 // Convert users into a list of (user, input-index) uses.
1439 for (HInstruction user in users) {
1440 var inputs = user.inputs;
1441 for (int i = 0; i < inputs.length; i++) {
1442 if (inputs[i] == source) {
1443 _addUse(user, i);
1444 }
1445 }
1446 }
1447 }
1448 }
1449
1372 /// A reference to a [HInstruction] that can hold its own source information. 1450 /// A reference to a [HInstruction] that can hold its own source information.
1373 /// 1451 ///
1374 /// This used for attaching source information to reads of locals. 1452 /// This used for attaching source information to reads of locals.
1375 class HRef extends HInstruction { 1453 class HRef extends HInstruction {
1376 HRef(HInstruction value, SourceInformation sourceInformation) 1454 HRef(HInstruction value, SourceInformation sourceInformation)
1377 : super([value], value.instructionType) { 1455 : super([value], value.instructionType) {
1378 this.sourceInformation = sourceInformation; 1456 this.sourceInformation = sourceInformation;
1379 } 1457 }
1380 1458
1381 HInstruction get value => inputs[0]; 1459 HInstruction get value => inputs[0];
(...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after
3393 3471
3394 String get kindAsString { 3472 String get kindAsString {
3395 switch (kind) { 3473 switch (kind) {
3396 case TypeInfoExpressionKind.COMPLETE: 3474 case TypeInfoExpressionKind.COMPLETE:
3397 return 'COMPLETE'; 3475 return 'COMPLETE';
3398 case TypeInfoExpressionKind.INSTANCE: 3476 case TypeInfoExpressionKind.INSTANCE:
3399 return 'INSTANCE'; 3477 return 'INSTANCE';
3400 } 3478 }
3401 } 3479 }
3402 } 3480 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/optimize.dart » ('j') | pkg/compiler/lib/src/ssa/optimize.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698