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

Side by Side Diff: test/cctest/compiler/test-osr.cc

Issue 809333002: [turbofan] Implement OSR for outer loops. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 11 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 | « test/cctest/cctest.gyp ('k') | test/mjsunit/compiler/osr-alignment.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/codegen.h"
6 #include "src/compiler/common-operator.h"
7 #include "src/compiler/diamond.h"
8 #include "src/compiler/graph.h"
9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/js-operator.h"
11 #include "src/compiler/operator.h"
12 #include "src/compiler/osr.h"
13 #include "test/cctest/cctest.h"
14
15 using namespace v8::internal;
16 using namespace v8::internal::compiler;
17
18 // TODO(titzer): move this method to a common testing place.
19
20 static int CheckInputs(Node* node, Node* i0 = NULL, Node* i1 = NULL,
21 Node* i2 = NULL, Node* i3 = NULL) {
22 int count = 4;
23 if (i3 == NULL) count = 3;
24 if (i2 == NULL) count = 2;
25 if (i1 == NULL) count = 1;
26 if (i0 == NULL) count = 0;
27 CHECK_EQ(count, node->InputCount());
28 if (i0 != NULL) CHECK_EQ(i0, node->InputAt(0));
29 if (i1 != NULL) CHECK_EQ(i1, node->InputAt(1));
30 if (i2 != NULL) CHECK_EQ(i2, node->InputAt(2));
31 if (i3 != NULL) CHECK_EQ(i3, node->InputAt(3));
32 return count;
33 }
34
35
36 static Operator kIntLt(IrOpcode::kInt32LessThan, Operator::kPure,
37 "Int32LessThan", 2, 0, 0, 1, 0, 0);
38
39
40 static const int kMaxOsrValues = 10;
41
42 class OsrDeconstructorTester : public HandleAndZoneScope {
43 public:
44 explicit OsrDeconstructorTester(int num_values)
45 : isolate(main_isolate()),
46 common(main_zone()),
47 graph(main_zone()),
48 jsgraph(&graph, &common, NULL, NULL),
49 start(graph.NewNode(common.Start(1))),
50 p0(graph.NewNode(common.Parameter(0), start)),
51 end(graph.NewNode(common.End(), start)),
52 osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start)),
53 osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start)),
54 self(graph.NewNode(common.Int32Constant(0xaabbccdd))) {
55 CHECK(num_values <= kMaxOsrValues);
56 graph.SetStart(start);
57 for (int i = 0; i < num_values; i++) {
58 osr_values[i] = graph.NewNode(common.OsrValue(i), osr_loop_entry);
59 }
60 }
61
62 Isolate* isolate;
63 CommonOperatorBuilder common;
64 Graph graph;
65 JSGraph jsgraph;
66 Node* start;
67 Node* p0;
68 Node* end;
69 Node* osr_normal_entry;
70 Node* osr_loop_entry;
71 Node* self;
72 Node* osr_values[kMaxOsrValues];
73
74 Node* NewOsrPhi(Node* loop, Node* incoming, int osr_value, Node* back1 = NULL,
75 Node* back2 = NULL, Node* back3 = NULL) {
76 int count = 5;
77 if (back3 == NULL) count = 4;
78 if (back2 == NULL) count = 3;
79 if (back1 == NULL) count = 2;
80 CHECK_EQ(loop->InputCount(), count);
81 CHECK_EQ(osr_loop_entry, loop->InputAt(1));
82
83 Node* inputs[6];
84 inputs[0] = incoming;
85 inputs[1] = osr_values[osr_value];
86 if (count > 2) inputs[2] = back1;
87 if (count > 3) inputs[3] = back2;
88 if (count > 4) inputs[4] = back3;
89 inputs[count] = loop;
90 return graph.NewNode(common.Phi(kMachAnyTagged, count), count + 1, inputs);
91 }
92
93 Node* NewOsrLoop(int num_backedges, Node* entry = NULL) {
94 CHECK_LT(num_backedges, 4);
95 CHECK_GE(num_backedges, 0);
96 int count = 2 + num_backedges;
97 if (entry == NULL) entry = osr_normal_entry;
98 Node* inputs[5] = {entry, osr_loop_entry, self, self, self};
99
100 Node* loop = graph.NewNode(common.Loop(count), count, inputs);
101 for (int i = 0; i < num_backedges; i++) {
102 loop->ReplaceInput(2 + i, loop);
103 }
104
105 return loop;
106 }
107 };
108
109
110 TEST(Deconstruct_osr0) {
111 OsrDeconstructorTester T(0);
112
113 Node* loop = T.NewOsrLoop(1);
114
115 T.graph.SetEnd(loop);
116
117 OsrHelper helper(0, 0);
118 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
119
120 CheckInputs(loop, T.start, loop);
121 }
122
123
124 TEST(Deconstruct_osr1) {
125 OsrDeconstructorTester T(1);
126
127 Node* loop = T.NewOsrLoop(1);
128 Node* osr_phi =
129 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
130
131 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop);
132 T.graph.SetEnd(ret);
133
134 OsrHelper helper(0, 0);
135 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
136
137 CheckInputs(loop, T.start, loop);
138 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
139 CheckInputs(ret, osr_phi, T.start, loop);
140 }
141
142
143 TEST(Deconstruct_osr_remove_prologue) {
144 OsrDeconstructorTester T(1);
145 Diamond d(&T.graph, &T.common, T.p0);
146 d.Chain(T.osr_normal_entry);
147
148 Node* loop = T.NewOsrLoop(1, d.merge);
149 Node* osr_phi =
150 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
151
152 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop);
153 T.graph.SetEnd(ret);
154
155 OsrHelper helper(0, 0);
156 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
157
158 CheckInputs(loop, T.start, loop);
159 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
160 CheckInputs(ret, osr_phi, T.start, loop);
161
162 // The control before the loop should have been removed.
163 CHECK(d.branch->IsDead());
164 CHECK(d.if_true->IsDead());
165 CHECK(d.if_false->IsDead());
166 CHECK(d.merge->IsDead());
167 }
168
169
170 TEST(Deconstruct_osr_with_body1) {
171 OsrDeconstructorTester T(1);
172
173 Node* loop = T.NewOsrLoop(1);
174
175 Node* branch = T.graph.NewNode(T.common.Branch(), T.p0, loop);
176 Node* if_true = T.graph.NewNode(T.common.IfTrue(), branch);
177 Node* if_false = T.graph.NewNode(T.common.IfFalse(), branch);
178 loop->ReplaceInput(2, if_true);
179
180 Node* osr_phi =
181 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
182
183 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false);
184 T.graph.SetEnd(ret);
185
186 OsrHelper helper(0, 0);
187 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
188
189 CheckInputs(loop, T.start, if_true);
190 CheckInputs(branch, T.p0, loop);
191 CheckInputs(if_true, branch);
192 CheckInputs(if_false, branch);
193 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
194 CheckInputs(ret, osr_phi, T.start, if_false);
195 }
196
197
198 TEST(Deconstruct_osr_with_body2) {
199 OsrDeconstructorTester T(1);
200
201 Node* loop = T.NewOsrLoop(1);
202
203 // Two chained branches in the the body of the loop.
204 Node* branch1 = T.graph.NewNode(T.common.Branch(), T.p0, loop);
205 Node* if_true1 = T.graph.NewNode(T.common.IfTrue(), branch1);
206 Node* if_false1 = T.graph.NewNode(T.common.IfFalse(), branch1);
207
208 Node* branch2 = T.graph.NewNode(T.common.Branch(), T.p0, if_true1);
209 Node* if_true2 = T.graph.NewNode(T.common.IfTrue(), branch2);
210 Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2);
211 loop->ReplaceInput(2, if_true2);
212
213 Node* osr_phi =
214 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
215
216 Node* merge = T.graph.NewNode(T.common.Merge(2), if_false1, if_false2);
217 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, merge);
218 T.graph.SetEnd(ret);
219
220 OsrHelper helper(0, 0);
221 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
222
223 CheckInputs(loop, T.start, if_true2);
224 CheckInputs(branch1, T.p0, loop);
225 CheckInputs(branch2, T.p0, if_true1);
226 CheckInputs(if_true1, branch1);
227 CheckInputs(if_false1, branch1);
228 CheckInputs(if_true2, branch2);
229 CheckInputs(if_false2, branch2);
230
231 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
232 CheckInputs(ret, osr_phi, T.start, merge);
233 CheckInputs(merge, if_false1, if_false2);
234 }
235
236
237 TEST(Deconstruct_osr_with_body3) {
238 OsrDeconstructorTester T(1);
239
240 Node* loop = T.NewOsrLoop(2);
241
242 // Two branches that create two different backedges.
243 Node* branch1 = T.graph.NewNode(T.common.Branch(), T.p0, loop);
244 Node* if_true1 = T.graph.NewNode(T.common.IfTrue(), branch1);
245 Node* if_false1 = T.graph.NewNode(T.common.IfFalse(), branch1);
246
247 Node* branch2 = T.graph.NewNode(T.common.Branch(), T.p0, if_true1);
248 Node* if_true2 = T.graph.NewNode(T.common.IfTrue(), branch2);
249 Node* if_false2 = T.graph.NewNode(T.common.IfFalse(), branch2);
250 loop->ReplaceInput(2, if_false1);
251 loop->ReplaceInput(3, if_true2);
252
253 Node* osr_phi =
254 T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant(),
255 T.jsgraph.ZeroConstant());
256
257 Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, if_false2);
258 T.graph.SetEnd(ret);
259
260 OsrHelper helper(0, 0);
261 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
262
263 CheckInputs(loop, T.start, if_false1, if_true2);
264 CheckInputs(branch1, T.p0, loop);
265 CheckInputs(branch2, T.p0, if_true1);
266 CheckInputs(if_true1, branch1);
267 CheckInputs(if_false1, branch1);
268 CheckInputs(if_true2, branch2);
269 CheckInputs(if_false2, branch2);
270
271 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(),
272 T.jsgraph.ZeroConstant(), loop);
273 CheckInputs(ret, osr_phi, T.start, if_false2);
274 }
OLDNEW
« no previous file with comments | « test/cctest/cctest.gyp ('k') | test/mjsunit/compiler/osr-alignment.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698