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

Unified Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10342002: Make sure that we don't assign phis before its uses. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Don't introduce temp for updates to self. Created 8 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 | tests/language/loop_exchange2_test.dart » ('j') | tests/language/loop_exchange2_test.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/ssa/codegen.dart
diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart
index 4ef4e02014b33084545e371663981db6515c2cf1..8e49b8ad54f732700bd4d3ea2d8c62f20486e525 100644
--- a/lib/compiler/implementation/ssa/codegen.dart
+++ b/lib/compiler/implementation/ssa/codegen.dart
@@ -435,6 +435,18 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
return newName(id, name);
}
+ // TODO(floitsch): share more code with [temporary].
+ String freshTemporary() {
+ String prefix = TEMPORARY_PREFIX;
+ String name = '${prefix}${prefixes[prefix]++}';
+ while (usedNames.contains(name)) {
+ name = '${prefix}${prefixes[prefix]++}';
+ }
+ String result = JsNames.getValid(name);
+ usedNames.add(result);
+ return result;
+ }
+
bool temporaryExists(HInstruction instruction) {
return names.containsKey(instruction.id);
}
@@ -909,50 +921,133 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
iterateBasicBlock(node);
}
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Please add dart-doc describing what the method doe
floitsch 2012/05/03 09:11:29 Done.
+ void assignPhisOfAllSuccessors(HBasicBlock node) {
+ Map<HInstruction, String> phiTemporaries = null;
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Can you give a better name to this map? I gives no
floitsch 2012/05/03 09:11:29 renamed to temporaryNamesOfPhis. (dart-editor for
+
+ void assignPhi(HPhi canonicalPhi, HInstruction value) {
Lasse Reichstein Nielsen 2012/05/03 08:22:02 assignPhi -> generateAssignment. You don't assign
floitsch 2012/05/03 09:11:29 Renamed and added doc.
+ if (isGeneratingExpression()) {
+ addExpressionSeparator();
+ } else {
+ addIndentation();
+ }
+ if (phiTemporaries !== null &&
+ canonicalPhi !== value &&
+ phiTemporaries.containsKey(canonicalPhi)) {
+ // This is the assignment to the temporary.
+ declareVariable(phiTemporaries[canonicalPhi]);
+ } else if (!temporaryExists(canonicalPhi)) {
+ declareVariable(temporary(canonicalPhi));
+ } else {
+ buffer.add(temporary(canonicalPhi));
+ }
+ buffer.add(" = ");
+ bool isLogicalOperation = logicalOperations.containsKey(canonicalPhi);
+ if (isLogicalOperation) {
+ emitLogicalOperation(canonicalPhi, logicalOperations[canonicalPhi]);
+ } else if (canonicalPhi === value) {
+ buffer.add(phiTemporaries[value]);
+ } else {
+ use(value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
+ }
+ if (!isGeneratingExpression()) {
+ buffer.add(';\n');
+ }
+ }
+
+ void collectInputPhis(HInstruction input, Set<HPhi> inputPhis,
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Dart-doc description of what the function does, pl
floitsch 2012/05/03 09:11:29 Done.
+ bool shouldBeAdded(HPhi phi)) {
+ if (input is HPhi) {
+ HPhi canonicalPhi = phiEquivalence.getRepresentative(input);
+ if (shouldBeAdded(canonicalPhi)) inputPhis.add(canonicalPhi);
+ } else if (isGenerateAtUseSite(input)) {
+ for (HInstruction inputOfInput in input.inputs) {
+ collectInputPhis(inputOfInput, inputPhis, shouldBeAdded);
+ }
+ }
+ }
+
+ // Assignments are delayed so that we don't overwrite phis that might
+ // be used as inputs.
+ // TODO(floitsch): improve phi assignments. Currently we introduce
+ // way too many temporary variables.
+ Map<HPhi, HInstruction> phiAssignments = new Map<HPhi, HInstruction>();
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Please add empty line after declaration.
floitsch 2012/05/03 09:11:29 Done.
+ for (HBasicBlock successor in node.successors) {
+ int index = successor.predecessors.indexOf(node);
+ successor.forEachPhi((HPhi phi) {
+ bool isLogicalOperation = logicalOperations.containsKey(phi);
+ // In case the phi is being generated by another
+ // instruction.
+ if (isLogicalOperation && isGenerateAtUseSite(phi)) return;
+ HPhi canonicalPhi = phiEquivalence.getRepresentative(phi);
+ assert(canonicalPhi === phi || !isLogicalOperation);
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Reading this now, I actually prefer: assert(!isL
floitsch 2012/05/03 09:11:29 Done.
+ HInstruction input = phi.inputs[index];
+ if (input is HPhi) {
+ input = phiEquivalence.getRepresentative(input);
+ // If we use the same variable, we don't need to create an
+ // assignment.
+ if (input === canonicalPhi) {
+ assert(!isLogicalOperation);
+ return;
+ }
+ }
+ phiAssignments[canonicalPhi] = input;
+ });
+ }
+
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Remove extra empty line.
floitsch 2012/05/03 09:11:29 Done.
+
+ List<HPhi> phis = <HPhi>[];
+ Set<HPhi> inputPhis = new Set<HPhi>();
+ phiAssignments.forEach((HPhi targetPhi, HInstruction input) {
+ phis.add(targetPhi);
+ collectInputPhis(input, inputPhis, (HPhi phi) {
+ // Self-assignments are ok.
+ return phi !== targetPhi && phiAssignments.containsKey(phi);
+ });
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Inline the shouldBeAdded function in collectInputP
floitsch 2012/05/03 09:11:29 Done.
+ });
+
+ bool phisAreUsedAsInputs = !inputPhis.isEmpty();
+
+ if (!phisAreUsedAsInputs) {
+ phiAssignments.forEach(assignPhi);
+ } else {
+ // Emit the phiX=phiY assignments, taking care to break cycles.
+ // Example program:
+ // var x = 499;
+ // var y = 99;
+ // while (x != 99) {
+ // var tmp = x; // <=== The tmp variable is removed in Ssa-form.
+ // x = y;
+ // y = tmp;
+ // }
+ //
+ int length = phis.length;
+ phiTemporaries = new HashMap<HInstruction, String>();
+ // For phis that are used as inputs simply *always* allocate a
+ // temporary.
+ for (int i = 0; i < length; i++) {
Lasse Reichstein Nielsen 2012/05/03 08:22:02 You don't use "i", so perhaps just for (HPhi phi
floitsch 2012/05/03 09:11:29 Done.
+ HPhi phi = phis[i];
+ if (inputPhis.contains(phi)) {
+ String temporaryPhi = freshTemporary();
+ phiTemporaries[phi] = temporaryPhi;
+ }
+ // The assignPhi uses temporary variables for the left-hand side if
+ // they exist.
+ assignPhi(phi, phiAssignments[phi]);
+ }
+ // Finally assign the input phis.
+ for (HPhi phi in inputPhis) {
+ // The assignPhi special-cases phi assignments to itself and recognizes
+ // it as assignment from the temporary variable to the actual phi.
+ assignPhi(phi, phi);
+ }
Lasse Reichstein Nielsen 2012/05/03 08:22:02 For a later version, maybe we can try sorting the
floitsch 2012/05/03 09:11:29 That's what the TODO implies.
+ }
+ }
+
void iterateBasicBlock(HBasicBlock node) {
HInstruction instruction = node.first;
while (instruction != null) {
if (instruction === node.last) {
- for (HBasicBlock successor in node.successors) {
- int index = successor.predecessors.indexOf(node);
- successor.forEachPhi((HPhi phi) {
- bool isLogicalOperation = logicalOperations.containsKey(phi);
- // In case the phi is being generated by another
- // instruction.
- if (isLogicalOperation && isGenerateAtUseSite(phi)) return;
- HPhi canonicalPhi = phiEquivalence.getRepresentative(phi);
- HInstruction input = phi.inputs[index];
- if (input is HPhi) {
- HPhi inputPhi = input;
- HPhi canonicalInput = phiEquivalence.getRepresentative(inputPhi);
- // If we use the same variable, we don't need to create an
- // assignment.
- if (canonicalInput === canonicalPhi) {
- assert(!isLogicalOperation);
- return;
- }
- }
- if (isGeneratingExpression()) {
- addExpressionSeparator();
- } else {
- addIndentation();
- }
- if (!temporaryExists(canonicalPhi)) {
- declareVariable(temporary(canonicalPhi));
- } else {
- buffer.add(temporary(canonicalPhi));
- }
- buffer.add(" = ");
- if (isLogicalOperation) {
- emitLogicalOperation(phi, logicalOperations[phi]);
- } else {
- use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE);
- }
- if (!isGeneratingExpression()) {
- buffer.add(';\n');
- }
- });
- }
+ assignPhisOfAllSuccessors(node);
}
if (instruction is HGoto || instruction is HExit || instruction is HTry) {
« no previous file with comments | « no previous file | tests/language/loop_exchange2_test.dart » ('j') | tests/language/loop_exchange2_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698