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

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

Issue 2301293002: kernel -> ssa: implement if-statements (Closed)
Patch Set: Created 4 years, 3 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
(Empty)
1 import '../compiler.dart';
Siggi Cherem (dart-lang) 2016/09/01 23:51:22 + copyright
Harry Terkelsen 2016/09/02 17:52:28 Done.
2 import '../io/source_information.dart';
3 import '../js_backend/js_backend.dart';
4 import '../tree/tree.dart' as ast;
5
6 import 'graph_builder.dart';
7 import 'locals_handler.dart';
8 import 'nodes.dart';
9
10 class SsaBranch {
11 final SsaBranchBuilder branchBuilder;
12 final HBasicBlock block;
13 LocalsHandler startLocals;
14 LocalsHandler exitLocals;
15 SubGraph graph;
16
17 SsaBranch(this.branchBuilder) : block = new HBasicBlock();
18 }
19
20 class SsaBranchBuilder {
21 final GraphBuilder builder;
22 final Compiler compiler;
23 final ast.Node diagnosticNode;
24
25 SsaBranchBuilder(this.builder, this.compiler, [this.diagnosticNode]);
26
27 void checkNotAborted() {
28 if (builder.isAborted()) {
29 compiler.unimplemented(diagnosticNode, "aborted control flow");
30 }
31 }
32
33 void buildCondition(
34 void visitCondition(),
35 SsaBranch conditionBranch,
36 SsaBranch thenBranch,
37 SsaBranch elseBranch,
38 SourceInformation sourceInformation) {
39 startBranch(conditionBranch);
40 visitCondition();
41 checkNotAborted();
42 assert(identical(builder.current, builder.lastOpenedBlock));
43 HInstruction conditionValue = builder.popBoolified();
44 HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation;
45 HBasicBlock conditionExitBlock = builder.current;
46 builder.close(branch);
47 conditionBranch.exitLocals = builder.localsHandler;
48 conditionExitBlock.addSuccessor(thenBranch.block);
49 conditionExitBlock.addSuccessor(elseBranch.block);
50 bool conditionBranchLocalsCanBeReused =
51 mergeLocals(conditionBranch, thenBranch, mayReuseFromLocals: true);
52 mergeLocals(conditionBranch, elseBranch,
53 mayReuseFromLocals: conditionBranchLocalsCanBeReused);
54
55 conditionBranch.graph =
56 new SubExpression(conditionBranch.block, conditionExitBlock);
57 }
58
59 /**
60 * Returns true if the locals of the [fromBranch] may be reused. A [:true:]
61 * return value implies that [mayReuseFromLocals] was set to [:true:].
62 */
63 bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch,
64 {bool mayReuseFromLocals}) {
65 LocalsHandler fromLocals = fromBranch.exitLocals;
66 if (toBranch.startLocals == null) {
67 if (mayReuseFromLocals) {
68 toBranch.startLocals = fromLocals;
69 return false;
70 } else {
71 toBranch.startLocals = new LocalsHandler.from(fromLocals);
72 return true;
73 }
74 } else {
75 toBranch.startLocals.mergeWith(fromLocals, toBranch.block);
76 return true;
77 }
78 }
79
80 void startBranch(SsaBranch branch) {
81 builder.graph.addBlock(branch.block);
82 builder.localsHandler = branch.startLocals;
83 builder.open(branch.block);
84 }
85
86 HInstruction buildBranch(SsaBranch branch, void visitBranch(),
87 SsaBranch joinBranch, bool isExpression) {
88 startBranch(branch);
89 visitBranch();
90 branch.graph = new SubGraph(branch.block, builder.lastOpenedBlock);
91 branch.exitLocals = builder.localsHandler;
92 if (!builder.isAborted()) {
93 builder.goto(builder.current, joinBranch.block);
94 mergeLocals(branch, joinBranch, mayReuseFromLocals: true);
95 }
96 if (isExpression) {
97 checkNotAborted();
98 return builder.pop();
99 }
100 return null;
101 }
102
103 handleIf(void visitCondition(), void visitThen(), void visitElse(),
104 {SourceInformation sourceInformation}) {
105 if (visitElse == null) {
106 // Make sure to have an else part to avoid a critical edge. A
107 // critical edge is an edge that connects a block with multiple
108 // successors to a block with multiple predecessors. We avoid
109 // such edges because they prevent inserting copies during code
110 // generation of phi instructions.
111 visitElse = () {};
112 }
113
114 _handleDiamondBranch(visitCondition, visitThen, visitElse,
115 isExpression: false, sourceInformation: sourceInformation);
116 }
117
118 handleConditional(void visitCondition(), void visitThen(), void visitElse()) {
119 assert(visitElse != null);
120 _handleDiamondBranch(visitCondition, visitThen, visitElse,
121 isExpression: true);
122 }
123
124 handleIfNull(void left(), void right()) {
125 // x ?? y is transformed into: x == null ? y : x
126 HInstruction leftExpression;
127 handleConditional(() {
128 left();
129 leftExpression = builder.pop();
130 builder.pushCheckNull(leftExpression);
131 }, right, () => builder.stack.add(leftExpression));
132 }
133
134 void handleLogicalAndOr(void left(), void right(), {bool isAnd}) {
Siggi Cherem (dart-lang) 2016/09/01 23:51:22 consider making this private and exposing 2 public
Harry Terkelsen 2016/09/02 17:52:27 Seems good, but if I do this then I will have to c
Siggi Cherem (dart-lang) 2016/09/02 17:56:37 Good point - now that we refactored the other, it
135 // x && y is transformed into:
136 // t0 = boolify(x);
137 // if (t0) {
138 // t1 = boolify(y);
139 // }
140 // result = phi(t1, false);
141 //
142 // x || y is transformed into:
143 // t0 = boolify(x);
144 // if (not(t0)) {
145 // t1 = boolify(y);
146 // }
147 // result = phi(t1, true);
148 HInstruction boolifiedLeft;
149 HInstruction boolifiedRight;
150
151 void visitCondition() {
152 left();
153 boolifiedLeft = builder.popBoolified();
154 builder.stack.add(boolifiedLeft);
155 if (!isAnd) {
156 JavaScriptBackend backend = compiler.backend;
157 builder.push(new HNot(builder.pop(), backend.boolType));
158 }
159 }
160
161 void visitThen() {
162 right();
163 boolifiedRight = builder.popBoolified();
164 }
165
166 handleIf(visitCondition, visitThen, null);
167 HConstant notIsAnd = builder.graph.addConstantBool(!isAnd, compiler);
168 JavaScriptBackend backend = compiler.backend;
169 HPhi result = new HPhi.manyInputs(
170 null, <HInstruction>[boolifiedRight, notIsAnd], backend.dynamicType);
171 builder.current.addPhi(result);
172 builder.stack.add(result);
173 }
174
175 void _handleDiamondBranch(
176 void visitCondition(), void visitThen(), void visitElse(),
177 {bool isExpression, SourceInformation sourceInformation}) {
178 SsaBranch conditionBranch = new SsaBranch(this);
179 SsaBranch thenBranch = new SsaBranch(this);
180 SsaBranch elseBranch = new SsaBranch(this);
181 SsaBranch joinBranch = new SsaBranch(this);
182
183 conditionBranch.startLocals = builder.localsHandler;
184 builder.goto(builder.current, conditionBranch.block);
185
186 buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch,
187 sourceInformation);
188 HInstruction thenValue =
189 buildBranch(thenBranch, visitThen, joinBranch, isExpression);
190 HInstruction elseValue =
191 buildBranch(elseBranch, visitElse, joinBranch, isExpression);
192
193 if (isExpression) {
194 assert(thenValue != null && elseValue != null);
195 JavaScriptBackend backend = compiler.backend;
196 HPhi phi = new HPhi.manyInputs(
197 null, <HInstruction>[thenValue, elseValue], backend.dynamicType);
198 joinBranch.block.addPhi(phi);
199 builder.stack.add(phi);
200 }
201
202 HBasicBlock joinBlock;
203 // If at least one branch did not abort, open the joinBranch.
204 if (!joinBranch.block.predecessors.isEmpty) {
205 startBranch(joinBranch);
206 joinBlock = joinBranch.block;
207 }
208
209 HIfBlockInformation info = new HIfBlockInformation(
210 new HSubExpressionBlockInformation(conditionBranch.graph),
211 new HSubGraphBlockInformation(thenBranch.graph),
212 new HSubGraphBlockInformation(elseBranch.graph));
213
214 HBasicBlock conditionStartBlock = conditionBranch.block;
215 conditionStartBlock.setBlockFlow(info, joinBlock);
216 SubGraph conditionGraph = conditionBranch.graph;
217 HIf branch = conditionGraph.end.last;
218 assert(branch is HIf);
219 branch.blockInformation = conditionStartBlock.blockFlow;
220 }
221 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698