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