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