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

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

Issue 2843523002: [wasm] Implement simd lowering for I16x8 (Closed)
Patch Set: [wasm] Implement simd lowering for I16x8 Created 3 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/simd-scalar-lowering.h ('k') | test/cctest/wasm/test-run-wasm-simd.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 2016 the V8 project authors. All rights reserved. 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 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/compiler/simd-scalar-lowering.h" 5 #include "src/compiler/simd-scalar-lowering.h"
6 #include "src/compiler/diamond.h" 6 #include "src/compiler/diamond.h"
7 #include "src/compiler/linkage.h" 7 #include "src/compiler/linkage.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 10
11 #include "src/compiler/node.h" 11 #include "src/compiler/node.h"
12 #include "src/objects-inl.h" 12 #include "src/objects-inl.h"
13 #include "src/wasm/wasm-module.h" 13 #include "src/wasm/wasm-module.h"
14 14
15 namespace v8 { 15 namespace v8 {
16 namespace internal { 16 namespace internal {
17 namespace compiler { 17 namespace compiler {
18 18
19 namespace {
20 static const int kNumLanes32 = 4;
21 static const int kNumLanes16 = 8;
22 static const int32_t kMask16 = 0xffff;
23 static const int32_t kShift16 = 16;
24 } // anonymous
25
19 SimdScalarLowering::SimdScalarLowering( 26 SimdScalarLowering::SimdScalarLowering(
20 JSGraph* jsgraph, Signature<MachineRepresentation>* signature) 27 JSGraph* jsgraph, Signature<MachineRepresentation>* signature)
21 : jsgraph_(jsgraph), 28 : jsgraph_(jsgraph),
22 state_(jsgraph->graph(), 3), 29 state_(jsgraph->graph(), 3),
23 stack_(jsgraph_->zone()), 30 stack_(jsgraph_->zone()),
24 replacements_(nullptr), 31 replacements_(nullptr),
25 signature_(signature), 32 signature_(signature),
26 placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"), 33 placeholder_(graph()->NewNode(common()->Parameter(-2, "placeholder"),
27 graph()->start())), 34 graph()->start())),
28 parameter_count_after_lowering_(-1) { 35 parameter_count_after_lowering_(-1) {
29 DCHECK_NOT_NULL(graph()); 36 DCHECK_NOT_NULL(graph());
30 DCHECK_NOT_NULL(graph()->end()); 37 DCHECK_NOT_NULL(graph()->end());
31 replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount()); 38 replacements_ = zone()->NewArray<Replacement>(graph()->NodeCount());
32 memset(replacements_, 0, sizeof(Replacement) * graph()->NodeCount()); 39 memset(replacements_, 0, sizeof(Replacement) * graph()->NodeCount());
33 } 40 }
34 41
35 void SimdScalarLowering::LowerGraph() { 42 void SimdScalarLowering::LowerGraph() {
36 stack_.push_back({graph()->end(), 0}); 43 stack_.push_back({graph()->end(), 0});
37 state_.Set(graph()->end(), State::kOnStack); 44 state_.Set(graph()->end(), State::kOnStack);
38 replacements_[graph()->end()->id()].type = SimdType::kInt32; 45 replacements_[graph()->end()->id()].type = SimdType::kInt32x4;
39 46
40 while (!stack_.empty()) { 47 while (!stack_.empty()) {
41 NodeState& top = stack_.back(); 48 NodeState& top = stack_.back();
42 if (top.input_index == top.node->InputCount()) { 49 if (top.input_index == top.node->InputCount()) {
43 // All inputs of top have already been lowered, now lower top. 50 // All inputs of top have already been lowered, now lower top.
44 stack_.pop_back(); 51 stack_.pop_back();
45 state_.Set(top.node, State::kVisited); 52 state_.Set(top.node, State::kVisited);
46 LowerNode(top.node); 53 LowerNode(top.node);
47 } else { 54 } else {
48 // Push the next input onto the stack. 55 // Push the next input onto the stack.
(...skipping 17 matching lines...) Expand all
66 } 73 }
67 } 74 }
68 75
69 #define FOREACH_INT32X4_OPCODE(V) \ 76 #define FOREACH_INT32X4_OPCODE(V) \
70 V(I32x4Splat) \ 77 V(I32x4Splat) \
71 V(I32x4ExtractLane) \ 78 V(I32x4ExtractLane) \
72 V(I32x4ReplaceLane) \ 79 V(I32x4ReplaceLane) \
73 V(I32x4SConvertF32x4) \ 80 V(I32x4SConvertF32x4) \
74 V(I32x4UConvertF32x4) \ 81 V(I32x4UConvertF32x4) \
75 V(I32x4Neg) \ 82 V(I32x4Neg) \
83 V(I32x4Shl) \
84 V(I32x4ShrS) \
76 V(I32x4Add) \ 85 V(I32x4Add) \
77 V(I32x4Sub) \ 86 V(I32x4Sub) \
78 V(I32x4Mul) \ 87 V(I32x4Mul) \
79 V(I32x4MinS) \ 88 V(I32x4MinS) \
80 V(I32x4MaxS) \ 89 V(I32x4MaxS) \
90 V(I32x4ShrU) \
81 V(I32x4MinU) \ 91 V(I32x4MinU) \
82 V(I32x4MaxU) \ 92 V(I32x4MaxU) \
83 V(S128And) \ 93 V(S128And) \
84 V(S128Or) \ 94 V(S128Or) \
85 V(S128Xor) \ 95 V(S128Xor) \
86 V(S128Not) 96 V(S128Not)
87 97
88 #define FOREACH_FLOAT32X4_OPCODE(V) \ 98 #define FOREACH_FLOAT32X4_OPCODE(V) \
89 V(F32x4Splat) \ 99 V(F32x4Splat) \
90 V(F32x4ExtractLane) \ 100 V(F32x4ExtractLane) \
(...skipping 21 matching lines...) Expand all
112 V(I32x4Ne) \ 122 V(I32x4Ne) \
113 V(I32x4LtS) \ 123 V(I32x4LtS) \
114 V(I32x4LeS) \ 124 V(I32x4LeS) \
115 V(I32x4GtS) \ 125 V(I32x4GtS) \
116 V(I32x4GeS) \ 126 V(I32x4GeS) \
117 V(I32x4LtU) \ 127 V(I32x4LtU) \
118 V(I32x4LeU) \ 128 V(I32x4LeU) \
119 V(I32x4GtU) \ 129 V(I32x4GtU) \
120 V(I32x4GeU) 130 V(I32x4GeU)
121 131
132 #define FOREACH_INT16X8_OPCODE(V) \
133 V(I16x8Splat) \
134 V(I16x8ExtractLane) \
135 V(I16x8ReplaceLane) \
136 V(I16x8Neg) \
137 V(I16x8Shl) \
138 V(I16x8ShrS) \
139 V(I16x8Add) \
140 V(I16x8AddSaturateS) \
141 V(I16x8Sub) \
142 V(I16x8SubSaturateS) \
143 V(I16x8Mul) \
144 V(I16x8MinS) \
145 V(I16x8MaxS) \
146 V(I16x8ShrU) \
147 V(I16x8AddSaturateU) \
148 V(I16x8SubSaturateU) \
149 V(I16x8MinU) \
150 V(I16x8MaxU)
151
152 #define FOREACH_INT16X8_TO_SIMD1X8OPCODE(V) \
153 V(I16x8Eq) \
154 V(I16x8Ne) \
155 V(I16x8LtS) \
156 V(I16x8LeS) \
157 V(I16x8LtU) \
158 V(I16x8LeU)
159
160 #define FOREACH_SIMD_TYPE_TO_MACHINE_TYPE(V) \
161 V(Float32x4, Float32) \
162 V(Int32x4, Int32) \
163 V(Int16x8, Int16)
164
165 #define FOREACH_SIMD_TYPE_TO_MACHINE_REP(V) \
166 V(Float32x4, Float32) \
167 V(Int32x4, Word32) \
168 V(Int16x8, Word16)
169
122 void SimdScalarLowering::SetLoweredType(Node* node, Node* output) { 170 void SimdScalarLowering::SetLoweredType(Node* node, Node* output) {
123 switch (node->opcode()) { 171 switch (node->opcode()) {
124 #define CASE_STMT(name) case IrOpcode::k##name: 172 #define CASE_STMT(name) case IrOpcode::k##name:
125 FOREACH_INT32X4_OPCODE(CASE_STMT) 173 FOREACH_INT32X4_OPCODE(CASE_STMT)
126 case IrOpcode::kReturn: 174 case IrOpcode::kReturn:
127 case IrOpcode::kParameter: 175 case IrOpcode::kParameter:
128 case IrOpcode::kCall: { 176 case IrOpcode::kCall: {
129 replacements_[node->id()].type = SimdType::kInt32; 177 replacements_[node->id()].type = SimdType::kInt32x4;
130 break; 178 break;
131 } 179 }
132 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) { 180 FOREACH_FLOAT32X4_OPCODE(CASE_STMT) {
133 replacements_[node->id()].type = SimdType::kFloat32; 181 replacements_[node->id()].type = SimdType::kFloat32x4;
134 break; 182 break;
135 } 183 }
136 FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT) 184 FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
137 FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT) { 185 FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT) {
138 replacements_[node->id()].type = SimdType::kSimd1x4; 186 replacements_[node->id()].type = SimdType::kSimd1x4;
139 break; 187 break;
140 } 188 }
189 FOREACH_INT16X8_OPCODE(CASE_STMT) {
190 replacements_[node->id()].type = SimdType::kInt16x8;
191 break;
192 }
193 FOREACH_INT16X8_TO_SIMD1X8OPCODE(CASE_STMT) {
194 replacements_[node->id()].type = SimdType::kSimd1x8;
195 break;
196 }
141 default: { 197 default: {
142 switch (output->opcode()) { 198 switch (output->opcode()) {
143 FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT) 199 FOREACH_FLOAT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
144 case IrOpcode::kF32x4SConvertI32x4: 200 case IrOpcode::kF32x4SConvertI32x4:
145 case IrOpcode::kF32x4UConvertI32x4: { 201 case IrOpcode::kF32x4UConvertI32x4: {
146 replacements_[node->id()].type = SimdType::kInt32; 202 replacements_[node->id()].type = SimdType::kInt32x4;
147 break; 203 break;
148 } 204 }
149 FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT) 205 FOREACH_INT32X4_TO_SIMD1X4OPCODE(CASE_STMT)
150 case IrOpcode::kI32x4SConvertF32x4: 206 case IrOpcode::kI32x4SConvertF32x4:
151 case IrOpcode::kI32x4UConvertF32x4: { 207 case IrOpcode::kI32x4UConvertF32x4: {
152 replacements_[node->id()].type = SimdType::kFloat32; 208 replacements_[node->id()].type = SimdType::kFloat32x4;
153 break; 209 break;
154 } 210 }
155 case IrOpcode::kS32x4Select: { 211 case IrOpcode::kS32x4Select: {
156 replacements_[node->id()].type = SimdType::kSimd1x4; 212 replacements_[node->id()].type = SimdType::kSimd1x4;
157 break; 213 break;
158 } 214 }
215 FOREACH_INT16X8_TO_SIMD1X8OPCODE(CASE_STMT) {
216 replacements_[node->id()].type = SimdType::kInt16x8;
217 break;
218 }
219 case IrOpcode::kS16x8Select: {
220 replacements_[node->id()].type = SimdType::kSimd1x8;
221 break;
222 }
159 default: { 223 default: {
160 replacements_[node->id()].type = replacements_[output->id()].type; 224 replacements_[node->id()].type = replacements_[output->id()].type;
161 } 225 }
162 } 226 }
163 } 227 }
164 #undef CASE_STMT 228 #undef CASE_STMT
165 } 229 }
166 } 230 }
167 231
168 static int GetParameterIndexAfterLowering( 232 static int GetParameterIndexAfterLowering(
(...skipping 23 matching lines...) Expand all
192 Signature<MachineRepresentation>* signature) { 256 Signature<MachineRepresentation>* signature) {
193 int result = static_cast<int>(signature->return_count()); 257 int result = static_cast<int>(signature->return_count());
194 for (int i = 0; i < static_cast<int>(signature->return_count()); ++i) { 258 for (int i = 0; i < static_cast<int>(signature->return_count()); ++i) {
195 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) { 259 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) {
196 result += 3; 260 result += 3;
197 } 261 }
198 } 262 }
199 return result; 263 return result;
200 } 264 }
201 265
202 void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices) { 266 int SimdScalarLowering::NumLanes(SimdType type) {
267 int num_lanes = 0;
268 if (type == SimdType::kFloat32x4 || type == SimdType::kInt32x4 ||
269 type == SimdType::kSimd1x4) {
270 num_lanes = kNumLanes32;
271 } else if (type == SimdType::kInt16x8 || type == SimdType::kSimd1x8) {
272 num_lanes = kNumLanes16;
273 } else {
274 UNREACHABLE();
275 }
276 return num_lanes;
277 }
278
279 void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices,
280 SimdType type) {
203 new_indices[0] = index; 281 new_indices[0] = index;
204 for (size_t i = 1; i < kMaxLanes; ++i) { 282 int num_lanes = NumLanes(type);
283 int lane_width = kSimd128Size / num_lanes;
284 for (int i = 1; i < num_lanes; ++i) {
205 new_indices[i] = graph()->NewNode(machine()->Int32Add(), index, 285 new_indices[i] = graph()->NewNode(machine()->Int32Add(), index,
206 graph()->NewNode(common()->Int32Constant( 286 graph()->NewNode(common()->Int32Constant(
207 static_cast<int>(i) * kLaneWidth))); 287 static_cast<int>(i) * lane_width)));
208 } 288 }
209 } 289 }
210 290
211 void SimdScalarLowering::LowerLoadOp(MachineRepresentation rep, Node* node, 291 void SimdScalarLowering::LowerLoadOp(MachineRepresentation rep, Node* node,
212 const Operator* load_op) { 292 const Operator* load_op, SimdType type) {
213 if (rep == MachineRepresentation::kSimd128) { 293 if (rep == MachineRepresentation::kSimd128) {
214 Node* base = node->InputAt(0); 294 Node* base = node->InputAt(0);
215 Node* index = node->InputAt(1); 295 Node* index = node->InputAt(1);
216 Node* indices[kMaxLanes]; 296 int num_lanes = NumLanes(type);
217 GetIndexNodes(index, indices); 297 Node** indices = zone()->NewArray<Node*>(num_lanes);
218 Node* rep_nodes[kMaxLanes]; 298 GetIndexNodes(index, indices, type);
299 Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
219 rep_nodes[0] = node; 300 rep_nodes[0] = node;
220 NodeProperties::ChangeOp(rep_nodes[0], load_op); 301 NodeProperties::ChangeOp(rep_nodes[0], load_op);
221 if (node->InputCount() > 2) { 302 if (node->InputCount() > 2) {
222 DCHECK(node->InputCount() > 3); 303 DCHECK(node->InputCount() > 3);
223 Node* effect_input = node->InputAt(2); 304 Node* effect_input = node->InputAt(2);
224 Node* control_input = node->InputAt(3); 305 Node* control_input = node->InputAt(3);
225 rep_nodes[3] = graph()->NewNode(load_op, base, indices[3], effect_input, 306 for (int i = num_lanes - 1; i > 0; --i) {
226 control_input); 307 rep_nodes[i] = graph()->NewNode(load_op, base, indices[i], effect_input,
227 rep_nodes[2] = graph()->NewNode(load_op, base, indices[2], rep_nodes[3], 308 control_input);
228 control_input); 309 effect_input = rep_nodes[i];
229 rep_nodes[1] = graph()->NewNode(load_op, base, indices[1], rep_nodes[2], 310 }
230 control_input);
231 rep_nodes[0]->ReplaceInput(2, rep_nodes[1]); 311 rep_nodes[0]->ReplaceInput(2, rep_nodes[1]);
232 } else { 312 } else {
233 for (size_t i = 1; i < kMaxLanes; ++i) { 313 for (int i = 1; i < num_lanes; ++i) {
234 rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]); 314 rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]);
235 } 315 }
236 } 316 }
237 ReplaceNode(node, rep_nodes); 317 ReplaceNode(node, rep_nodes, num_lanes);
238 } else { 318 } else {
239 DefaultLowering(node); 319 DefaultLowering(node);
240 } 320 }
241 } 321 }
242 322
243 void SimdScalarLowering::LowerStoreOp(MachineRepresentation rep, Node* node, 323 void SimdScalarLowering::LowerStoreOp(MachineRepresentation rep, Node* node,
244 const Operator* store_op, 324 const Operator* store_op,
245 SimdType rep_type) { 325 SimdType rep_type) {
246 if (rep == MachineRepresentation::kSimd128) { 326 if (rep == MachineRepresentation::kSimd128) {
247 Node* base = node->InputAt(0); 327 Node* base = node->InputAt(0);
248 Node* index = node->InputAt(1); 328 Node* index = node->InputAt(1);
249 Node* indices[kMaxLanes]; 329 int num_lanes = NumLanes(rep_type);
250 GetIndexNodes(index, indices); 330 Node** indices = zone()->NewArray<Node*>(num_lanes);
331 GetIndexNodes(index, indices, rep_type);
251 DCHECK(node->InputCount() > 2); 332 DCHECK(node->InputCount() > 2);
252 Node* value = node->InputAt(2); 333 Node* value = node->InputAt(2);
253 DCHECK(HasReplacement(1, value)); 334 DCHECK(HasReplacement(1, value));
254 Node* rep_nodes[kMaxLanes]; 335 Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
255 rep_nodes[0] = node; 336 rep_nodes[0] = node;
256 Node** rep_inputs = GetReplacementsWithType(value, rep_type); 337 Node** rep_inputs = GetReplacementsWithType(value, rep_type);
257 rep_nodes[0]->ReplaceInput(2, rep_inputs[0]); 338 rep_nodes[0]->ReplaceInput(2, rep_inputs[0]);
258 NodeProperties::ChangeOp(node, store_op); 339 NodeProperties::ChangeOp(node, store_op);
259 if (node->InputCount() > 3) { 340 if (node->InputCount() > 3) {
260 DCHECK(node->InputCount() > 4); 341 DCHECK(node->InputCount() > 4);
261 Node* effect_input = node->InputAt(3); 342 Node* effect_input = node->InputAt(3);
262 Node* control_input = node->InputAt(4); 343 Node* control_input = node->InputAt(4);
263 rep_nodes[3] = graph()->NewNode(store_op, base, indices[3], rep_inputs[3], 344 for (int i = num_lanes - 1; i > 0; --i) {
264 effect_input, control_input); 345 rep_nodes[i] =
265 rep_nodes[2] = graph()->NewNode(store_op, base, indices[2], rep_inputs[2], 346 graph()->NewNode(store_op, base, indices[i], rep_inputs[i],
266 rep_nodes[3], control_input); 347 effect_input, control_input);
267 rep_nodes[1] = graph()->NewNode(store_op, base, indices[1], rep_inputs[1], 348 effect_input = rep_nodes[i];
268 rep_nodes[2], control_input); 349 }
269 rep_nodes[0]->ReplaceInput(3, rep_nodes[1]); 350 rep_nodes[0]->ReplaceInput(3, rep_nodes[1]);
270 351
271 } else { 352 } else {
272 for (size_t i = 1; i < kMaxLanes; ++i) { 353 for (int i = 1; i < num_lanes; ++i) {
273 rep_nodes[i] = 354 rep_nodes[i] =
274 graph()->NewNode(store_op, base, indices[i], rep_inputs[i]); 355 graph()->NewNode(store_op, base, indices[i], rep_inputs[i]);
275 } 356 }
276 } 357 }
277 358
278 ReplaceNode(node, rep_nodes); 359 ReplaceNode(node, rep_nodes, num_lanes);
279 } else { 360 } else {
280 DefaultLowering(node); 361 DefaultLowering(node);
281 } 362 }
282 } 363 }
283 364
284 void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type, 365 void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType input_rep_type,
285 const Operator* op, bool invert_inputs) { 366 const Operator* op, bool invert_inputs) {
286 DCHECK(node->InputCount() == 2); 367 DCHECK(node->InputCount() == 2);
287 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type); 368 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
288 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type); 369 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
289 Node* rep_node[kMaxLanes]; 370 int num_lanes = NumLanes(input_rep_type);
290 for (int i = 0; i < kMaxLanes; ++i) { 371 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
372 for (int i = 0; i < num_lanes; ++i) {
291 if (invert_inputs) { 373 if (invert_inputs) {
292 rep_node[i] = graph()->NewNode(op, rep_right[i], rep_left[i]); 374 rep_node[i] = graph()->NewNode(op, rep_right[i], rep_left[i]);
293 } else { 375 } else {
294 rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]); 376 rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]);
295 } 377 }
296 } 378 }
297 ReplaceNode(node, rep_node); 379 ReplaceNode(node, rep_node, num_lanes);
380 }
381
382 Node* SimdScalarLowering::FixUpperBits(Node* input, int32_t shift) {
383 return graph()->NewNode(machine()->Word32Sar(),
384 graph()->NewNode(machine()->Word32Shl(), input,
385 jsgraph_->Int32Constant(shift)),
386 jsgraph_->Int32Constant(shift));
387 }
388
389 void SimdScalarLowering::LowerBinaryOpForSmallInt(Node* node,
390 SimdType input_rep_type,
391 const Operator* op) {
392 DCHECK(node->InputCount() == 2);
393 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
394 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
395 int num_lanes = NumLanes(input_rep_type);
396 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
397 for (int i = 0; i < num_lanes; ++i) {
398 rep_node[i] =
399 FixUpperBits(graph()->NewNode(op, rep_left[i], rep_right[i]), kShift16);
400 }
401 ReplaceNode(node, rep_node, num_lanes);
402 }
403
404 Node* SimdScalarLowering::Mask(Node* input, int32_t mask) {
405 return graph()->NewNode(machine()->Word32And(), input,
406 jsgraph_->Int32Constant(mask));
407 }
408
409 void SimdScalarLowering::LowerSaturateBinaryOp(Node* node,
410 SimdType input_rep_type,
411 const Operator* op,
412 bool is_signed) {
413 DCHECK(node->InputCount() == 2);
414 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
415 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
416 int32_t min = 0;
417 int32_t max = 0;
418 if (is_signed) {
419 min = std::numeric_limits<int16_t>::min();
420 max = std::numeric_limits<int16_t>::max();
421 } else {
422 min = std::numeric_limits<uint16_t>::min();
423 max = std::numeric_limits<uint16_t>::max();
424 }
425 int num_lanes = NumLanes(input_rep_type);
426 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
427 for (int i = 0; i < num_lanes; ++i) {
428 Node* op_result = nullptr;
429 Node* left = is_signed ? rep_left[i] : Mask(rep_left[i], kMask16);
430 Node* right = is_signed ? rep_right[i] : Mask(rep_right[i], kMask16);
431 op_result = graph()->NewNode(op, left, right);
432 Diamond d_min(graph(), common(),
433 graph()->NewNode(machine()->Int32LessThan(), op_result,
434 jsgraph_->Int32Constant(min)));
435 rep_node[i] = d_min.Phi(MachineRepresentation::kWord16,
436 jsgraph_->Int32Constant(min), op_result);
437 Diamond d_max(graph(), common(),
438 graph()->NewNode(machine()->Int32LessThan(),
439 jsgraph_->Int32Constant(max), rep_node[i]));
440 rep_node[i] = d_max.Phi(MachineRepresentation::kWord16,
441 jsgraph_->Int32Constant(max), rep_node[i]);
442 rep_node[i] = is_signed ? rep_node[i] : FixUpperBits(rep_node[i], kShift16);
443 }
444 ReplaceNode(node, rep_node, num_lanes);
298 } 445 }
299 446
300 void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type, 447 void SimdScalarLowering::LowerUnaryOp(Node* node, SimdType input_rep_type,
301 const Operator* op) { 448 const Operator* op) {
302 DCHECK(node->InputCount() == 1); 449 DCHECK(node->InputCount() == 1);
303 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type); 450 Node** rep = GetReplacementsWithType(node->InputAt(0), input_rep_type);
304 Node* rep_node[kMaxLanes]; 451 int num_lanes = NumLanes(input_rep_type);
305 for (int i = 0; i < kMaxLanes; ++i) { 452 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
453 for (int i = 0; i < num_lanes; ++i) {
306 rep_node[i] = graph()->NewNode(op, rep[i]); 454 rep_node[i] = graph()->NewNode(op, rep[i]);
307 } 455 }
308 ReplaceNode(node, rep_node); 456 ReplaceNode(node, rep_node, num_lanes);
309 } 457 }
310 458
311 void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op, 459 void SimdScalarLowering::LowerIntMinMax(Node* node, const Operator* op,
312 bool is_max) { 460 bool is_max, SimdType type) {
313 DCHECK(node->InputCount() == 2); 461 DCHECK(node->InputCount() == 2);
314 Node** rep_left = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); 462 Node** rep_left = GetReplacementsWithType(node->InputAt(0), type);
315 Node** rep_right = 463 Node** rep_right = GetReplacementsWithType(node->InputAt(1), type);
316 GetReplacementsWithType(node->InputAt(1), SimdType::kInt32); 464 int num_lanes = NumLanes(type);
317 Node* rep_node[kMaxLanes]; 465 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
318 for (int i = 0; i < kMaxLanes; ++i) { 466 MachineRepresentation rep = MachineRepresentation::kNone;
467 if (type == SimdType::kInt32x4) {
468 rep = MachineRepresentation::kWord32;
469 } else if (type == SimdType::kInt16x8) {
470 rep = MachineRepresentation::kWord16;
471 } else {
472 UNREACHABLE();
473 }
474 for (int i = 0; i < num_lanes; ++i) {
319 Diamond d(graph(), common(), 475 Diamond d(graph(), common(),
320 graph()->NewNode(op, rep_left[i], rep_right[i])); 476 graph()->NewNode(op, rep_left[i], rep_right[i]));
321 if (is_max) { 477 if (is_max) {
322 rep_node[i] = 478 rep_node[i] = d.Phi(rep, rep_right[i], rep_left[i]);
323 d.Phi(MachineRepresentation::kWord32, rep_right[i], rep_left[i]);
324 } else { 479 } else {
325 rep_node[i] = 480 rep_node[i] = d.Phi(rep, rep_left[i], rep_right[i]);
326 d.Phi(MachineRepresentation::kWord32, rep_left[i], rep_right[i]);
327 } 481 }
328 } 482 }
329 ReplaceNode(node, rep_node); 483 ReplaceNode(node, rep_node, num_lanes);
330 } 484 }
331 485
332 Node* SimdScalarLowering::BuildF64Trunc(Node* input) { 486 Node* SimdScalarLowering::BuildF64Trunc(Node* input) {
333 if (machine()->Float64RoundTruncate().IsSupported()) { 487 if (machine()->Float64RoundTruncate().IsSupported()) {
334 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input); 488 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
335 } else { 489 } else {
336 ExternalReference ref = 490 ExternalReference ref =
337 ExternalReference::wasm_f64_trunc(jsgraph_->isolate()); 491 ExternalReference::wasm_f64_trunc(jsgraph_->isolate());
338 Node* stack_slot = 492 Node* stack_slot =
339 graph()->NewNode(machine()->StackSlot(MachineRepresentation::kFloat64)); 493 graph()->NewNode(machine()->StackSlot(MachineRepresentation::kFloat64));
(...skipping 14 matching lines...) Expand all
354 Linkage::GetSimplifiedCDescriptor(zone(), sig_builder.Build()); 508 Linkage::GetSimplifiedCDescriptor(zone(), sig_builder.Build());
355 Node* call = graph()->NewNode(common()->Call(desc), 4, args); 509 Node* call = graph()->NewNode(common()->Call(desc), 4, args);
356 return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()), 510 return graph()->NewNode(machine()->Load(LoadRepresentation::Float64()),
357 stack_slot, jsgraph_->Int32Constant(0), call, 511 stack_slot, jsgraph_->Int32Constant(0), call,
358 graph()->start()); 512 graph()->start());
359 } 513 }
360 } 514 }
361 515
362 void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) { 516 void SimdScalarLowering::LowerConvertFromFloat(Node* node, bool is_signed) {
363 DCHECK(node->InputCount() == 1); 517 DCHECK(node->InputCount() == 1);
364 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32); 518 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kFloat32x4);
365 Node* rep_node[kMaxLanes]; 519 Node* rep_node[kNumLanes32];
366 Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0)); 520 Node* double_zero = graph()->NewNode(common()->Float64Constant(0.0));
367 Node* min = graph()->NewNode( 521 Node* min = graph()->NewNode(
368 common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0))); 522 common()->Float64Constant(static_cast<double>(is_signed ? kMinInt : 0)));
369 Node* max = graph()->NewNode(common()->Float64Constant( 523 Node* max = graph()->NewNode(common()->Float64Constant(
370 static_cast<double>(is_signed ? kMaxInt : 0xffffffffu))); 524 static_cast<double>(is_signed ? kMaxInt : 0xffffffffu)));
371 for (int i = 0; i < kMaxLanes; ++i) { 525 for (int i = 0; i < kNumLanes32; ++i) {
372 Node* double_rep = 526 Node* double_rep =
373 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]); 527 graph()->NewNode(machine()->ChangeFloat32ToFloat64(), rep[i]);
374 Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(), 528 Diamond nan_d(graph(), common(), graph()->NewNode(machine()->Float64Equal(),
375 double_rep, double_rep)); 529 double_rep, double_rep));
376 Node* temp = 530 Node* temp =
377 nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero); 531 nan_d.Phi(MachineRepresentation::kFloat64, double_rep, double_zero);
378 Diamond min_d(graph(), common(), 532 Diamond min_d(graph(), common(),
379 graph()->NewNode(machine()->Float64LessThan(), temp, min)); 533 graph()->NewNode(machine()->Float64LessThan(), temp, min));
380 temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp); 534 temp = min_d.Phi(MachineRepresentation::kFloat64, min, temp);
381 Diamond max_d(graph(), common(), 535 Diamond max_d(graph(), common(),
382 graph()->NewNode(machine()->Float64LessThan(), max, temp)); 536 graph()->NewNode(machine()->Float64LessThan(), max, temp));
383 temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp); 537 temp = max_d.Phi(MachineRepresentation::kFloat64, max, temp);
384 Node* trunc = BuildF64Trunc(temp); 538 Node* trunc = BuildF64Trunc(temp);
385 if (is_signed) { 539 if (is_signed) {
386 rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc); 540 rep_node[i] = graph()->NewNode(machine()->ChangeFloat64ToInt32(), trunc);
387 } else { 541 } else {
388 rep_node[i] = 542 rep_node[i] =
389 graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc); 543 graph()->NewNode(machine()->TruncateFloat64ToUint32(), trunc);
390 } 544 }
391 } 545 }
392 ReplaceNode(node, rep_node); 546 ReplaceNode(node, rep_node, kNumLanes32);
393 } 547 }
394 548
395 void SimdScalarLowering::LowerShiftOp(Node* node, const Operator* op) { 549 void SimdScalarLowering::LowerShiftOp(Node* node, SimdType type) {
396 static int32_t shift_mask = 0x1f;
397 DCHECK_EQ(1, node->InputCount()); 550 DCHECK_EQ(1, node->InputCount());
398 int32_t shift_amount = OpParameter<int32_t>(node); 551 int32_t shift_amount = OpParameter<int32_t>(node);
399 Node* shift_node = 552 Node* shift_node = graph()->NewNode(common()->Int32Constant(shift_amount));
400 graph()->NewNode(common()->Int32Constant(shift_amount & shift_mask)); 553 Node** rep = GetReplacementsWithType(node->InputAt(0), type);
401 Node** rep = GetReplacementsWithType(node->InputAt(0), SimdType::kInt32); 554 int num_lanes = NumLanes(type);
402 Node* rep_node[kMaxLanes]; 555 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
403 for (int i = 0; i < kMaxLanes; ++i) { 556 for (int i = 0; i < num_lanes; ++i) {
404 rep_node[i] = graph()->NewNode(op, rep[i], shift_node); 557 rep_node[i] = rep[i];
558 switch (node->opcode()) {
559 case IrOpcode::kI16x8ShrU:
560 rep_node[i] = Mask(rep_node[i], kMask16); // Fallthrough
bbudge 2017/05/01 18:42:27 nit: Fall through.
aseemgarg 2017/05/01 18:48:21 Done.
561 case IrOpcode::kI32x4ShrU:
562 rep_node[i] =
563 graph()->NewNode(machine()->Word32Shr(), rep_node[i], shift_node);
564 break;
565 case IrOpcode::kI32x4Shl:
566 rep_node[i] =
567 graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
568 break;
569 case IrOpcode::kI16x8Shl:
570 rep_node[i] =
571 graph()->NewNode(machine()->Word32Shl(), rep_node[i], shift_node);
572 rep_node[i] = FixUpperBits(rep_node[i], kShift16);
573 break;
574 case IrOpcode::kI32x4ShrS:
575 case IrOpcode::kI16x8ShrS:
576 rep_node[i] =
577 graph()->NewNode(machine()->Word32Sar(), rep_node[i], shift_node);
578 break;
579 default:
580 UNREACHABLE();
581 }
405 } 582 }
406 ReplaceNode(node, rep_node); 583 ReplaceNode(node, rep_node, num_lanes);
407 } 584 }
408 585
409 void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type, 586 void SimdScalarLowering::LowerNotEqual(Node* node, SimdType input_rep_type,
410 const Operator* op) { 587 const Operator* op) {
411 DCHECK(node->InputCount() == 2); 588 DCHECK(node->InputCount() == 2);
412 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type); 589 Node** rep_left = GetReplacementsWithType(node->InputAt(0), input_rep_type);
413 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type); 590 Node** rep_right = GetReplacementsWithType(node->InputAt(1), input_rep_type);
414 Node* rep_node[kMaxLanes]; 591 int num_lanes = NumLanes(input_rep_type);
415 for (int i = 0; i < kMaxLanes; ++i) { 592 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
593 for (int i = 0; i < num_lanes; ++i) {
416 Diamond d(graph(), common(), 594 Diamond d(graph(), common(),
417 graph()->NewNode(op, rep_left[i], rep_right[i])); 595 graph()->NewNode(op, rep_left[i], rep_right[i]));
418 rep_node[i] = d.Phi(MachineRepresentation::kWord32, 596 rep_node[i] = d.Phi(MachineRepresentation::kWord32,
419 jsgraph_->Int32Constant(0), jsgraph_->Int32Constant(1)); 597 jsgraph_->Int32Constant(0), jsgraph_->Int32Constant(1));
420 } 598 }
421 ReplaceNode(node, rep_node); 599 ReplaceNode(node, rep_node, num_lanes);
422 } 600 }
423 601
424 void SimdScalarLowering::LowerNode(Node* node) { 602 void SimdScalarLowering::LowerNode(Node* node) {
425 SimdType rep_type = ReplacementType(node); 603 SimdType rep_type = ReplacementType(node);
604 int num_lanes = NumLanes(rep_type);
426 switch (node->opcode()) { 605 switch (node->opcode()) {
427 case IrOpcode::kStart: { 606 case IrOpcode::kStart: {
428 int parameter_count = GetParameterCountAfterLowering(); 607 int parameter_count = GetParameterCountAfterLowering();
429 // Only exchange the node if the parameter count actually changed. 608 // Only exchange the node if the parameter count actually changed.
430 if (parameter_count != static_cast<int>(signature()->parameter_count())) { 609 if (parameter_count != static_cast<int>(signature()->parameter_count())) {
431 int delta = 610 int delta =
432 parameter_count - static_cast<int>(signature()->parameter_count()); 611 parameter_count - static_cast<int>(signature()->parameter_count());
433 int new_output_count = node->op()->ValueOutputCount() + delta; 612 int new_output_count = node->op()->ValueOutputCount() + delta;
434 NodeProperties::ChangeOp(node, common()->Start(new_output_count)); 613 NodeProperties::ChangeOp(node, common()->Start(new_output_count));
435 } 614 }
436 break; 615 break;
437 } 616 }
438 case IrOpcode::kParameter: { 617 case IrOpcode::kParameter: {
439 DCHECK(node->InputCount() == 1); 618 DCHECK(node->InputCount() == 1);
440 // Only exchange the node if the parameter count actually changed. We do 619 // Only exchange the node if the parameter count actually changed. We do
441 // not even have to do the default lowering because the the start node, 620 // not even have to do the default lowering because the the start node,
442 // the only input of a parameter node, only changes if the parameter count 621 // the only input of a parameter node, only changes if the parameter count
443 // changes. 622 // changes.
444 if (GetParameterCountAfterLowering() != 623 if (GetParameterCountAfterLowering() !=
445 static_cast<int>(signature()->parameter_count())) { 624 static_cast<int>(signature()->parameter_count())) {
446 int old_index = ParameterIndexOf(node->op()); 625 int old_index = ParameterIndexOf(node->op());
447 int new_index = GetParameterIndexAfterLowering(signature(), old_index); 626 int new_index = GetParameterIndexAfterLowering(signature(), old_index);
448 if (old_index == new_index) { 627 if (old_index == new_index) {
449 NodeProperties::ChangeOp(node, common()->Parameter(new_index)); 628 NodeProperties::ChangeOp(node, common()->Parameter(new_index));
450 629
451 Node* new_node[kMaxLanes]; 630 Node* new_node[kNumLanes32];
452 for (int i = 0; i < kMaxLanes; ++i) { 631 for (int i = 0; i < kNumLanes32; ++i) {
453 new_node[i] = nullptr; 632 new_node[i] = nullptr;
454 } 633 }
455 new_node[0] = node; 634 new_node[0] = node;
456 if (signature()->GetParam(old_index) == 635 if (signature()->GetParam(old_index) ==
457 MachineRepresentation::kSimd128) { 636 MachineRepresentation::kSimd128) {
458 for (int i = 1; i < kMaxLanes; ++i) { 637 for (int i = 1; i < kNumLanes32; ++i) {
459 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i), 638 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i),
460 graph()->start()); 639 graph()->start());
461 } 640 }
462 } 641 }
463 ReplaceNode(node, new_node); 642 ReplaceNode(node, new_node, kNumLanes32);
464 } 643 }
465 } 644 }
466 break; 645 break;
467 } 646 }
468 case IrOpcode::kLoad: { 647 case IrOpcode::kLoad: {
469 MachineRepresentation rep = 648 MachineRepresentation rep =
470 LoadRepresentationOf(node->op()).representation(); 649 LoadRepresentationOf(node->op()).representation();
471 const Operator* load_op; 650 const Operator* load_op;
472 if (rep_type == SimdType::kInt32) { 651 #define LOAD_CASE(sType, mType) \
473 load_op = machine()->Load(MachineType::Int32()); 652 case SimdType::k##sType: \
474 } else if (rep_type == SimdType::kFloat32) { 653 load_op = machine()->Load(MachineType::mType()); \
475 load_op = machine()->Load(MachineType::Float32()); 654 break;
655
656 switch (rep_type) {
657 FOREACH_SIMD_TYPE_TO_MACHINE_TYPE(LOAD_CASE)
658 default:
659 UNREACHABLE();
476 } 660 }
477 LowerLoadOp(rep, node, load_op); 661 #undef LOAD_CASE
662 LowerLoadOp(rep, node, load_op, rep_type);
478 break; 663 break;
479 } 664 }
480 case IrOpcode::kUnalignedLoad: { 665 case IrOpcode::kUnalignedLoad: {
481 MachineRepresentation rep = 666 MachineRepresentation rep =
482 UnalignedLoadRepresentationOf(node->op()).representation(); 667 UnalignedLoadRepresentationOf(node->op()).representation();
483 const Operator* load_op; 668 const Operator* load_op;
484 if (rep_type == SimdType::kInt32) { 669 #define UNALIGNED_LOAD_CASE(sType, mType) \
485 load_op = machine()->UnalignedLoad(MachineType::Int32()); 670 case SimdType::k##sType: \
486 } else if (rep_type == SimdType::kFloat32) { 671 load_op = machine()->UnalignedLoad(MachineType::mType()); \
487 load_op = machine()->UnalignedLoad(MachineType::Float32()); 672 break;
673
674 switch (rep_type) {
675 FOREACH_SIMD_TYPE_TO_MACHINE_TYPE(UNALIGNED_LOAD_CASE)
676 default:
677 UNREACHABLE();
488 } 678 }
489 LowerLoadOp(rep, node, load_op); 679 #undef UNALIGHNED_LOAD_CASE
680 LowerLoadOp(rep, node, load_op, rep_type);
490 break; 681 break;
491 } 682 }
492 case IrOpcode::kStore: { 683 case IrOpcode::kStore: {
493 MachineRepresentation rep = 684 MachineRepresentation rep =
494 StoreRepresentationOf(node->op()).representation(); 685 StoreRepresentationOf(node->op()).representation();
495 WriteBarrierKind write_barrier_kind = 686 WriteBarrierKind write_barrier_kind =
496 StoreRepresentationOf(node->op()).write_barrier_kind(); 687 StoreRepresentationOf(node->op()).write_barrier_kind();
497 const Operator* store_op; 688 const Operator* store_op;
498 if (rep_type == SimdType::kInt32) { 689 #define STORE_CASE(sType, mType) \
499 store_op = machine()->Store(StoreRepresentation( 690 case SimdType::k##sType: \
500 MachineRepresentation::kWord32, write_barrier_kind)); 691 store_op = machine()->Store(StoreRepresentation( \
501 } else { 692 MachineRepresentation::k##mType, write_barrier_kind)); \
502 store_op = machine()->Store(StoreRepresentation( 693 break;
503 MachineRepresentation::kFloat32, write_barrier_kind)); 694
695 switch (rep_type) {
696 FOREACH_SIMD_TYPE_TO_MACHINE_REP(STORE_CASE)
697 default:
698 UNREACHABLE();
504 } 699 }
700 #undef STORE_CASE
505 LowerStoreOp(rep, node, store_op, rep_type); 701 LowerStoreOp(rep, node, store_op, rep_type);
506 break; 702 break;
507 } 703 }
508 case IrOpcode::kUnalignedStore: { 704 case IrOpcode::kUnalignedStore: {
509 MachineRepresentation rep = UnalignedStoreRepresentationOf(node->op()); 705 MachineRepresentation rep = UnalignedStoreRepresentationOf(node->op());
510 const Operator* store_op; 706 const Operator* store_op;
511 if (rep_type == SimdType::kInt32) { 707 #define UNALIGNED_STORE_CASE(sType, mType) \
512 store_op = machine()->UnalignedStore(MachineRepresentation::kWord32); 708 case SimdType::k##sType: \
513 } else { 709 store_op = machine()->UnalignedStore(MachineRepresentation::k##mType); \
514 store_op = machine()->UnalignedStore(MachineRepresentation::kFloat32); 710 break;
711
712 switch (rep_type) {
713 FOREACH_SIMD_TYPE_TO_MACHINE_REP(UNALIGNED_STORE_CASE)
714 default:
715 UNREACHABLE();
515 } 716 }
717 #undef UNALIGNED_STORE_CASE
516 LowerStoreOp(rep, node, store_op, rep_type); 718 LowerStoreOp(rep, node, store_op, rep_type);
517 break; 719 break;
518 } 720 }
519 case IrOpcode::kReturn: { 721 case IrOpcode::kReturn: {
520 DefaultLowering(node); 722 DefaultLowering(node);
521 int new_return_count = GetReturnCountAfterLowering(signature()); 723 int new_return_count = GetReturnCountAfterLowering(signature());
522 if (static_cast<int>(signature()->return_count()) != new_return_count) { 724 if (static_cast<int>(signature()->return_count()) != new_return_count) {
523 NodeProperties::ChangeOp(node, common()->Return(new_return_count)); 725 NodeProperties::ChangeOp(node, common()->Return(new_return_count));
524 } 726 }
525 break; 727 break;
526 } 728 }
527 case IrOpcode::kCall: { 729 case IrOpcode::kCall: {
528 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor. 730 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor.
529 CallDescriptor* descriptor = 731 CallDescriptor* descriptor =
530 const_cast<CallDescriptor*>(CallDescriptorOf(node->op())); 732 const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
531 if (DefaultLowering(node) || 733 if (DefaultLowering(node) ||
532 (descriptor->ReturnCount() == 1 && 734 (descriptor->ReturnCount() == 1 &&
533 descriptor->GetReturnType(0) == MachineType::Simd128())) { 735 descriptor->GetReturnType(0) == MachineType::Simd128())) {
534 // We have to adjust the call descriptor. 736 // We have to adjust the call descriptor.
535 const Operator* op = 737 const Operator* op =
536 common()->Call(wasm::ModuleEnv::GetI32WasmCallDescriptorForSimd( 738 common()->Call(wasm::ModuleEnv::GetI32WasmCallDescriptorForSimd(
537 zone(), descriptor)); 739 zone(), descriptor));
538 NodeProperties::ChangeOp(node, op); 740 NodeProperties::ChangeOp(node, op);
539 } 741 }
540 if (descriptor->ReturnCount() == 1 && 742 if (descriptor->ReturnCount() == 1 &&
541 descriptor->GetReturnType(0) == MachineType::Simd128()) { 743 descriptor->GetReturnType(0) == MachineType::Simd128()) {
542 // We access the additional return values through projections. 744 // We access the additional return values through projections.
543 Node* rep_node[kMaxLanes]; 745 Node* rep_node[kNumLanes32];
544 for (int i = 0; i < kMaxLanes; ++i) { 746 for (int i = 0; i < kNumLanes32; ++i) {
545 rep_node[i] = 747 rep_node[i] =
546 graph()->NewNode(common()->Projection(i), node, graph()->start()); 748 graph()->NewNode(common()->Projection(i), node, graph()->start());
547 } 749 }
548 ReplaceNode(node, rep_node); 750 ReplaceNode(node, rep_node, kNumLanes32);
549 } 751 }
550 break; 752 break;
551 } 753 }
552 case IrOpcode::kPhi: { 754 case IrOpcode::kPhi: {
553 MachineRepresentation rep = PhiRepresentationOf(node->op()); 755 MachineRepresentation rep = PhiRepresentationOf(node->op());
554 if (rep == MachineRepresentation::kSimd128) { 756 if (rep == MachineRepresentation::kSimd128) {
555 // The replacement nodes have already been created, we only have to 757 // The replacement nodes have already been created, we only have to
556 // replace placeholder nodes. 758 // replace placeholder nodes.
557 Node** rep_node = GetReplacements(node); 759 Node** rep_node = GetReplacements(node);
558 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 760 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
559 Node** rep_input = 761 Node** rep_input =
560 GetReplacementsWithType(node->InputAt(i), rep_type); 762 GetReplacementsWithType(node->InputAt(i), rep_type);
561 for (int j = 0; j < kMaxLanes; j++) { 763 for (int j = 0; j < num_lanes; j++) {
562 rep_node[j]->ReplaceInput(i, rep_input[j]); 764 rep_node[j]->ReplaceInput(i, rep_input[j]);
563 } 765 }
564 } 766 }
565 } else { 767 } else {
566 DefaultLowering(node); 768 DefaultLowering(node);
567 } 769 }
568 break; 770 break;
569 } 771 }
570 #define I32X4_BINOP_CASE(opcode, instruction) \ 772 #define I32X4_BINOP_CASE(opcode, instruction) \
571 case IrOpcode::opcode: { \ 773 case IrOpcode::opcode: { \
572 LowerBinaryOp(node, rep_type, machine()->instruction()); \ 774 LowerBinaryOp(node, rep_type, machine()->instruction()); \
573 break; \ 775 break; \
574 } 776 }
575 I32X4_BINOP_CASE(kI32x4Add, Int32Add) 777 I32X4_BINOP_CASE(kI32x4Add, Int32Add)
576 I32X4_BINOP_CASE(kI32x4Sub, Int32Sub) 778 I32X4_BINOP_CASE(kI32x4Sub, Int32Sub)
577 I32X4_BINOP_CASE(kI32x4Mul, Int32Mul) 779 I32X4_BINOP_CASE(kI32x4Mul, Int32Mul)
578 I32X4_BINOP_CASE(kS128And, Word32And) 780 I32X4_BINOP_CASE(kS128And, Word32And)
579 I32X4_BINOP_CASE(kS128Or, Word32Or) 781 I32X4_BINOP_CASE(kS128Or, Word32Or)
580 I32X4_BINOP_CASE(kS128Xor, Word32Xor) 782 I32X4_BINOP_CASE(kS128Xor, Word32Xor)
581 #undef I32X4_BINOP_CASE 783 #undef I32X4_BINOP_CASE
582 case IrOpcode::kI32x4MaxS: { 784 case IrOpcode::kI16x8Add: {
583 LowerIntMinMax(node, machine()->Int32LessThan(), true); 785 LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Add());
584 break; 786 break;
585 } 787 }
586 case IrOpcode::kI32x4MinS: { 788 case IrOpcode::kI16x8Sub: {
587 LowerIntMinMax(node, machine()->Int32LessThan(), false); 789 LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Sub());
588 break; 790 break;
589 } 791 }
590 case IrOpcode::kI32x4MaxU: { 792 case IrOpcode::kI16x8Mul: {
591 LowerIntMinMax(node, machine()->Uint32LessThan(), true); 793 LowerBinaryOpForSmallInt(node, rep_type, machine()->Int32Mul());
592 break; 794 break;
593 } 795 }
594 case IrOpcode::kI32x4MinU: { 796 case IrOpcode::kI16x8AddSaturateS: {
595 LowerIntMinMax(node, machine()->Uint32LessThan(), false); 797 LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), true);
798 break;
799 }
800 case IrOpcode::kI16x8SubSaturateS: {
801 LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), true);
802 break;
803 }
804 case IrOpcode::kI16x8AddSaturateU: {
805 LowerSaturateBinaryOp(node, rep_type, machine()->Int32Add(), false);
806 break;
807 }
808 case IrOpcode::kI16x8SubSaturateU: {
809 LowerSaturateBinaryOp(node, rep_type, machine()->Int32Sub(), false);
810 break;
811 }
812 case IrOpcode::kI32x4MaxS:
813 case IrOpcode::kI16x8MaxS: {
814 LowerIntMinMax(node, machine()->Int32LessThan(), true, rep_type);
815 break;
816 }
817 case IrOpcode::kI32x4MinS:
818 case IrOpcode::kI16x8MinS: {
819 LowerIntMinMax(node, machine()->Int32LessThan(), false, rep_type);
820 break;
821 }
822 case IrOpcode::kI32x4MaxU:
823 case IrOpcode::kI16x8MaxU: {
824 LowerIntMinMax(node, machine()->Uint32LessThan(), true, rep_type);
825 break;
826 }
827 case IrOpcode::kI32x4MinU:
828 case IrOpcode::kI16x8MinU: {
829 LowerIntMinMax(node, machine()->Uint32LessThan(), false, rep_type);
596 break; 830 break;
597 } 831 }
598 case IrOpcode::kI32x4Neg: { 832 case IrOpcode::kI32x4Neg: {
599 DCHECK(node->InputCount() == 1); 833 DCHECK(node->InputCount() == 1);
600 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); 834 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
601 Node* rep_node[kMaxLanes]; 835 Node* rep_node[kNumLanes32];
602 Node* zero = graph()->NewNode(common()->Int32Constant(0)); 836 Node* zero = graph()->NewNode(common()->Int32Constant(0));
603 for (int i = 0; i < kMaxLanes; ++i) { 837 for (int i = 0; i < kNumLanes32; ++i) {
604 rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]); 838 rep_node[i] = graph()->NewNode(machine()->Int32Sub(), zero, rep[i]);
605 } 839 }
606 ReplaceNode(node, rep_node); 840 ReplaceNode(node, rep_node, kNumLanes32);
607 break; 841 break;
608 } 842 }
609 case IrOpcode::kS128Not: { 843 case IrOpcode::kS128Not: {
610 DCHECK(node->InputCount() == 1); 844 DCHECK(node->InputCount() == 1);
611 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type); 845 Node** rep = GetReplacementsWithType(node->InputAt(0), rep_type);
612 Node* rep_node[kMaxLanes]; 846 Node* rep_node[kNumLanes32];
613 Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff)); 847 Node* mask = graph()->NewNode(common()->Int32Constant(0xffffffff));
614 for (int i = 0; i < kMaxLanes; ++i) { 848 for (int i = 0; i < kNumLanes32; ++i) {
615 rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask); 849 rep_node[i] = graph()->NewNode(machine()->Word32Xor(), rep[i], mask);
616 } 850 }
617 ReplaceNode(node, rep_node); 851 ReplaceNode(node, rep_node, kNumLanes32);
618 break; 852 break;
619 } 853 }
620 case IrOpcode::kI32x4SConvertF32x4: { 854 case IrOpcode::kI32x4SConvertF32x4: {
621 LowerConvertFromFloat(node, true); 855 LowerConvertFromFloat(node, true);
622 break; 856 break;
623 } 857 }
624 case IrOpcode::kI32x4UConvertF32x4: { 858 case IrOpcode::kI32x4UConvertF32x4: {
625 LowerConvertFromFloat(node, false); 859 LowerConvertFromFloat(node, false);
626 break; 860 break;
627 } 861 }
628 case IrOpcode::kI32x4Shl: { 862 case IrOpcode::kI32x4Shl:
629 LowerShiftOp(node, machine()->Word32Shl()); 863 case IrOpcode::kI16x8Shl:
630 break; 864 case IrOpcode::kI32x4ShrS:
631 } 865 case IrOpcode::kI16x8ShrS:
632 case IrOpcode::kI32x4ShrS: { 866 case IrOpcode::kI32x4ShrU:
633 LowerShiftOp(node, machine()->Word32Sar()); 867 case IrOpcode::kI16x8ShrU: {
634 break; 868 LowerShiftOp(node, rep_type);
635 }
636 case IrOpcode::kI32x4ShrU: {
637 LowerShiftOp(node, machine()->Word32Shr());
638 break; 869 break;
639 } 870 }
640 #define F32X4_BINOP_CASE(name) \ 871 #define F32X4_BINOP_CASE(name) \
641 case IrOpcode::kF32x4##name: { \ 872 case IrOpcode::kF32x4##name: { \
642 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \ 873 LowerBinaryOp(node, rep_type, machine()->Float32##name()); \
643 break; \ 874 break; \
644 } 875 }
645 F32X4_BINOP_CASE(Add) 876 F32X4_BINOP_CASE(Add)
646 F32X4_BINOP_CASE(Sub) 877 F32X4_BINOP_CASE(Sub)
647 F32X4_BINOP_CASE(Mul) 878 F32X4_BINOP_CASE(Mul)
648 F32X4_BINOP_CASE(Min) 879 F32X4_BINOP_CASE(Min)
649 F32X4_BINOP_CASE(Max) 880 F32X4_BINOP_CASE(Max)
650 #undef F32X4_BINOP_CASE 881 #undef F32X4_BINOP_CASE
651 #define F32X4_UNOP_CASE(name) \ 882 #define F32X4_UNOP_CASE(name) \
652 case IrOpcode::kF32x4##name: { \ 883 case IrOpcode::kF32x4##name: { \
653 LowerUnaryOp(node, rep_type, machine()->Float32##name()); \ 884 LowerUnaryOp(node, rep_type, machine()->Float32##name()); \
654 break; \ 885 break; \
655 } 886 }
656 F32X4_UNOP_CASE(Abs) 887 F32X4_UNOP_CASE(Abs)
657 F32X4_UNOP_CASE(Neg) 888 F32X4_UNOP_CASE(Neg)
658 #undef F32x4_UNOP_CASE 889 #undef F32x4_UNOP_CASE
659 case IrOpcode::kF32x4SConvertI32x4: { 890 case IrOpcode::kF32x4SConvertI32x4: {
660 LowerUnaryOp(node, SimdType::kInt32, machine()->RoundInt32ToFloat32()); 891 LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundInt32ToFloat32());
661 break; 892 break;
662 } 893 }
663 case IrOpcode::kF32x4UConvertI32x4: { 894 case IrOpcode::kF32x4UConvertI32x4: {
664 LowerUnaryOp(node, SimdType::kInt32, machine()->RoundUint32ToFloat32()); 895 LowerUnaryOp(node, SimdType::kInt32x4, machine()->RoundUint32ToFloat32());
665 break; 896 break;
666 } 897 }
667 case IrOpcode::kI32x4Splat: 898 case IrOpcode::kI32x4Splat:
668 case IrOpcode::kF32x4Splat: { 899 case IrOpcode::kF32x4Splat:
669 Node* rep_node[kMaxLanes]; 900 case IrOpcode::kI16x8Splat: {
670 for (int i = 0; i < kMaxLanes; ++i) { 901 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
902 for (int i = 0; i < num_lanes; ++i) {
671 if (HasReplacement(0, node->InputAt(0))) { 903 if (HasReplacement(0, node->InputAt(0))) {
672 rep_node[i] = GetReplacements(node->InputAt(0))[0]; 904 rep_node[i] = GetReplacements(node->InputAt(0))[0];
673 } else { 905 } else {
674 rep_node[i] = node->InputAt(0); 906 rep_node[i] = node->InputAt(0);
675 } 907 }
676 } 908 }
677 ReplaceNode(node, rep_node); 909 ReplaceNode(node, rep_node, num_lanes);
678 break; 910 break;
679 } 911 }
680 case IrOpcode::kI32x4ExtractLane: 912 case IrOpcode::kI32x4ExtractLane:
681 case IrOpcode::kF32x4ExtractLane: { 913 case IrOpcode::kF32x4ExtractLane:
914 case IrOpcode::kI16x8ExtractLane: {
682 int32_t lane = OpParameter<int32_t>(node); 915 int32_t lane = OpParameter<int32_t>(node);
683 Node* rep_node[kMaxLanes] = { 916 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
684 GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, 917 rep_node[0] = GetReplacementsWithType(node->InputAt(0), rep_type)[lane];
685 nullptr, nullptr}; 918 for (int i = 1; i < num_lanes; ++i) {
686 ReplaceNode(node, rep_node); 919 rep_node[i] = nullptr;
920 }
921 ReplaceNode(node, rep_node, num_lanes);
687 break; 922 break;
688 } 923 }
689 case IrOpcode::kI32x4ReplaceLane: 924 case IrOpcode::kI32x4ReplaceLane:
690 case IrOpcode::kF32x4ReplaceLane: { 925 case IrOpcode::kF32x4ReplaceLane:
926 case IrOpcode::kI16x8ReplaceLane: {
691 DCHECK_EQ(2, node->InputCount()); 927 DCHECK_EQ(2, node->InputCount());
692 Node* repNode = node->InputAt(1); 928 Node* repNode = node->InputAt(1);
693 int32_t lane = OpParameter<int32_t>(node); 929 int32_t lane = OpParameter<int32_t>(node);
694 DCHECK(lane >= 0 && lane <= 3);
695 Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type); 930 Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type);
696 if (HasReplacement(0, repNode)) { 931 if (HasReplacement(0, repNode)) {
697 rep_node[lane] = GetReplacements(repNode)[0]; 932 rep_node[lane] = GetReplacements(repNode)[0];
698 } else { 933 } else {
699 rep_node[lane] = repNode; 934 rep_node[lane] = repNode;
700 } 935 }
701 ReplaceNode(node, rep_node); 936 ReplaceNode(node, rep_node, num_lanes);
702 break; 937 break;
703 } 938 }
704 #define COMPARISON_CASE(type, simd_op, lowering_op, invert) \ 939 #define COMPARISON_CASE(type, simd_op, lowering_op, invert) \
705 case IrOpcode::simd_op: { \ 940 case IrOpcode::simd_op: { \
706 LowerBinaryOp(node, SimdType::k##type, machine()->lowering_op(), invert); \ 941 LowerBinaryOp(node, SimdType::k##type, machine()->lowering_op(), invert); \
707 break; \ 942 break; \
708 } 943 }
709 COMPARISON_CASE(Float32, kF32x4Eq, Float32Equal, false) 944 COMPARISON_CASE(Float32x4, kF32x4Eq, Float32Equal, false)
710 COMPARISON_CASE(Float32, kF32x4Lt, Float32LessThan, false) 945 COMPARISON_CASE(Float32x4, kF32x4Lt, Float32LessThan, false)
711 COMPARISON_CASE(Float32, kF32x4Le, Float32LessThanOrEqual, false) 946 COMPARISON_CASE(Float32x4, kF32x4Le, Float32LessThanOrEqual, false)
712 COMPARISON_CASE(Float32, kF32x4Gt, Float32LessThan, true) 947 COMPARISON_CASE(Float32x4, kF32x4Gt, Float32LessThan, true)
713 COMPARISON_CASE(Float32, kF32x4Ge, Float32LessThanOrEqual, true) 948 COMPARISON_CASE(Float32x4, kF32x4Ge, Float32LessThanOrEqual, true)
714 COMPARISON_CASE(Int32, kI32x4Eq, Word32Equal, false) 949 COMPARISON_CASE(Int32x4, kI32x4Eq, Word32Equal, false)
715 COMPARISON_CASE(Int32, kI32x4LtS, Int32LessThan, false) 950 COMPARISON_CASE(Int32x4, kI32x4LtS, Int32LessThan, false)
716 COMPARISON_CASE(Int32, kI32x4LeS, Int32LessThanOrEqual, false) 951 COMPARISON_CASE(Int32x4, kI32x4LeS, Int32LessThanOrEqual, false)
717 COMPARISON_CASE(Int32, kI32x4GtS, Int32LessThan, true) 952 COMPARISON_CASE(Int32x4, kI32x4GtS, Int32LessThan, true)
718 COMPARISON_CASE(Int32, kI32x4GeS, Int32LessThanOrEqual, true) 953 COMPARISON_CASE(Int32x4, kI32x4GeS, Int32LessThanOrEqual, true)
719 COMPARISON_CASE(Int32, kI32x4LtU, Uint32LessThan, false) 954 COMPARISON_CASE(Int32x4, kI32x4LtU, Uint32LessThan, false)
720 COMPARISON_CASE(Int32, kI32x4LeU, Uint32LessThanOrEqual, false) 955 COMPARISON_CASE(Int32x4, kI32x4LeU, Uint32LessThanOrEqual, false)
721 COMPARISON_CASE(Int32, kI32x4GtU, Uint32LessThan, true) 956 COMPARISON_CASE(Int32x4, kI32x4GtU, Uint32LessThan, true)
722 COMPARISON_CASE(Int32, kI32x4GeU, Uint32LessThanOrEqual, true) 957 COMPARISON_CASE(Int32x4, kI32x4GeU, Uint32LessThanOrEqual, true)
958 COMPARISON_CASE(Int16x8, kI16x8Eq, Word32Equal, false)
959 COMPARISON_CASE(Int16x8, kI16x8LtS, Int32LessThan, false)
960 COMPARISON_CASE(Int16x8, kI16x8LeS, Int32LessThanOrEqual, false)
961 COMPARISON_CASE(Int16x8, kI16x8GtS, Int32LessThan, true)
962 COMPARISON_CASE(Int16x8, kI16x8GeS, Int32LessThanOrEqual, true)
963 COMPARISON_CASE(Int16x8, kI16x8LtU, Uint32LessThan, false)
964 COMPARISON_CASE(Int16x8, kI16x8LeU, Uint32LessThanOrEqual, false)
965 COMPARISON_CASE(Int16x8, kI16x8GtU, Uint32LessThan, true)
966 COMPARISON_CASE(Int16x8, kI16x8GeU, Uint32LessThanOrEqual, true)
723 #undef COMPARISON_CASE 967 #undef COMPARISON_CASE
724 case IrOpcode::kF32x4Ne: { 968 case IrOpcode::kF32x4Ne: {
725 LowerNotEqual(node, SimdType::kFloat32, machine()->Float32Equal()); 969 LowerNotEqual(node, SimdType::kFloat32x4, machine()->Float32Equal());
726 break; 970 break;
727 } 971 }
728 case IrOpcode::kI32x4Ne: { 972 case IrOpcode::kI32x4Ne: {
729 LowerNotEqual(node, SimdType::kInt32, machine()->Word32Equal()); 973 LowerNotEqual(node, SimdType::kInt32x4, machine()->Word32Equal());
730 break; 974 break;
731 } 975 }
732 case IrOpcode::kS32x4Select: { 976 case IrOpcode::kI16x8Ne: {
977 LowerNotEqual(node, SimdType::kInt16x8, machine()->Word32Equal());
978 break;
979 }
980 case IrOpcode::kS32x4Select:
981 case IrOpcode::kS16x8Select: {
733 DCHECK(node->InputCount() == 3); 982 DCHECK(node->InputCount() == 3);
734 DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kSimd1x4); 983 DCHECK(ReplacementType(node->InputAt(0)) == SimdType::kSimd1x4 ||
984 ReplacementType(node->InputAt(0)) == SimdType::kSimd1x8);
735 Node** boolean_input = GetReplacements(node->InputAt(0)); 985 Node** boolean_input = GetReplacements(node->InputAt(0));
736 Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type); 986 Node** rep_left = GetReplacementsWithType(node->InputAt(1), rep_type);
737 Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type); 987 Node** rep_right = GetReplacementsWithType(node->InputAt(2), rep_type);
738 Node* rep_node[kMaxLanes]; 988 Node** rep_node = zone()->NewArray<Node*>(num_lanes);
739 for (int i = 0; i < kMaxLanes; ++i) { 989 for (int i = 0; i < num_lanes; ++i) {
740 Diamond d(graph(), common(), 990 Diamond d(graph(), common(),
741 graph()->NewNode(machine()->Word32Equal(), boolean_input[i], 991 graph()->NewNode(machine()->Word32Equal(), boolean_input[i],
742 jsgraph_->Int32Constant(0))); 992 jsgraph_->Int32Constant(0)));
743 if (rep_type == SimdType::kFloat32) { 993 #define SELECT_CASE(sType, mType) \
744 rep_node[i] = 994 case SimdType::k##sType: \
745 d.Phi(MachineRepresentation::kFloat32, rep_right[1], rep_left[0]); 995 rep_node[i] = \
746 } else if (rep_type == SimdType::kInt32) { 996 d.Phi(MachineRepresentation::k##mType, rep_right[1], rep_left[0]); \
747 rep_node[i] = 997 break;
748 d.Phi(MachineRepresentation::kWord32, rep_right[1], rep_left[0]); 998
749 } else { 999 switch (rep_type) {
750 UNREACHABLE(); 1000 FOREACH_SIMD_TYPE_TO_MACHINE_REP(SELECT_CASE)
1001 default:
1002 UNREACHABLE();
751 } 1003 }
1004 #undef SELECT_CASE
752 } 1005 }
753 ReplaceNode(node, rep_node); 1006 ReplaceNode(node, rep_node, num_lanes);
754 break; 1007 break;
755 } 1008 }
756 default: { DefaultLowering(node); } 1009 default: { DefaultLowering(node); }
757 } 1010 }
758 } 1011 }
759 1012
760 bool SimdScalarLowering::DefaultLowering(Node* node) { 1013 bool SimdScalarLowering::DefaultLowering(Node* node) {
761 bool something_changed = false; 1014 bool something_changed = false;
762 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { 1015 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
763 Node* input = node->InputAt(i); 1016 Node* input = node->InputAt(i);
764 if (HasReplacement(0, input)) { 1017 if (HasReplacement(0, input)) {
765 something_changed = true; 1018 something_changed = true;
766 node->ReplaceInput(i, GetReplacements(input)[0]); 1019 node->ReplaceInput(i, GetReplacements(input)[0]);
767 } 1020 }
768 if (HasReplacement(1, input)) { 1021 if (HasReplacement(1, input)) {
769 something_changed = true; 1022 something_changed = true;
770 for (int j = 1; j < kMaxLanes; j++) { 1023 for (int j = 1; j < ReplacementCount(input); ++j) {
771 node->InsertInput(zone(), i + j, GetReplacements(input)[j]); 1024 node->InsertInput(zone(), i + j, GetReplacements(input)[j]);
772 } 1025 }
773 } 1026 }
774 } 1027 }
775 return something_changed; 1028 return something_changed;
776 } 1029 }
777 1030
778 void SimdScalarLowering::ReplaceNode(Node* old, Node** new_node) { 1031 void SimdScalarLowering::ReplaceNode(Node* old, Node** new_nodes, int count) {
779 // if new_low == nullptr, then also new_high == nullptr. 1032 replacements_[old->id()].node = zone()->NewArray<Node*>(count);
780 DCHECK(new_node[0] != nullptr || 1033 for (int i = 0; i < count; ++i) {
781 (new_node[1] == nullptr && new_node[2] == nullptr && 1034 replacements_[old->id()].node[i] = new_nodes[i];
782 new_node[3] == nullptr));
783 for (int i = 0; i < kMaxLanes; ++i) {
784 replacements_[old->id()].node[i] = new_node[i];
785 } 1035 }
1036 replacements_[old->id()].num_replacements = count;
786 } 1037 }
787 1038
788 bool SimdScalarLowering::HasReplacement(size_t index, Node* node) { 1039 bool SimdScalarLowering::HasReplacement(size_t index, Node* node) {
789 return replacements_[node->id()].node[index] != nullptr; 1040 return replacements_[node->id()].node != nullptr &&
1041 replacements_[node->id()].node[index] != nullptr;
790 } 1042 }
791 1043
792 SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) { 1044 SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) {
793 return replacements_[node->id()].type; 1045 return replacements_[node->id()].type;
794 } 1046 }
795 1047
796 Node** SimdScalarLowering::GetReplacements(Node* node) { 1048 Node** SimdScalarLowering::GetReplacements(Node* node) {
797 Node** result = replacements_[node->id()].node; 1049 Node** result = replacements_[node->id()].node;
798 DCHECK(result); 1050 DCHECK(result);
799 return result; 1051 return result;
800 } 1052 }
801 1053
1054 int SimdScalarLowering::ReplacementCount(Node* node) {
1055 return replacements_[node->id()].num_replacements;
1056 }
1057
1058 void SimdScalarLowering::Int32ToFloat32(Node** replacements, Node** result) {
1059 for (int i = 0; i < kNumLanes32; ++i) {
1060 if (replacements[i] != nullptr) {
1061 result[i] =
1062 graph()->NewNode(machine()->BitcastInt32ToFloat32(), replacements[i]);
1063 } else {
1064 result[i] = nullptr;
1065 }
1066 }
1067 }
1068
1069 void SimdScalarLowering::Float32ToInt32(Node** replacements, Node** result) {
1070 for (int i = 0; i < kNumLanes32; ++i) {
1071 if (replacements[i] != nullptr) {
1072 result[i] =
1073 graph()->NewNode(machine()->BitcastFloat32ToInt32(), replacements[i]);
1074 } else {
1075 result[i] = nullptr;
1076 }
1077 }
1078 }
1079
802 Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) { 1080 Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) {
803 Node** replacements = GetReplacements(node); 1081 Node** replacements = GetReplacements(node);
804 if (ReplacementType(node) == type) { 1082 if (ReplacementType(node) == type) {
805 return GetReplacements(node); 1083 return GetReplacements(node);
806 } 1084 }
807 Node** result = zone()->NewArray<Node*>(kMaxLanes); 1085 int num_lanes = NumLanes(type);
808 if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) { 1086 Node** result = zone()->NewArray<Node*>(num_lanes);
809 for (int i = 0; i < kMaxLanes; ++i) { 1087 if (type == SimdType::kInt32x4) {
810 if (replacements[i] != nullptr) { 1088 if (ReplacementType(node) == SimdType::kFloat32x4) {
811 result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(), 1089 Float32ToInt32(replacements, result);
812 replacements[i]); 1090 } else if (ReplacementType(node) == SimdType::kInt16x8) {
813 } else { 1091 UNIMPLEMENTED();
814 result[i] = nullptr; 1092 } else {
815 } 1093 UNREACHABLE();
816 } 1094 }
817 } else if (ReplacementType(node) == SimdType::kFloat32 && 1095 } else if (type == SimdType::kFloat32x4) {
818 type == SimdType::kInt32) { 1096 if (ReplacementType(node) == SimdType::kInt32x4) {
819 for (int i = 0; i < kMaxLanes; ++i) { 1097 Int32ToFloat32(replacements, result);
820 if (replacements[i] != nullptr) { 1098 } else if (ReplacementType(node) == SimdType::kInt16x8) {
821 result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(), 1099 UNIMPLEMENTED();
822 replacements[i]); 1100 } else {
823 } else { 1101 UNREACHABLE();
824 result[i] = nullptr; 1102 }
825 } 1103 } else if (type == SimdType::kInt16x8) {
1104 if (ReplacementType(node) == SimdType::kInt32x4 ||
1105 ReplacementType(node) == SimdType::kFloat32x4) {
1106 UNIMPLEMENTED();
1107 } else {
1108 UNREACHABLE();
826 } 1109 }
827 } else { 1110 } else {
828 UNREACHABLE(); 1111 UNREACHABLE();
829 } 1112 }
830 return result; 1113 return result;
831 } 1114 }
832 1115
833 void SimdScalarLowering::PreparePhiReplacement(Node* phi) { 1116 void SimdScalarLowering::PreparePhiReplacement(Node* phi) {
834 MachineRepresentation rep = PhiRepresentationOf(phi->op()); 1117 MachineRepresentation rep = PhiRepresentationOf(phi->op());
835 if (rep == MachineRepresentation::kSimd128) { 1118 if (rep == MachineRepresentation::kSimd128) {
836 // We have to create the replacements for a phi node before we actually 1119 // We have to create the replacements for a phi node before we actually
837 // lower the phi to break potential cycles in the graph. The replacements of 1120 // lower the phi to break potential cycles in the graph. The replacements of
838 // input nodes do not exist yet, so we use a placeholder node to pass the 1121 // input nodes do not exist yet, so we use a placeholder node to pass the
839 // graph verifier. 1122 // graph verifier.
840 int value_count = phi->op()->ValueInputCount(); 1123 int value_count = phi->op()->ValueInputCount();
841 SimdType type = ReplacementType(phi); 1124 SimdType type = ReplacementType(phi);
842 Node** inputs_rep[kMaxLanes]; 1125 int num_lanes = NumLanes(type);
843 for (int i = 0; i < kMaxLanes; ++i) { 1126 Node*** inputs_rep = zone()->NewArray<Node**>(num_lanes);
1127 for (int i = 0; i < num_lanes; ++i) {
844 inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1); 1128 inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1);
845 inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0); 1129 inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0);
846 } 1130 }
847 for (int i = 0; i < value_count; ++i) { 1131 for (int i = 0; i < value_count; ++i) {
848 for (int j = 0; j < kMaxLanes; j++) { 1132 for (int j = 0; j < num_lanes; ++j) {
849 inputs_rep[j][i] = placeholder_; 1133 inputs_rep[j][i] = placeholder_;
850 } 1134 }
851 } 1135 }
852 Node* rep_nodes[kMaxLanes]; 1136 Node** rep_nodes = zone()->NewArray<Node*>(num_lanes);
853 for (int i = 0; i < kMaxLanes; ++i) { 1137 for (int i = 0; i < num_lanes; ++i) {
854 if (type == SimdType::kInt32) { 1138 #define PHI_CASE(sType, mType) \
855 rep_nodes[i] = graph()->NewNode( 1139 case SimdType::k##sType: \
856 common()->Phi(MachineRepresentation::kWord32, value_count), 1140 rep_nodes[i] = graph()->NewNode( \
857 value_count + 1, inputs_rep[i], false); 1141 common()->Phi(MachineRepresentation::k##mType, value_count), \
858 } else if (type == SimdType::kFloat32) { 1142 value_count + 1, inputs_rep[i], false); \
859 rep_nodes[i] = graph()->NewNode( 1143 break;
860 common()->Phi(MachineRepresentation::kFloat32, value_count), 1144
861 value_count + 1, inputs_rep[i], false); 1145 switch (type) {
862 } else { 1146 FOREACH_SIMD_TYPE_TO_MACHINE_REP(PHI_CASE)
863 UNREACHABLE(); 1147 default:
1148 UNREACHABLE();
864 } 1149 }
1150 #undef PHI_CASE
865 } 1151 }
866 ReplaceNode(phi, rep_nodes); 1152 ReplaceNode(phi, rep_nodes, num_lanes);
867 } 1153 }
868 } 1154 }
869 } // namespace compiler 1155 } // namespace compiler
870 } // namespace internal 1156 } // namespace internal
871 } // namespace v8 1157 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/simd-scalar-lowering.h ('k') | test/cctest/wasm/test-run-wasm-simd.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698