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

Side by Side Diff: test/cctest/compiler/test-control-reducer.cc

Issue 1122423003: [turbofan] Add support for advanced reducers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Move comment Created 5 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
« no previous file with comments | « src/compiler/pipeline.cc ('k') | test/unittests/compiler/control-reducer-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 #include "test/cctest/cctest.h" 6 #include "test/cctest/cctest.h"
7 7
8 #include "src/base/bits.h" 8 #include "src/base/bits.h"
9 #include "src/compiler/all-nodes.h"
9 #include "src/compiler/common-operator.h" 10 #include "src/compiler/common-operator.h"
10 #include "src/compiler/control-reducer.h" 11 #include "src/compiler/control-reducer.h"
11 #include "src/compiler/graph.h" 12 #include "src/compiler/graph.h"
12 #include "src/compiler/js-graph.h" 13 #include "src/compiler/js-graph.h"
13 #include "src/compiler/node-properties.h" 14 #include "src/compiler/node-properties.h"
14 15
15 using namespace v8::internal; 16 using namespace v8::internal;
16 using namespace v8::internal::compiler; 17 using namespace v8::internal::compiler;
17 18
18 static const size_t kNumLeafs = 4; 19 static const size_t kNumLeafs = 4;
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 } 136 }
136 return node; 137 return node;
137 } 138 }
138 139
139 const Operator* op(int count, bool effect) { 140 const Operator* op(int count, bool effect) {
140 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count); 141 return effect ? common.EffectPhi(count) : common.Phi(kMachAnyTagged, count);
141 } 142 }
142 143
143 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); } 144 void Trim() { ControlReducer::TrimGraph(main_zone(), &jsgraph); }
144 145
145 void ReduceGraph() { 146 void ReduceGraph() { ControlReducer::ReduceGraph(main_zone(), &jsgraph); }
146 ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common);
147 }
148 147
149 // Checks one-step reduction of a phi. 148 // Checks one-step reduction of a phi.
150 void ReducePhi(Node* expect, Node* phi) { 149 void ReducePhi(Node* expect, Node* phi) {
151 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, &common, phi); 150 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi);
152 CHECK_EQ(expect, result); 151 CHECK_EQ(expect, result);
153 ReducePhiIterative(expect, phi); // iterative should give the same result. 152 ReducePhiIterative(expect, phi); // iterative should give the same result.
154 } 153 }
155 154
156 // Checks one-step reduction of a phi. 155 // Checks one-step reduction of a phi.
157 void ReducePhiNonIterative(Node* expect, Node* phi) { 156 void ReducePhiNonIterative(Node* expect, Node* phi) {
158 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, &common, phi); 157 Node* result = ControlReducer::ReducePhiForTesting(&jsgraph, phi);
159 CHECK_EQ(expect, result); 158 CHECK_EQ(expect, result);
160 } 159 }
161 160
162 void ReducePhiIterative(Node* expect, Node* phi) { 161 void ReducePhiIterative(Node* expect, Node* phi) {
163 p0->ReplaceInput(0, start); // hack: parameters may be trimmed. 162 p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
164 Node* ret = graph.NewNode(common.Return(), phi, start, start); 163 Node* ret = graph.NewNode(common.Return(), phi, start, start);
165 Node* end = graph.NewNode(common.End(), ret); 164 Node* end = graph.NewNode(common.End(), ret);
166 graph.SetEnd(end); 165 graph.SetEnd(end);
167 ControlReducer::ReduceGraph(main_zone(), &jsgraph, &common); 166 ControlReducer::ReduceGraph(main_zone(), &jsgraph);
168 CheckInputs(end, ret); 167 CheckInputs(end, ret);
169 CheckInputs(ret, expect, start, start); 168 CheckInputs(ret, expect, start, start);
170 } 169 }
171 170
172 void ReduceMerge(Node* expect, Node* merge) { 171 void ReduceMerge(Node* expect, Node* merge) {
173 Node* result = ControlReducer::ReduceMerge(&jsgraph, &common, merge); 172 Node* result = ControlReducer::ReduceMerge(&jsgraph, merge);
174 CHECK_EQ(expect, result); 173 CHECK_EQ(expect, result);
175 } 174 }
176 175
177 void ReduceMergeIterative(Node* expect, Node* merge) { 176 void ReduceMergeIterative(Node* expect, Node* merge) {
178 p0->ReplaceInput(0, start); // hack: parameters may be trimmed. 177 p0->ReplaceInput(0, start); // hack: parameters may be trimmed.
179 Node* end = graph.NewNode(common.End(), merge); 178 Node* end = graph.NewNode(common.End(), merge);
180 graph.SetEnd(end); 179 graph.SetEnd(end);
181 ReduceGraph(); 180 ReduceGraph();
182 CheckInputs(end, expect); 181 CheckInputs(end, expect);
183 } 182 }
184 183
185 void ReduceBranch(Decision expected, Node* branch) { 184 void ReduceBranch(Decision expected, Node* branch) {
186 Node* control = branch->InputAt(1); 185 Node* control = branch->InputAt(1);
187 for (Node* use : branch->uses()) { 186 for (Node* use : branch->uses()) {
188 if (use->opcode() == IrOpcode::kIfTrue) { 187 if (use->opcode() == IrOpcode::kIfTrue) {
189 Node* result = 188 Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use);
190 ControlReducer::ReduceIfNodeForTesting(&jsgraph, &common, use);
191 if (expected == kTrue) CHECK_EQ(control, result); 189 if (expected == kTrue) CHECK_EQ(control, result);
192 if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode()); 190 if (expected == kFalse) CHECK_EQ(IrOpcode::kDead, result->opcode());
193 if (expected == kUnknown) CHECK_EQ(use, result); 191 if (expected == kUnknown) CHECK_EQ(use, result);
194 } else if (use->opcode() == IrOpcode::kIfFalse) { 192 } else if (use->opcode() == IrOpcode::kIfFalse) {
195 Node* result = 193 Node* result = ControlReducer::ReduceIfNodeForTesting(&jsgraph, use);
196 ControlReducer::ReduceIfNodeForTesting(&jsgraph, &common, use);
197 if (expected == kFalse) CHECK_EQ(control, result); 194 if (expected == kFalse) CHECK_EQ(control, result);
198 if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode()); 195 if (expected == kTrue) CHECK_EQ(IrOpcode::kDead, result->opcode());
199 if (expected == kUnknown) CHECK_EQ(use, result); 196 if (expected == kUnknown) CHECK_EQ(use, result);
200 } else { 197 } else {
201 UNREACHABLE(); 198 UNREACHABLE();
202 } 199 }
203 } 200 }
204 } 201 }
205 202
206 Node* Return(Node* val, Node* effect, Node* control) { 203 Node* Return(Node* val, Node* effect, Node* control) {
207 Node* ret = graph.NewNode(common.Return(), val, effect, control); 204 Node* ret = graph.NewNode(common.Return(), val, effect, control);
208 end->ReplaceInput(0, ret); 205 end->ReplaceInput(0, ret);
209 return ret; 206 return ret;
210 } 207 }
211 }; 208 };
212 209
213 210
211 struct Branch {
212 Node* branch;
213 Node* if_true;
214 Node* if_false;
215
216 Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) {
217 if (control == NULL) control = R.start;
218 branch = R.graph.NewNode(R.common.Branch(), cond, control);
219 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
220 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
221 }
222 };
223
224
225 // TODO(titzer): use the diamonds from src/compiler/diamond.h here.
226 struct Diamond {
227 Node* branch;
228 Node* if_true;
229 Node* if_false;
230 Node* merge;
231 Node* phi;
232
233 Diamond(ControlReducerTester& R, Node* cond) {
234 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
235 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
236 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
237 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
238 phi = NULL;
239 }
240
241 Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) {
242 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
243 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
244 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
245 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
246 phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge);
247 }
248
249 void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); }
250
251 // Nest {this} into either the if_true or if_false branch of {that}.
252 void nest(Diamond& that, bool if_true) {
253 if (if_true) {
254 branch->ReplaceInput(1, that.if_true);
255 that.merge->ReplaceInput(0, merge);
256 } else {
257 branch->ReplaceInput(1, that.if_false);
258 that.merge->ReplaceInput(1, merge);
259 }
260 }
261 };
262
263
264 struct While {
265 Node* branch;
266 Node* if_true;
267 Node* exit;
268 Node* loop;
269
270 While(ControlReducerTester& R, Node* cond) {
271 loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
272 branch = R.graph.NewNode(R.common.Branch(), cond, loop);
273 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
274 exit = R.graph.NewNode(R.common.IfFalse(), branch);
275 loop->ReplaceInput(1, if_true);
276 }
277
278 void chain(Node* control) { loop->ReplaceInput(0, control); }
279 };
280
281
282 // Helper for checking that nodes are *not* reachable from end.
283 struct DeadChecker {
284 Zone zone;
285 AllNodes nodes;
286 explicit DeadChecker(Graph* graph) : zone(), nodes(&zone, graph) {}
287
288 void Check(Node* node) { CHECK(!nodes.IsLive(node)); }
289
290 void Check(Diamond& d) {
291 Check(d.branch);
292 Check(d.if_true);
293 Check(d.if_false);
294 Check(d.merge);
295 if (d.phi != NULL) Check(d.phi);
296 }
297
298 void CheckLive(Diamond& d, bool live_phi = true) {
299 CheckInputs(d.merge, d.if_true, d.if_false);
300 CheckInputs(d.if_true, d.branch);
301 CheckInputs(d.if_false, d.branch);
302 if (d.phi != NULL) {
303 if (live_phi) {
304 CHECK_EQ(3, d.phi->InputCount());
305 CHECK_EQ(d.merge, d.phi->InputAt(2));
306 } else {
307 Check(d.phi);
308 }
309 }
310 }
311 };
312
313
214 TEST(Trim1_live) { 314 TEST(Trim1_live) {
215 ControlReducerTester T; 315 ControlReducerTester T;
216 CHECK(IsUsedBy(T.start, T.p0)); 316 CHECK(IsUsedBy(T.start, T.p0));
217 T.graph.SetEnd(T.p0); 317 T.graph.SetEnd(T.p0);
218 T.Trim(); 318 T.Trim();
219 CHECK(IsUsedBy(T.start, T.p0)); 319 CHECK(IsUsedBy(T.start, T.p0));
220 CheckInputs(T.p0, T.start); 320 CheckInputs(T.p0, T.start);
221 } 321 }
222 322
223 323
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 Node* phi_use = 990 Node* phi_use =
891 R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start); 991 R.graph.NewNode(R.common.Phi(kMachAnyTagged, 1), phi, R.start);
892 Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start); 992 Node* ephi_use = R.graph.NewNode(R.common.EffectPhi(1), ephi, R.start);
893 993
894 Selector selector(mask); 994 Selector selector(mask);
895 995
896 for (int i = 0; i < kSelectorSize; i++) { // set up dead merge inputs. 996 for (int i = 0; i < kSelectorSize; i++) { // set up dead merge inputs.
897 if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead); 997 if (!selector.is_selected(i)) merge->ReplaceInput(i, R.dead);
898 } 998 }
899 999
900 Node* result = ControlReducer::ReduceMerge(&R.jsgraph, &R.common, merge); 1000 Node* result = ControlReducer::ReduceMerge(&R.jsgraph, merge);
901 1001
902 int count = selector.count; 1002 int count = selector.count;
903 if (count == 0) { 1003 if (count == 0) {
904 // result should be dead. 1004 // result should be dead.
905 CHECK_EQ(IrOpcode::kDead, result->opcode()); 1005 CHECK_EQ(IrOpcode::kDead, result->opcode());
906 } else if (count == 1) { 1006 } else if (count == 1) {
907 // merge should be replaced with one of the controls. 1007 // merge should be replaced with one of the controls.
908 CHECK_EQ(controls[selector.single_index()], result); 1008 CHECK_EQ(controls[selector.single_index()], result);
909 // Phis should have been directly replaced. 1009 // Phis should have been directly replaced.
910 CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0)); 1010 CHECK_EQ(values[selector.single_index()], phi_use->InputAt(0));
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 for (int i = 0; i < 5; i++) { 1086 for (int i = 0; i < 5; i++) {
987 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start); 1087 Node* merge = R.graph.NewNode(R.common.Merge(1), R.start);
988 for (int j = 0; j < i; j++) { 1088 for (int j = 0; j < i; j++) {
989 merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead); 1089 merge = R.graph.NewNode(R.common.Merge(2), merge, R.dead);
990 } 1090 }
991 R.ReduceMergeIterative(R.start, merge); 1091 R.ReduceMergeIterative(R.start, merge);
992 } 1092 }
993 } 1093 }
994 1094
995 1095
996 struct Branch {
997 Node* branch;
998 Node* if_true;
999 Node* if_false;
1000
1001 Branch(ControlReducerTester& R, Node* cond, Node* control = NULL) {
1002 if (control == NULL) control = R.start;
1003 branch = R.graph.NewNode(R.common.Branch(), cond, control);
1004 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
1005 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
1006 }
1007 };
1008
1009
1010 // TODO(titzer): use the diamonds from src/compiler/diamond.h here.
1011 struct Diamond {
1012 Node* branch;
1013 Node* if_true;
1014 Node* if_false;
1015 Node* merge;
1016 Node* phi;
1017
1018 Diamond(ControlReducerTester& R, Node* cond) {
1019 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
1020 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
1021 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
1022 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
1023 phi = NULL;
1024 }
1025
1026 Diamond(ControlReducerTester& R, Node* cond, Node* tv, Node* fv) {
1027 branch = R.graph.NewNode(R.common.Branch(), cond, R.start);
1028 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
1029 if_false = R.graph.NewNode(R.common.IfFalse(), branch);
1030 merge = R.graph.NewNode(R.common.Merge(2), if_true, if_false);
1031 phi = R.graph.NewNode(R.common.Phi(kMachAnyTagged, 2), tv, fv, merge);
1032 }
1033
1034 void chain(Diamond& that) { branch->ReplaceInput(1, that.merge); }
1035
1036 // Nest {this} into either the if_true or if_false branch of {that}.
1037 void nest(Diamond& that, bool if_true) {
1038 if (if_true) {
1039 branch->ReplaceInput(1, that.if_true);
1040 that.merge->ReplaceInput(0, merge);
1041 } else {
1042 branch->ReplaceInput(1, that.if_false);
1043 that.merge->ReplaceInput(1, merge);
1044 }
1045 }
1046 };
1047
1048
1049 struct While {
1050 Node* branch;
1051 Node* if_true;
1052 Node* exit;
1053 Node* loop;
1054
1055 While(ControlReducerTester& R, Node* cond) {
1056 loop = R.graph.NewNode(R.common.Loop(2), R.start, R.start);
1057 branch = R.graph.NewNode(R.common.Branch(), cond, loop);
1058 if_true = R.graph.NewNode(R.common.IfTrue(), branch);
1059 exit = R.graph.NewNode(R.common.IfFalse(), branch);
1060 loop->ReplaceInput(1, if_true);
1061 }
1062
1063 void chain(Node* control) { loop->ReplaceInput(0, control); }
1064 };
1065
1066
1067 TEST(CBranchReduce_none1) { 1096 TEST(CBranchReduce_none1) {
1068 ControlReducerTester R; 1097 ControlReducerTester R;
1069 Diamond d(R, R.p0); 1098 Diamond d(R, R.p0);
1070 R.ReduceBranch(kUnknown, d.branch); 1099 R.ReduceBranch(kUnknown, d.branch);
1071 } 1100 }
1072 1101
1073 1102
1074 TEST(CBranchReduce_none2) { 1103 TEST(CBranchReduce_none2) {
1075 ControlReducerTester R; 1104 ControlReducerTester R;
1076 Diamond d1(R, R.p0); 1105 Diamond d1(R, R.p0);
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1230 1259
1231 1260
1232 TEST(CDeadLoop1) { 1261 TEST(CDeadLoop1) {
1233 ControlReducerTester R; 1262 ControlReducerTester R;
1234 1263
1235 Node* loop = R.graph.NewNode(R.common.Loop(1), R.start); 1264 Node* loop = R.graph.NewNode(R.common.Loop(1), R.start);
1236 Branch b(R, R.p0, loop); 1265 Branch b(R, R.p0, loop);
1237 loop->ReplaceInput(0, b.if_true); // loop is not connected to start. 1266 loop->ReplaceInput(0, b.if_true); // loop is not connected to start.
1238 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, b.if_false); 1267 Node* merge = R.graph.NewNode(R.common.Merge(2), R.start, b.if_false);
1239 R.ReduceMergeIterative(R.start, merge); 1268 R.ReduceMergeIterative(R.start, merge);
1240 CHECK(b.if_true->IsDead()); 1269
1241 CHECK(b.if_false->IsDead()); 1270 DeadChecker dead(&R.graph);
1271 dead.Check(b.if_true);
1272 dead.Check(b.if_false);
1273 dead.Check(b.branch);
1274 dead.Check(loop);
1242 } 1275 }
1243 1276
1244 1277
1245 TEST(CDeadLoop2) { 1278 TEST(CDeadLoop2) {
1246 ControlReducerTester R; 1279 ControlReducerTester R;
1247 1280
1248 While w(R, R.p0); 1281 While w(R, R.p0);
1249 Diamond d(R, R.zero); 1282 Diamond d(R, R.zero);
1250 // if (0) { while (p0) ; } else { } 1283 // if (0) { while (p0) ; } else { }
1251 w.branch->ReplaceInput(1, d.if_true); 1284 w.branch->ReplaceInput(1, d.if_true);
1252 d.merge->ReplaceInput(0, w.exit); 1285 d.merge->ReplaceInput(0, w.exit);
1253 1286
1254 R.ReduceMergeIterative(R.start, d.merge); 1287 R.ReduceMergeIterative(R.start, d.merge);
1255 CHECK(d.if_true->IsDead()); 1288
1256 CHECK(d.if_false->IsDead()); 1289 DeadChecker dead(&R.graph);
1290 dead.Check(d);
1291 dead.Check(w.loop);
1257 } 1292 }
1258 1293
1259 1294
1260 TEST(Return1) { 1295 TEST(Return1) {
1261 ControlReducerTester R; 1296 ControlReducerTester R;
1262 Node* ret = R.Return(R.one, R.start, R.start); 1297 Node* ret = R.Return(R.one, R.start, R.start);
1263 R.ReduceGraph(); 1298 R.ReduceGraph();
1264 CheckInputs(R.graph.end(), ret); 1299 CheckInputs(R.graph.end(), ret);
1265 CheckInputs(ret, R.one, R.start, R.start); 1300 CheckInputs(ret, R.one, R.start, R.start);
1266 } 1301 }
1267 1302
1268 1303
1269 TEST(Return2) { 1304 TEST(Return2) {
1270 ControlReducerTester R; 1305 ControlReducerTester R;
1271 Diamond d(R, R.one); 1306 Diamond d(R, R.one);
1272 Node* ret = R.Return(R.half, R.start, d.merge); 1307 Node* ret = R.Return(R.half, R.start, d.merge);
1273 R.ReduceGraph(); 1308 R.ReduceGraph();
1274 CHECK(d.branch->IsDead()); 1309
1275 CHECK(d.if_true->IsDead()); 1310 DeadChecker dead(&R.graph);
1276 CHECK(d.if_false->IsDead()); 1311 dead.Check(d.branch);
1277 CHECK(d.merge->IsDead()); 1312 dead.Check(d.if_true);
1313 dead.Check(d.if_false);
1314 dead.Check(d.merge);
1278 1315
1279 CheckInputs(R.graph.end(), ret); 1316 CheckInputs(R.graph.end(), ret);
1280 CheckInputs(ret, R.half, R.start, R.start); 1317 CheckInputs(ret, R.half, R.start, R.start);
1281 } 1318 }
1282 1319
1283 1320
1284 TEST(Return_true1) { 1321 TEST(Return_true1) {
1285 ControlReducerTester R; 1322 ControlReducerTester R;
1286 Diamond d(R, R.one, R.half, R.zero); 1323 Diamond d(R, R.one, R.half, R.zero);
1287 Node* ret = R.Return(d.phi, R.start, d.merge); 1324 Node* ret = R.Return(d.phi, R.start, d.merge);
1288 R.ReduceGraph(); 1325 R.ReduceGraph();
1289 CHECK(d.branch->IsDead()); 1326
1290 CHECK(d.if_true->IsDead()); 1327 DeadChecker dead(&R.graph);
1291 CHECK(d.if_false->IsDead()); 1328 dead.Check(d.branch);
1292 CHECK(d.merge->IsDead()); 1329 dead.Check(d.if_true);
1293 CHECK(d.phi->IsDead()); 1330 dead.Check(d.if_false);
1331 dead.Check(d.merge);
1332 dead.Check(d.phi);
1294 1333
1295 CheckInputs(R.graph.end(), ret); 1334 CheckInputs(R.graph.end(), ret);
1296 CheckInputs(ret, R.half, R.start, R.start); 1335 CheckInputs(ret, R.half, R.start, R.start);
1297 } 1336 }
1298 1337
1299 1338
1300 TEST(Return_false1) { 1339 TEST(Return_false1) {
1301 ControlReducerTester R; 1340 ControlReducerTester R;
1302 Diamond d(R, R.zero, R.one, R.half); 1341 Diamond d(R, R.zero, R.one, R.half);
1303 Node* ret = R.Return(d.phi, R.start, d.merge); 1342 Node* ret = R.Return(d.phi, R.start, d.merge);
1304 R.ReduceGraph(); 1343 R.ReduceGraph();
1305 CHECK(d.branch->IsDead()); 1344
1306 CHECK(d.if_true->IsDead()); 1345 DeadChecker dead(&R.graph);
1307 CHECK(d.if_false->IsDead()); 1346 dead.Check(d.branch);
1308 CHECK(d.merge->IsDead()); 1347 dead.Check(d.if_true);
1309 CHECK(d.phi->IsDead()); 1348 dead.Check(d.if_false);
1349 dead.Check(d.merge);
1350 dead.Check(d.phi);
1310 1351
1311 CheckInputs(R.graph.end(), ret); 1352 CheckInputs(R.graph.end(), ret);
1312 CheckInputs(ret, R.half, R.start, R.start); 1353 CheckInputs(ret, R.half, R.start, R.start);
1313 } 1354 }
1314 1355
1315 1356
1316 void CheckDeadDiamond(Diamond& d) {
1317 CHECK(d.branch->IsDead());
1318 CHECK(d.if_true->IsDead());
1319 CHECK(d.if_false->IsDead());
1320 CHECK(d.merge->IsDead());
1321 if (d.phi != NULL) CHECK(d.phi->IsDead());
1322 }
1323
1324
1325 void CheckLiveDiamond(Diamond& d, bool live_phi = true) {
1326 CheckInputs(d.merge, d.if_true, d.if_false);
1327 CheckInputs(d.if_true, d.branch);
1328 CheckInputs(d.if_false, d.branch);
1329 if (d.phi != NULL) {
1330 if (live_phi) {
1331 CHECK_EQ(3, d.phi->InputCount());
1332 CHECK_EQ(d.merge, d.phi->InputAt(2));
1333 } else {
1334 CHECK(d.phi->IsDead());
1335 }
1336 }
1337 }
1338
1339
1340 TEST(Return_effect1) { 1357 TEST(Return_effect1) {
1341 ControlReducerTester R; 1358 ControlReducerTester R;
1342 Diamond d(R, R.one); 1359 Diamond d(R, R.one);
1343 Node* e1 = R.jsgraph.Float64Constant(-100.1); 1360 Node* e1 = R.jsgraph.Float64Constant(-100.1);
1344 Node* e2 = R.jsgraph.Float64Constant(+100.1); 1361 Node* e2 = R.jsgraph.Float64Constant(+100.1);
1345 Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge); 1362 Node* effect = R.graph.NewNode(R.common.EffectPhi(2), e1, e2, d.merge);
1346 Node* ret = R.Return(R.p0, effect, d.merge); 1363 Node* ret = R.Return(R.p0, effect, d.merge);
1347 R.ReduceGraph(); 1364 R.ReduceGraph();
1348 CheckDeadDiamond(d); 1365
1349 CHECK(effect->IsDead()); 1366 DeadChecker dead(&R.graph);
1367 dead.Check(d);
1368 dead.Check(effect);
1350 1369
1351 CheckInputs(R.graph.end(), ret); 1370 CheckInputs(R.graph.end(), ret);
1352 CheckInputs(ret, R.p0, e1, R.start); 1371 CheckInputs(ret, R.p0, e1, R.start);
1353 } 1372 }
1354 1373
1355 1374
1356 TEST(Return_nested_diamonds1) { 1375 TEST(Return_nested_diamonds1) {
1357 ControlReducerTester R; 1376 ControlReducerTester R;
1358 Diamond d1(R, R.p0, R.one, R.zero); 1377 Diamond d2(R, R.p0, R.one, R.zero);
1359 Diamond d2(R, R.p0); 1378 Diamond d3(R, R.p0, R.one, R.zero);
1360 Diamond d3(R, R.p0); 1379 Diamond d1(R, R.p0, d2.phi, d3.phi);
1361 1380
1362 d2.nest(d1, true); 1381 d2.nest(d1, true);
1363 d3.nest(d1, false); 1382 d3.nest(d1, false);
1364 1383
1365 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1384 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1366 1385
1367 R.ReduceGraph(); // nothing should happen. 1386 R.ReduceGraph(); // nothing should happen.
1368 1387
1369 CheckInputs(ret, d1.phi, R.start, d1.merge); 1388 CheckInputs(ret, d1.phi, R.start, d1.merge);
1389 CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge);
1390 CheckInputs(d1.merge, d2.merge, d3.merge);
1391
1392 DeadChecker dead(&R.graph);
1393 dead.CheckLive(d2);
1394 dead.CheckLive(d3);
1395 }
1396
1397
1398 TEST(Return_nested_diamonds1_dead1) {
1399 ControlReducerTester R;
1400 Diamond d2(R, R.p0); // dead diamond
1401 Diamond d3(R, R.p0, R.one, R.zero);
1402 Diamond d1(R, R.p0, R.one, d3.phi);
1403
1404 d2.nest(d1, true);
1405 d3.nest(d1, false);
1406
1407 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1408
1409 R.ReduceGraph();
1410
1411 CheckInputs(ret, d1.phi, R.start, d1.merge);
1412 CheckInputs(d1.phi, R.one, d3.phi, d1.merge);
1413 CheckInputs(d1.merge, d1.if_true, d3.merge);
1414
1415 DeadChecker dead(&R.graph);
1416 dead.Check(d2); // d2 was a dead diamond.
1417 dead.CheckLive(d3);
1418 }
1419
1420
1421 TEST(Return_nested_diamonds1_dead2) {
1422 ControlReducerTester R;
1423 Diamond d2(R, R.p0); // dead diamond
1424 Diamond d3(R, R.p0); // dead diamond
1425 Diamond d1(R, R.p0, R.one, R.zero);
1426
1427 d2.nest(d1, true);
1428 d3.nest(d1, false);
1429
1430 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1431
1432 R.ReduceGraph();
1433
1434 CheckInputs(ret, d1.phi, R.start, d1.merge);
1370 CheckInputs(d1.phi, R.one, R.zero, d1.merge); 1435 CheckInputs(d1.phi, R.one, R.zero, d1.merge);
1371 CheckInputs(d1.merge, d1.if_true, d1.if_false); 1436 CheckInputs(d1.merge, d1.if_true, d1.if_false);
1437
1438 DeadChecker dead(&R.graph);
1439 dead.Check(d2);
1440 dead.Check(d3);
1372 } 1441 }
1373 1442
1374 1443
1375 TEST(Return_nested_diamonds_true1) { 1444 TEST(Return_nested_diamonds_true1) {
1376 ControlReducerTester R; 1445 ControlReducerTester R;
1377 Diamond d1(R, R.one, R.one, R.zero); 1446 Diamond d2(R, R.p0, R.one, R.zero);
1378 Diamond d2(R, R.p0); 1447 Diamond d1(R, R.one, d2.phi, R.zero);
1379 Diamond d3(R, R.p0); 1448 Diamond d3(R, R.p0);
1380 1449
1381 d2.nest(d1, true); 1450 d2.nest(d1, true);
1382 d3.nest(d1, false); 1451 d3.nest(d1, false);
1383 1452
1384 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1453 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1385 1454
1386 R.ReduceGraph(); // d1 gets folded true. 1455 R.ReduceGraph(); // d1 gets folded true.
1387 1456
1388 CheckInputs(ret, R.one, R.start, R.start); 1457 CheckInputs(ret, d2.phi, R.start, d2.merge);
1458 CheckInputs(d2.branch, R.p0, R.start);
1459
1460 DeadChecker dead(&R.graph);
1461 dead.Check(d1);
1462 dead.CheckLive(d2);
1463 dead.Check(d3);
1389 } 1464 }
1390 1465
1391 1466
1392 TEST(Return_nested_diamonds_false1) { 1467 TEST(Return_nested_diamonds_false1) {
1393 ControlReducerTester R; 1468 ControlReducerTester R;
1394 Diamond d1(R, R.zero, R.one, R.zero); 1469 Diamond d3(R, R.p0, R.one, R.zero);
1470 Diamond d1(R, R.zero, R.one, d3.phi);
1395 Diamond d2(R, R.p0); 1471 Diamond d2(R, R.p0);
1396 Diamond d3(R, R.p0);
1397 1472
1398 d2.nest(d1, true); 1473 d2.nest(d1, true);
1399 d3.nest(d1, false); 1474 d3.nest(d1, false);
1400 1475
1401 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1476 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1402 1477
1403 R.ReduceGraph(); // d1 gets folded false. 1478 R.ReduceGraph(); // d1 gets folded false.
1404 1479
1405 CheckInputs(ret, R.zero, R.start, R.start); 1480 CheckInputs(ret, d3.phi, R.start, d3.merge);
1481 CheckInputs(d3.branch, R.p0, R.start);
1482
1483 DeadChecker dead(&R.graph);
1484 dead.Check(d1);
1485 dead.Check(d2);
1486 dead.CheckLive(d3);
1406 } 1487 }
1407 1488
1408 1489
1409 TEST(Return_nested_diamonds_true_true1) { 1490 TEST(Return_nested_diamonds_true_true1) {
1410 ControlReducerTester R; 1491 ControlReducerTester R;
1411 Diamond d1(R, R.one, R.one, R.zero); 1492 Diamond d1(R, R.one, R.one, R.zero);
1412 Diamond d2(R, R.one); 1493 Diamond d2(R, R.one);
1413 Diamond d3(R, R.p0); 1494 Diamond d3(R, R.p0);
1414 1495
1415 d2.nest(d1, true); 1496 d2.nest(d1, true);
1416 d3.nest(d1, false); 1497 d3.nest(d1, false);
1417 1498
1418 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1499 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1419 1500
1420 R.ReduceGraph(); // d1 and d2 both get folded true. 1501 R.ReduceGraph(); // d1 and d2 both get folded true.
1421 1502
1422 CheckInputs(ret, R.one, R.start, R.start); 1503 CheckInputs(ret, R.one, R.start, R.start);
1423 CheckDeadDiamond(d1); 1504
1424 CheckDeadDiamond(d2); 1505 DeadChecker dead(&R.graph);
1425 CheckDeadDiamond(d3); 1506 dead.Check(d1);
1507 dead.Check(d2);
1508 dead.Check(d3);
1426 } 1509 }
1427 1510
1428 1511
1429 TEST(Return_nested_diamonds_true_false1) { 1512 TEST(Return_nested_diamonds_true_false1) {
1430 ControlReducerTester R; 1513 ControlReducerTester R;
1431 Diamond d1(R, R.one, R.one, R.zero); 1514 Diamond d1(R, R.one, R.one, R.zero);
1432 Diamond d2(R, R.zero); 1515 Diamond d2(R, R.zero);
1433 Diamond d3(R, R.p0); 1516 Diamond d3(R, R.p0);
1434 1517
1435 d2.nest(d1, true); 1518 d2.nest(d1, true);
1436 d3.nest(d1, false); 1519 d3.nest(d1, false);
1437 1520
1438 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1521 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1439 1522
1440 R.ReduceGraph(); // d1 gets folded true and d2 gets folded false. 1523 R.ReduceGraph(); // d1 gets folded true and d2 gets folded false.
1441 1524
1442 CheckInputs(ret, R.one, R.start, R.start); 1525 CheckInputs(ret, R.one, R.start, R.start);
1443 CheckDeadDiamond(d1); 1526
1444 CheckDeadDiamond(d2); 1527 DeadChecker dead(&R.graph);
1445 CheckDeadDiamond(d3); 1528 dead.Check(d1);
1529 dead.Check(d2);
1530 dead.Check(d3);
1446 } 1531 }
1447 1532
1448 1533
1449 TEST(Return_nested_diamonds2) { 1534 TEST(Return_nested_diamonds2) {
1450 ControlReducerTester R; 1535 ControlReducerTester R;
1451 Node* x2 = R.jsgraph.Float64Constant(11.1); 1536 Node* x2 = R.jsgraph.Float64Constant(11.1);
1452 Node* y2 = R.jsgraph.Float64Constant(22.2); 1537 Node* y2 = R.jsgraph.Float64Constant(22.2);
1453 Node* x3 = R.jsgraph.Float64Constant(33.3); 1538 Node* x3 = R.jsgraph.Float64Constant(33.3);
1454 Node* y3 = R.jsgraph.Float64Constant(44.4); 1539 Node* y3 = R.jsgraph.Float64Constant(44.4);
1455 1540
1456 Diamond d2(R, R.p0, x2, y2); 1541 Diamond d2(R, R.p0, x2, y2);
1457 Diamond d3(R, R.p0, x3, y3); 1542 Diamond d3(R, R.p0, x3, y3);
1458 Diamond d1(R, R.p0, d2.phi, d3.phi); 1543 Diamond d1(R, R.p0, d2.phi, d3.phi);
1459 1544
1460 d2.nest(d1, true); 1545 d2.nest(d1, true);
1461 d3.nest(d1, false); 1546 d3.nest(d1, false);
1462 1547
1463 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1548 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1464 1549
1465 R.ReduceGraph(); // nothing should happen. 1550 R.ReduceGraph(); // nothing should happen.
1466 1551
1467 CheckInputs(ret, d1.phi, R.start, d1.merge); 1552 CheckInputs(ret, d1.phi, R.start, d1.merge);
1468 CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge); 1553 CheckInputs(d1.phi, d2.phi, d3.phi, d1.merge);
1469 CheckInputs(d1.merge, d2.merge, d3.merge); 1554 CheckInputs(d1.merge, d2.merge, d3.merge);
1470 CheckLiveDiamond(d2); 1555
1471 CheckLiveDiamond(d3); 1556 DeadChecker dead(&R.graph);
1557 dead.CheckLive(d2);
1558 dead.CheckLive(d3);
1472 } 1559 }
1473 1560
1474 1561
1475 TEST(Return_nested_diamonds_true2) { 1562 TEST(Return_nested_diamonds_true2) {
1476 ControlReducerTester R; 1563 ControlReducerTester R;
1477 Node* x2 = R.jsgraph.Float64Constant(11.1); 1564 Node* x2 = R.jsgraph.Float64Constant(11.1);
1478 Node* y2 = R.jsgraph.Float64Constant(22.2); 1565 Node* y2 = R.jsgraph.Float64Constant(22.2);
1479 Node* x3 = R.jsgraph.Float64Constant(33.3); 1566 Node* x3 = R.jsgraph.Float64Constant(33.3);
1480 Node* y3 = R.jsgraph.Float64Constant(44.4); 1567 Node* y3 = R.jsgraph.Float64Constant(44.4);
1481 1568
1482 Diamond d2(R, R.p0, x2, y2); 1569 Diamond d2(R, R.p0, x2, y2);
1483 Diamond d3(R, R.p0, x3, y3); 1570 Diamond d3(R, R.p0, x3, y3);
1484 Diamond d1(R, R.one, d2.phi, d3.phi); 1571 Diamond d1(R, R.one, d2.phi, d3.phi);
1485 1572
1486 d2.nest(d1, true); 1573 d2.nest(d1, true);
1487 d3.nest(d1, false); 1574 d3.nest(d1, false);
1488 1575
1489 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1576 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1490 1577
1491 R.ReduceGraph(); // d1 gets folded true. 1578 R.ReduceGraph(); // d1 gets folded true.
1492 1579
1493 CheckInputs(ret, d2.phi, R.start, d2.merge); 1580 CheckInputs(ret, d2.phi, R.start, d2.merge);
1494 CheckInputs(d2.branch, R.p0, R.start); 1581 CheckInputs(d2.branch, R.p0, R.start);
1495 CheckDeadDiamond(d1); 1582
1496 CheckLiveDiamond(d2); 1583 DeadChecker dead(&R.graph);
1497 CheckDeadDiamond(d3); 1584 dead.Check(d1);
1585 dead.CheckLive(d2);
1586 dead.Check(d3);
1498 } 1587 }
1499 1588
1500 1589
1501 TEST(Return_nested_diamonds_true_true2) { 1590 TEST(Return_nested_diamonds_true_true2) {
1502 ControlReducerTester R; 1591 ControlReducerTester R;
1503 Node* x2 = R.jsgraph.Float64Constant(11.1); 1592 Node* x2 = R.jsgraph.Float64Constant(11.1);
1504 Node* y2 = R.jsgraph.Float64Constant(22.2); 1593 Node* y2 = R.jsgraph.Float64Constant(22.2);
1505 Node* x3 = R.jsgraph.Float64Constant(33.3); 1594 Node* x3 = R.jsgraph.Float64Constant(33.3);
1506 Node* y3 = R.jsgraph.Float64Constant(44.4); 1595 Node* y3 = R.jsgraph.Float64Constant(44.4);
1507 1596
1508 Diamond d2(R, R.one, x2, y2); 1597 Diamond d2(R, R.one, x2, y2);
1509 Diamond d3(R, R.p0, x3, y3); 1598 Diamond d3(R, R.p0, x3, y3);
1510 Diamond d1(R, R.one, d2.phi, d3.phi); 1599 Diamond d1(R, R.one, d2.phi, d3.phi);
1511 1600
1512 d2.nest(d1, true); 1601 d2.nest(d1, true);
1513 d3.nest(d1, false); 1602 d3.nest(d1, false);
1514 1603
1515 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1604 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1516 1605
1517 R.ReduceGraph(); // d1 gets folded true. 1606 R.ReduceGraph(); // d1 gets folded true.
1518 1607
1519 CheckInputs(ret, x2, R.start, R.start); 1608 CheckInputs(ret, x2, R.start, R.start);
1520 CheckDeadDiamond(d1); 1609
1521 CheckDeadDiamond(d2); 1610 DeadChecker dead(&R.graph);
1522 CheckDeadDiamond(d3); 1611 dead.Check(d1);
1612 dead.Check(d2);
1613 dead.Check(d3);
1523 } 1614 }
1524 1615
1525 1616
1526 TEST(Return_nested_diamonds_true_false2) { 1617 TEST(Return_nested_diamonds_true_false2) {
1527 ControlReducerTester R; 1618 ControlReducerTester R;
1528 Node* x2 = R.jsgraph.Float64Constant(11.1); 1619 Node* x2 = R.jsgraph.Float64Constant(11.1);
1529 Node* y2 = R.jsgraph.Float64Constant(22.2); 1620 Node* y2 = R.jsgraph.Float64Constant(22.2);
1530 Node* x3 = R.jsgraph.Float64Constant(33.3); 1621 Node* x3 = R.jsgraph.Float64Constant(33.3);
1531 Node* y3 = R.jsgraph.Float64Constant(44.4); 1622 Node* y3 = R.jsgraph.Float64Constant(44.4);
1532 1623
1533 Diamond d2(R, R.zero, x2, y2); 1624 Diamond d2(R, R.zero, x2, y2);
1534 Diamond d3(R, R.p0, x3, y3); 1625 Diamond d3(R, R.p0, x3, y3);
1535 Diamond d1(R, R.one, d2.phi, d3.phi); 1626 Diamond d1(R, R.one, d2.phi, d3.phi);
1536 1627
1537 d2.nest(d1, true); 1628 d2.nest(d1, true);
1538 d3.nest(d1, false); 1629 d3.nest(d1, false);
1539 1630
1540 Node* ret = R.Return(d1.phi, R.start, d1.merge); 1631 Node* ret = R.Return(d1.phi, R.start, d1.merge);
1541 1632
1542 R.ReduceGraph(); // d1 gets folded true. 1633 R.ReduceGraph(); // d1 gets folded true.
1543 1634
1544 CheckInputs(ret, y2, R.start, R.start); 1635 CheckInputs(ret, y2, R.start, R.start);
1545 CheckDeadDiamond(d1); 1636
1546 CheckDeadDiamond(d2); 1637 DeadChecker dead(&R.graph);
1547 CheckDeadDiamond(d3); 1638 dead.Check(d1);
1639 dead.Check(d2);
1640 dead.Check(d3);
1548 } 1641 }
OLDNEW
« no previous file with comments | « src/compiler/pipeline.cc ('k') | test/unittests/compiler/control-reducer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698