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

Side by Side Diff: src/compiler/simd-scalar-lowering.cc

Issue 2294743003: [wasm] simd scalar lowering F32x4Add and I32x4Add (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
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 // Copyright 2016 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/compiler/simd-scalar-lowering.h"
6 #include "src/compiler/diamond.h"
7 #include "src/compiler/linkage.h"
8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h"
10
11 #include "src/compiler/node.h"
12 #include "src/wasm/wasm-module.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17
18 SimdScalarLowering::SimdScalarLowering(
19 Graph* graph, MachineOperatorBuilder* machine,
20 CommonOperatorBuilder* common, Zone* zone,
21 Signature<MachineRepresentation>* signature)
22 : zone_(zone),
23 graph_(graph),
24 machine_(machine),
25 common_(common),
26 state_(graph, 3),
27 stack_(zone),
28 replacements_(nullptr),
29 signature_(signature),
30 placeholder_(graph->NewNode(common->Parameter(-2, "placeholder"),
31 graph->start())) {
32 DCHECK_NOT_NULL(graph);
33 DCHECK_NOT_NULL(graph->end());
34 replacements_ = zone->NewArray<Replacement>(graph->NodeCount());
35 memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount());
36 }
37
38 void SimdScalarLowering::LowerGraph() {
39 stack_.push_back({graph()->end(), 0});
40 state_.Set(graph()->end(), State::kOnStack);
41 replacements_[graph()->end()->id()].type = SimdType::kInt32;
42
43 while (!stack_.empty()) {
44 NodeState& top = stack_.back();
45 if (top.input_index == top.node->InputCount()) {
46 // All inputs of top have already been lowered, now lower top.
47 stack_.pop_back();
48 state_.Set(top.node, State::kVisited);
49 LowerNode(top.node);
50 } else {
51 // Push the next input onto the stack.
52 Node* input = top.node->InputAt(top.input_index++);
53 if (state_.Get(input) == State::kUnvisited) {
54 SetType(input, top.node);
55 if (input->opcode() == IrOpcode::kPhi) {
56 // To break cycles with phi nodes we push phis on a separate stack so
57 // that they are processed after all other nodes.
58 PreparePhiReplacement(input);
59 stack_.push_front({input, 0});
60 } else {
61 stack_.push_back({input, 0});
62 }
63 state_.Set(input, State::kOnStack);
64 }
65 }
66 }
67 }
68
69 #define FOREACH_INT32X4_OPCODE(V) \
70 V(Int32x4Add) \
71 V(Int32x4ExtractLane) \
72 V(CreateInt32x4)
73
74 #define FOREACH_FLOAT32X4_OPCODE(V) \
75 V(Float32x4Add) \
76 V(Float32x4ExtractLane) \
77 V(CreateFloat32x4)
78
bradnelson 2016/08/31 22:42:08 SetLoweredType ?
aseemgarg 2016/10/10 17:35:16 Done.
79 void SimdScalarLowering::SetType(Node* node, Node* output) {
80 switch (node->opcode()) {
81 #define CASE_STMT(name) case IrOpcode::k##name:
82 FOREACH_INT32X4_OPCODE(CASE_STMT)
83 case IrOpcode::kReturn:
84 case IrOpcode::kParameter:
85 case IrOpcode::kCall: {
86 replacements_[node->id()].type = SimdType::kInt32;
87 break;
88 }
89 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
bradnelson 2016/08/31 22:42:08 Indent is weird, did this make it through git cl p
aseemgarg 2016/10/10 17:35:17 Did git cl format. And the changes seem to have ma
90 replacements_[node->id()].type = SimdType::kFloat32;
91 break;
92 }
93 #undef CASE_STMT
94 default:
95 replacements_[node->id()].type = replacements_[output->id()].type;
96 }
97 }
98
99 static int GetParameterIndexAfterLowering(
100 Signature<MachineRepresentation>* signature, int old_index) {
101 int result = old_index;
102 for (int i = 0; i < old_index; i++) {
103 if (signature->GetParam(i) == MachineRepresentation::kSimd128) {
104 result += 3;
bradnelson 2016/08/31 22:42:08 Comment explaining this is single items going to 4
aseemgarg 2016/10/10 17:35:16 Done.
105 }
106 }
107 return result;
108 }
109
110 int SimdScalarLowering::GetParameterCountAfterLowering(
111 Signature<MachineRepresentation>* signature) {
112 // GetParameterIndexAfterLowering(parameter_count) returns the parameter count
113 // after lowering.
114 return GetParameterIndexAfterLowering(
115 signature, static_cast<int>(signature->parameter_count()));
116 }
117
118 static int GetReturnCountAfterLowering(
119 Signature<MachineRepresentation>* signature) {
120 int result = static_cast<int>(signature->return_count());
121 for (int i = 0; i < static_cast<int>(signature->return_count()); i++) {
122 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) {
123 result += 3;
124 }
125 }
126 return result;
127 }
128
129 void SimdScalarLowering::LowerNode(Node* node) {
130 SimdType rep_type = ReplacementType(node);
131 switch (node->opcode()) {
132 case IrOpcode::kStart: {
133 int parameter_count = GetParameterCountAfterLowering(signature());
134 // Only exchange the node if the parameter count actually changed.
135 if (parameter_count != signature()->parameter_count()) {
136 int delta =
137 parameter_count - static_cast<int>(signature()->parameter_count());
138 int new_output_count = node->op()->ValueOutputCount() + delta;
139 NodeProperties::ChangeOp(node, common()->Start(new_output_count));
140 }
141 break;
142 }
143 case IrOpcode::kParameter: {
144 DCHECK(node->InputCount() == 1);
145 // Only exchange the node if the parameter count actually changed. We do
146 // not even have to do the default lowering because the the start node,
147 // the only input of a parameter node, only changes if the parameter count
148 // changes.
149 if (GetParameterCountAfterLowering(signature()) !=
150 signature()->parameter_count()) {
151 int old_index = ParameterIndexOf(node->op());
152 int new_index = GetParameterIndexAfterLowering(signature(), old_index);
153 NodeProperties::ChangeOp(node, common()->Parameter(new_index));
154
155 Node* new_node[4];
bradnelson 2016/08/31 22:42:08 constant
titzer 2016/09/05 12:59:35 Yes, please use kMaxLanes or similar.
aseemgarg 2016/10/10 17:35:16 Done.
156 for (int i = 0; i < 4; i++) {
157 new_node[i] = nullptr;
158 }
159 new_node[0] = node;
160 if (signature()->GetParam(old_index) ==
161 MachineRepresentation::kSimd128) {
162 for (int i = 1; i < 4; i++) {
163 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i),
164 graph()->start());
165 }
166 }
167 ReplaceNode(node, new_node);
168 }
169 break;
170 }
171 case IrOpcode::kReturn: {
172 DefaultLowering(node);
173 int new_return_count = GetReturnCountAfterLowering(signature());
174 if (signature()->return_count() != new_return_count) {
175 NodeProperties::ChangeOp(node, common()->Return(new_return_count));
176 }
177 break;
178 }
179 case IrOpcode::kCall: {
180 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor.
181 CallDescriptor* descriptor =
182 const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
183 if (DefaultLowering(node) ||
184 (descriptor->ReturnCount() == 1 &&
185 descriptor->GetReturnType(0) == MachineType::Simd128())) {
186 // We have to adjust the call descriptor.
187 const Operator* op =
188 common()->Call(wasm::ModuleEnv::GetI32WasmCallDescriptorForSimd(
189 zone(), descriptor));
190 NodeProperties::ChangeOp(node, op);
191 }
192 if (descriptor->ReturnCount() == 1 &&
193 descriptor->GetReturnType(0) == MachineType::Simd128()) {
194 // We access the additional return values through projections.
195 Node* rep_node[4];
196 for (int i = 0; i < 4; i++) {
197 rep_node[i] =
198 graph()->NewNode(common()->Projection(i), node, graph()->start());
199 }
200 ReplaceNode(node, rep_node);
201 }
202 break;
203 }
204 case IrOpcode::kPhi: {
205 MachineRepresentation rep = PhiRepresentationOf(node->op());
206 if (rep == MachineRepresentation::kSimd128) {
207 // The replacement nodes have already been created, we only have to
208 // replace placeholder nodes.
209 Node** rep_node = GetReplacements(node);
210 for (int i = 0; i < node->op()->ValueInputCount(); i++) {
211 Node** rep_input =
212 GetReplacementsWithType(node->InputAt(i), rep_type);
213 for (int j = 0; j < 4; j++) {
214 rep_node[j]->ReplaceInput(i, rep_input[j]);
215 }
216 }
217 } else {
218 DefaultLowering(node);
219 }
220 break;
221 }
222
223 case IrOpcode::kInt32x4Add: {
bradnelson 2016/08/31 22:42:08 Macros might be in order once you have more of the
aseemgarg 2016/10/10 17:35:16 that's the plan. Macros or functions.
224 DCHECK(node->InputCount() == 2);
225 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type);
226 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type);
227 Node* rep_node[4];
228 for (int i = 0; i < 4; i++) {
229 rep_node[i] =
230 graph()->NewNode(machine()->Int32Add(), rep_left[i], rep_right[i]);
231 }
232 ReplaceNode(node, rep_node);
233 break;
234 }
235
236 case IrOpcode::kCreateInt32x4: {
237 Node* rep_node[4];
238 for (int i = 0; i < 4; i++) {
239 DCHECK(!HasReplacementHigh(node->InputAt(i)));
240 rep_node[i] = node->InputAt(i);
241 }
242 ReplaceNode(node, rep_node);
243 break;
244 }
245
246 case IrOpcode::kInt32x4ExtractLane: {
247 Node* rep_node[4] = {
248 GetReplacementsWithType(node->InputAt(0), rep_type)[0], nullptr,
249 nullptr, nullptr};
250 ReplaceNode(node, rep_node);
251 break;
252 }
253
254 case IrOpcode::kFloat32x4Add: {
255 DCHECK(node->InputCount() == 2);
256 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type);
257 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type);
258 Node* rep_node[4];
259 for (int i = 0; i < 4; i++) {
260 rep_node[i] = graph()->NewNode(machine()->Float32Add(), rep_left[i],
261 rep_right[i]);
262 }
263 ReplaceNode(node, rep_node);
264 break;
265 }
266
267 case IrOpcode::kCreateFloat32x4: {
268 Node* rep_node[4];
269 for (int i = 0; i < 4; i++) {
270 DCHECK(!HasReplacementHigh(node->InputAt(i)));
271 rep_node[i] = node->InputAt(i);
272 }
273 ReplaceNode(node, rep_node);
274 break;
275 }
276
277 case IrOpcode::kFloat32x4ExtractLane: {
278 Node* rep_node[4] = {
279 GetReplacementsWithType(node->InputAt(0), rep_type)[0], nullptr,
280 nullptr, nullptr};
281 ReplaceNode(node, rep_node);
282 break;
283 }
284
285 default: { DefaultLowering(node); }
286 }
287 }
288
289 bool SimdScalarLowering::DefaultLowering(Node* node) {
290 bool something_changed = false;
291 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
292 Node* input = node->InputAt(i);
293 if (HasReplacementLow(input)) {
294 something_changed = true;
295 node->ReplaceInput(i, GetReplacements(input)[0]);
296 }
297 if (HasReplacementHigh(input)) {
bradnelson 2016/08/31 22:42:08 This naming from the 64-bit stuff is goofy. HasRep
aseemgarg 2016/10/10 17:35:16 Done.
298 something_changed = true;
299 for (int j = 1; j < 4; j++) {
300 node->InsertInput(zone(), i + j, GetReplacements(input)[j]);
301 }
302 }
303 }
304 return something_changed;
305 }
306
307 void SimdScalarLowering::ReplaceNode(Node* old, Node** new_node) {
308 // if new_low == nullptr, then also new_high == nullptr.
309 DCHECK(new_node[0] != nullptr ||
310 (new_node[1] == nullptr && new_node[2] == nullptr &&
311 new_node[3] == nullptr));
312 for (int i = 0; i < 4; i++) {
313 replacements_[old->id()].node[i] = new_node[i];
314 }
315 }
316
317 bool SimdScalarLowering::HasReplacementLow(Node* node) {
318 return replacements_[node->id()].node[0] != nullptr;
319 }
320
321 bool SimdScalarLowering::HasReplacementHigh(Node* node) {
322 return replacements_[node->id()].node[1] != nullptr;
323 }
324
325 SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) {
326 return replacements_[node->id()].type;
327 }
328
329 Node** SimdScalarLowering::GetReplacements(Node* node) {
330 Node** result = replacements_[node->id()].node;
331 DCHECK(result);
332 return result;
333 }
334
335 Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) {
336 Node** replacements = GetReplacements(node);
337 if (ReplacementType(node) == type) {
338 return GetReplacements(node);
339 }
340 Node** result = zone()->NewArray<Node*>(4);
341 for (int i = 0; i < 4; i++) {
titzer 2016/09/05 12:59:34 No need to initialize these to null if you are goi
aseemgarg 2016/10/10 17:35:16 Actually we do need to mark some null in case ther
342 result[i] = nullptr;
343 }
344 if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) {
titzer 2016/09/05 12:59:34 If you get rid of the kUndefined type, this will b
aseemgarg 2016/10/10 17:35:17 Done.
345 for (int i = 0; i < 4; i++) {
346 if (replacements[i] != nullptr) {
347 result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(),
348 replacements[i]);
349 }
350 }
351 } else if (ReplacementType(node) == SimdType::kFloat32 &&
352 type == SimdType::kInt32) {
353 for (int i = 0; i < 4; i++) {
354 if (replacements[i] != nullptr) {
355 result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(),
356 replacements[i]);
357 }
358 }
359 } else {
360 UNREACHABLE();
361 }
362 return result;
363 }
364
365 void SimdScalarLowering::PreparePhiReplacement(Node* phi) {
366 MachineRepresentation rep = PhiRepresentationOf(phi->op());
367 if (rep == MachineRepresentation::kSimd128) {
368 // We have to create the replacements for a phi node before we actually
369 // lower the phi to break potential cycles in the graph. The replacements of
370 // input nodes do not exist yet, so we use a placeholder node to pass the
371 // graph verifier.
372 int value_count = phi->op()->ValueInputCount();
373 SimdType type = ReplacementType(phi);
374 Node** inputs_rep[4];
375 for (int i = 0; i < 4; i++) {
376 inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1);
377 inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0);
378 }
379 for (int i = 0; i < value_count; i++) {
380 for (int j = 0; j < 4; j++) {
381 inputs_rep[j][i] = placeholder_;
382 }
383 }
384 Node* rep_nodes[4];
385 for (int i = 0; i < 4; i++) {
386 if (type == SimdType::kInt32) {
387 rep_nodes[i] = graph()->NewNode(
388 common()->Phi(MachineRepresentation::kWord32, value_count),
389 value_count + 1, inputs_rep[i], false);
390 } else if (type == SimdType::kFloat32) {
391 rep_nodes[i] = graph()->NewNode(
392 common()->Phi(MachineRepresentation::kFloat32, value_count),
393 value_count + 1, inputs_rep[i], false);
394 } else {
395 UNREACHABLE();
396 }
397 }
398 ReplaceNode(phi, rep_nodes);
399 }
400 }
401 } // namespace compiler
402 } // namespace internal
403 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698