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

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

Powered by Google App Engine
This is Rietveld 408576698