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

Side by Side 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, 7 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
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 class SsaCodeGeneratorTask extends CompilerTask { 5 class SsaCodeGeneratorTask extends CompilerTask {
6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler);
7 String get name() => 'SSA code generator'; 7 String get name() => 'SSA code generator';
8 8
9 9
10 String buildJavaScriptFunction(FunctionElement element, 10 String buildJavaScriptFunction(FunctionElement element,
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 } 428 }
429 } 429 }
430 430
431 name = '${prefix}${prefixes[prefix]++}'; 431 name = '${prefix}${prefixes[prefix]++}';
432 while (usedNames.contains(name)) { 432 while (usedNames.contains(name)) {
433 name = '${prefix}${prefixes[prefix]++}'; 433 name = '${prefix}${prefixes[prefix]++}';
434 } 434 }
435 return newName(id, name); 435 return newName(id, name);
436 } 436 }
437 437
438 // TODO(floitsch): share more code with [temporary].
439 String freshTemporary() {
440 String prefix = TEMPORARY_PREFIX;
441 String name = '${prefix}${prefixes[prefix]++}';
442 while (usedNames.contains(name)) {
443 name = '${prefix}${prefixes[prefix]++}';
444 }
445 String result = JsNames.getValid(name);
446 usedNames.add(result);
447 return result;
448 }
449
438 bool temporaryExists(HInstruction instruction) { 450 bool temporaryExists(HInstruction instruction) {
439 return names.containsKey(instruction.id); 451 return names.containsKey(instruction.id);
440 } 452 }
441 453
442 String newName(int id, String name) { 454 String newName(int id, String name) {
443 String result = JsNames.getValid(name); 455 String result = JsNames.getValid(name);
444 names[id] = result; 456 names[id] = result;
445 usedNames.add(result); 457 usedNames.add(result);
446 return result; 458 return result;
447 } 459 }
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 if (success) return; 913 if (success) return;
902 914
903 // If our special handling didn't succeed, we have to emit a generic 915 // If our special handling didn't succeed, we have to emit a generic
904 // version. This still requires special handling for loop-blocks 916 // version. This still requires special handling for loop-blocks
905 if (node.isLoopHeader()) { 917 if (node.isLoopHeader()) {
906 beginLoop(node); 918 beginLoop(node);
907 } 919 }
908 } 920 }
909 iterateBasicBlock(node); 921 iterateBasicBlock(node);
910 } 922 }
911 923
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.
924 void assignPhisOfAllSuccessors(HBasicBlock node) {
925 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
926
927 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.
928 if (isGeneratingExpression()) {
929 addExpressionSeparator();
930 } else {
931 addIndentation();
932 }
933 if (phiTemporaries !== null &&
934 canonicalPhi !== value &&
935 phiTemporaries.containsKey(canonicalPhi)) {
936 // This is the assignment to the temporary.
937 declareVariable(phiTemporaries[canonicalPhi]);
938 } else if (!temporaryExists(canonicalPhi)) {
939 declareVariable(temporary(canonicalPhi));
940 } else {
941 buffer.add(temporary(canonicalPhi));
942 }
943 buffer.add(" = ");
944 bool isLogicalOperation = logicalOperations.containsKey(canonicalPhi);
945 if (isLogicalOperation) {
946 emitLogicalOperation(canonicalPhi, logicalOperations[canonicalPhi]);
947 } else if (canonicalPhi === value) {
948 buffer.add(phiTemporaries[value]);
949 } else {
950 use(value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
951 }
952 if (!isGeneratingExpression()) {
953 buffer.add(';\n');
954 }
955 }
956
957 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.
958 bool shouldBeAdded(HPhi phi)) {
959 if (input is HPhi) {
960 HPhi canonicalPhi = phiEquivalence.getRepresentative(input);
961 if (shouldBeAdded(canonicalPhi)) inputPhis.add(canonicalPhi);
962 } else if (isGenerateAtUseSite(input)) {
963 for (HInstruction inputOfInput in input.inputs) {
964 collectInputPhis(inputOfInput, inputPhis, shouldBeAdded);
965 }
966 }
967 }
968
969 // Assignments are delayed so that we don't overwrite phis that might
970 // be used as inputs.
971 // TODO(floitsch): improve phi assignments. Currently we introduce
972 // way too many temporary variables.
973 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.
974 for (HBasicBlock successor in node.successors) {
975 int index = successor.predecessors.indexOf(node);
976 successor.forEachPhi((HPhi phi) {
977 bool isLogicalOperation = logicalOperations.containsKey(phi);
978 // In case the phi is being generated by another
979 // instruction.
980 if (isLogicalOperation && isGenerateAtUseSite(phi)) return;
981 HPhi canonicalPhi = phiEquivalence.getRepresentative(phi);
982 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.
983 HInstruction input = phi.inputs[index];
984 if (input is HPhi) {
985 input = phiEquivalence.getRepresentative(input);
986 // If we use the same variable, we don't need to create an
987 // assignment.
988 if (input === canonicalPhi) {
989 assert(!isLogicalOperation);
990 return;
991 }
992 }
993 phiAssignments[canonicalPhi] = input;
994 });
995 }
996
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Remove extra empty line.
floitsch 2012/05/03 09:11:29 Done.
997
998 List<HPhi> phis = <HPhi>[];
999 Set<HPhi> inputPhis = new Set<HPhi>();
1000 phiAssignments.forEach((HPhi targetPhi, HInstruction input) {
1001 phis.add(targetPhi);
1002 collectInputPhis(input, inputPhis, (HPhi phi) {
1003 // Self-assignments are ok.
1004 return phi !== targetPhi && phiAssignments.containsKey(phi);
1005 });
Lasse Reichstein Nielsen 2012/05/03 08:22:02 Inline the shouldBeAdded function in collectInputP
floitsch 2012/05/03 09:11:29 Done.
1006 });
1007
1008 bool phisAreUsedAsInputs = !inputPhis.isEmpty();
1009
1010 if (!phisAreUsedAsInputs) {
1011 phiAssignments.forEach(assignPhi);
1012 } else {
1013 // Emit the phiX=phiY assignments, taking care to break cycles.
1014 // Example program:
1015 // var x = 499;
1016 // var y = 99;
1017 // while (x != 99) {
1018 // var tmp = x; // <=== The tmp variable is removed in Ssa-form.
1019 // x = y;
1020 // y = tmp;
1021 // }
1022 //
1023 int length = phis.length;
1024 phiTemporaries = new HashMap<HInstruction, String>();
1025 // For phis that are used as inputs simply *always* allocate a
1026 // temporary.
1027 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.
1028 HPhi phi = phis[i];
1029 if (inputPhis.contains(phi)) {
1030 String temporaryPhi = freshTemporary();
1031 phiTemporaries[phi] = temporaryPhi;
1032 }
1033 // The assignPhi uses temporary variables for the left-hand side if
1034 // they exist.
1035 assignPhi(phi, phiAssignments[phi]);
1036 }
1037 // Finally assign the input phis.
1038 for (HPhi phi in inputPhis) {
1039 // The assignPhi special-cases phi assignments to itself and recognizes
1040 // it as assignment from the temporary variable to the actual phi.
1041 assignPhi(phi, phi);
1042 }
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.
1043 }
1044 }
1045
912 void iterateBasicBlock(HBasicBlock node) { 1046 void iterateBasicBlock(HBasicBlock node) {
913 HInstruction instruction = node.first; 1047 HInstruction instruction = node.first;
914 while (instruction != null) { 1048 while (instruction != null) {
915 if (instruction === node.last) { 1049 if (instruction === node.last) {
916 for (HBasicBlock successor in node.successors) { 1050 assignPhisOfAllSuccessors(node);
917 int index = successor.predecessors.indexOf(node);
918 successor.forEachPhi((HPhi phi) {
919 bool isLogicalOperation = logicalOperations.containsKey(phi);
920 // In case the phi is being generated by another
921 // instruction.
922 if (isLogicalOperation && isGenerateAtUseSite(phi)) return;
923 HPhi canonicalPhi = phiEquivalence.getRepresentative(phi);
924 HInstruction input = phi.inputs[index];
925 if (input is HPhi) {
926 HPhi inputPhi = input;
927 HPhi canonicalInput = phiEquivalence.getRepresentative(inputPhi);
928 // If we use the same variable, we don't need to create an
929 // assignment.
930 if (canonicalInput === canonicalPhi) {
931 assert(!isLogicalOperation);
932 return;
933 }
934 }
935 if (isGeneratingExpression()) {
936 addExpressionSeparator();
937 } else {
938 addIndentation();
939 }
940 if (!temporaryExists(canonicalPhi)) {
941 declareVariable(temporary(canonicalPhi));
942 } else {
943 buffer.add(temporary(canonicalPhi));
944 }
945 buffer.add(" = ");
946 if (isLogicalOperation) {
947 emitLogicalOperation(phi, logicalOperations[phi]);
948 } else {
949 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE);
950 }
951 if (!isGeneratingExpression()) {
952 buffer.add(';\n');
953 }
954 });
955 }
956 } 1051 }
957 1052
958 if (instruction is HGoto || instruction is HExit || instruction is HTry) { 1053 if (instruction is HGoto || instruction is HExit || instruction is HTry) {
959 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1054 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
960 return; 1055 return;
961 } else if (!isGenerateAtUseSite(instruction)) { 1056 } else if (!isGenerateAtUseSite(instruction)) {
962 if (instruction is !HIf && instruction is !HTypeGuard && 1057 if (instruction is !HIf && instruction is !HTypeGuard &&
963 instruction is !HLoopBranch && !isGeneratingExpression()) { 1058 instruction is !HLoopBranch && !isGeneratingExpression()) {
964 addIndentation(); 1059 addIndentation();
965 } 1060 }
(...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after
2294 startBailoutSwitch(); 2389 startBailoutSwitch();
2295 } 2390 }
2296 } 2391 }
2297 2392
2298 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2393 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2299 if (labeledBlockInfo.body.start.hasGuards()) { 2394 if (labeledBlockInfo.body.start.hasGuards()) {
2300 endBailoutSwitch(); 2395 endBailoutSwitch();
2301 } 2396 }
2302 } 2397 }
2303 } 2398 }
OLDNEW
« 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