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

Unified Diff: pkg/compiler/lib/src/ssa/nodes.dart

Issue 2802323002: Redo "dart2js: Insert HTypeKnown refinement nodes on dominated edges of HPhi nodes." (Closed)
Patch Set: Work around VM performance bug (29302) Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/optimize.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/nodes.dart
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 12d82d9a966f2b318da8dc2c7aabcb4a2f287b77..5d9f10c8c994985d899219e8e0b294a5bca84ccd 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -866,6 +866,8 @@ class HBasicBlock extends HInstructionList {
} while (other != null && other.id >= id);
return dominatesCache[other] = false;
}
+
+ toString() => 'HBasicBlock($id)';
}
abstract class HInstruction implements Spannable {
@@ -1277,60 +1279,9 @@ abstract class HInstruction implements Spannable {
removeFromList(oldInput.usedBy, this);
}
- // Compute the set of users of this instruction that is dominated by
- // [other]. If [other] is a user of [this], it is included in the
- // returned set.
- Setlet<HInstruction> dominatedUsers(HInstruction other) {
- // Keep track of all instructions that we have to deal with later
- // and count the number of them that are in the current block.
- Setlet<HInstruction> users = new Setlet<HInstruction>();
- int usersInCurrentBlock = 0;
-
- // Run through all the users and see if they are dominated or
- // potentially dominated by [other].
- HBasicBlock otherBlock = other.block;
- for (int i = 0, length = usedBy.length; i < length; i++) {
- HInstruction current = usedBy[i];
- HBasicBlock currentBlock = current.block;
- if (otherBlock.dominates(currentBlock)) {
- if (identical(currentBlock, otherBlock)) usersInCurrentBlock++;
- users.add(current);
- }
- }
-
- // Run through all the phis in the same block as [other] and remove them
- // from the users set.
- if (usersInCurrentBlock > 0) {
- for (HPhi phi = otherBlock.phis.first; phi != null; phi = phi.next) {
- if (users.contains(phi)) {
- users.remove(phi);
- if (--usersInCurrentBlock == 0) break;
- }
- }
- }
-
- // Run through all the instructions before [other] and remove them
- // from the users set.
- if (usersInCurrentBlock > 0) {
- HInstruction current = otherBlock.first;
- while (!identical(current, other)) {
- if (users.contains(current)) {
- users.remove(current);
- if (--usersInCurrentBlock == 0) break;
- }
- current = current.next;
- }
- }
-
- return users;
- }
-
void replaceAllUsersDominatedBy(
HInstruction cursor, HInstruction newInstruction) {
- Setlet<HInstruction> users = dominatedUsers(cursor);
- for (HInstruction user in users) {
- user.changeUse(this, newInstruction);
- }
+ DominatedUses.of(this, cursor).replaceWith(newInstruction);
}
void moveBefore(HInstruction other) {
@@ -1417,6 +1368,134 @@ abstract class HInstruction implements Spannable {
}
}
+/// The set of uses of [source] that are dominated by [dominator].
+class DominatedUses {
+ final HInstruction _source;
+
+ // Two list of matching length holding (instruction, input-index) pairs for
+ // the dominated uses.
+ final List<HInstruction> _instructions = <HInstruction>[];
+ final List<int> _indexes = <int>[];
+
+ DominatedUses._(this._source);
+
+ /// The uses of [source] that are dominated by [dominator].
+ ///
+ /// The uses by [dominator] are included in the result, unless
+ /// [excludeDominator] is `true`, so `true` selects uses following
+ /// [dominator].
+ ///
+ /// The uses include the in-edges of a HPhi node that corresponds to a
+ /// dominated block. (There can be many such edges on a single phi at the exit
+ /// of a loop with many break statements). If [excludePhiOutEdges] is `true`
+ /// then these edge uses are not included.
+ static of(HInstruction source, HInstruction dominator,
+ {bool excludeDominator: false, bool excludePhiOutEdges: false}) {
+ return new DominatedUses._(source)
+ .._compute(source, dominator, excludeDominator, excludePhiOutEdges);
+ }
+
+ bool get isEmpty => _instructions.isEmpty;
+ bool get isNotEmpty => !isEmpty;
+
+ /// Changes all the uses in the set to [newInstruction].
+ void replaceWith(HInstruction newInstruction) {
+ assert(!identical(newInstruction, _source));
+ if (isEmpty) return;
+ for (int i = 0; i < _instructions.length; i++) {
+ HInstruction user = _instructions[i];
+ int index = _indexes[i];
+ HInstruction oldInstruction = user.inputs[index];
+ assert(
+ identical(oldInstruction, _source),
+ 'Input ${index} of ${user} changed.'
+ '\n Found: ${oldInstruction}\n Expected: ${_source}');
+ user.inputs[index] = newInstruction;
+ oldInstruction.usedBy.remove(user);
+ newInstruction.usedBy.add(user);
+ }
+ }
+
+ void _addUse(HInstruction user, int inputIndex) {
+ _instructions.add(user);
+ _indexes.add(inputIndex);
+ }
+
+ void _compute(HInstruction source, HInstruction dominator,
+ bool excludeDominator, bool excludePhiOutEdges) {
+ // Keep track of all instructions that we have to deal with later and count
+ // the number of them that are in the current block.
+ Set<HInstruction> users = new Setlet<HInstruction>();
+ Set<HInstruction> seen = new Setlet<HInstruction>();
+ int usersInCurrentBlock = 0;
+
+ HBasicBlock dominatorBlock = dominator.block;
+
+ // Run through all the users and see if they are dominated, or potentially
+ // dominated, or partially dominated by [dominator]. It is easier to
+ // de-duplicate [usedBy] and process all inputs of an instruction than to
+ // track the repeated elements of usedBy and match them up by index.
+ for (HInstruction current in source.usedBy) {
+ if (!seen.add(current)) continue;
+ HBasicBlock currentBlock = current.block;
+ if (dominatorBlock.dominates(currentBlock)) {
+ users.add(current);
+ if (identical(currentBlock, dominatorBlock)) usersInCurrentBlock++;
+ } else if (!excludePhiOutEdges && current is HPhi) {
+ // A non-dominated HPhi.
+ // See if there a dominated edge into the phi. The input must be
+ // [source] and the position must correspond to a dominated block.
+ List<HBasicBlock> predecessors = currentBlock.predecessors;
+ for (int i = 0; i < predecessors.length; i++) {
+ if (current.inputs[i] != source) continue;
+ HBasicBlock predecessor = predecessors[i];
+ if (dominatorBlock.dominates(predecessor)) {
+ _addUse(current, i);
+ }
+ }
+ }
+ }
+
+ // Run through all the phis in the same block as [dominator] and remove them
+ // from the users set. These come before [dominator].
+ // TODO(sra): Could we simply not add them in the first place?
+ if (usersInCurrentBlock > 0) {
+ for (HPhi phi = dominatorBlock.phis.first; phi != null; phi = phi.next) {
+ if (users.remove(phi)) {
+ if (--usersInCurrentBlock == 0) break;
+ }
+ }
+ }
+
+ // Run through all the instructions before [dominator] and remove them from
+ // the users set.
+ if (usersInCurrentBlock > 0) {
+ HInstruction current = dominatorBlock.first;
+ while (!identical(current, dominator)) {
+ if (users.contains(current)) {
+ // TODO(29302): Use 'user.remove(current)' as the condition.
+ users.remove(current);
+ if (--usersInCurrentBlock == 0) break;
+ }
+ current = current.next;
+ }
+ if (excludeDominator) {
+ users.remove(dominator);
+ }
+ }
+
+ // Convert users into a list of (user, input-index) uses.
+ for (HInstruction user in users) {
+ var inputs = user.inputs;
+ for (int i = 0; i < inputs.length; i++) {
+ if (inputs[i] == source) {
+ _addUse(user, i);
+ }
+ }
+ }
+ }
+}
+
/// A reference to a [HInstruction] that can hold its own source information.
///
/// This used for attaching source information to reads of locals.
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/optimize.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698