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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
124 Signature<MachineRepresentation>* signature) { | 124 Signature<MachineRepresentation>* signature) { |
125 int result = static_cast<int>(signature->return_count()); | 125 int result = static_cast<int>(signature->return_count()); |
126 for (int i = 0; i < static_cast<int>(signature->return_count()); i++) { | 126 for (int i = 0; i < static_cast<int>(signature->return_count()); i++) { |
127 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) { | 127 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) { |
128 result += 3; | 128 result += 3; |
129 } | 129 } |
130 } | 130 } |
131 return result; | 131 return result; |
132 } | 132 } |
133 | 133 |
134 void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices) { | |
135 new_indices[0] = index; | |
136 for (size_t i = 1; i < kMaxLanes; i++) { | |
Mircea Trofin
2016/11/15 16:21:27
++i
aseemgarg
2016/11/19 01:56:54
Done.
| |
137 new_indices[i] = graph()->NewNode( | |
138 machine()->Int32Add(), index, | |
139 graph()->NewNode(common()->Int32Constant(static_cast<int>(i) * 4))); | |
titzer
2016/11/15 09:21:17
Should this be 16 / kMaxLanes for clarity?
Mircea Trofin
2016/11/15 16:21:27
Consider using the relevant constant for "4" (or "
aseemgarg
2016/11/19 01:56:54
Done. But I don't get how it is clearer? 4 is just
titzer
2016/11/22 12:01:52
I meant, please introduce a constant that defines
aseemgarg
2016/11/23 23:07:56
Done.
| |
140 } | |
141 } | |
142 | |
134 void SimdScalarLowering::LowerNode(Node* node) { | 143 void SimdScalarLowering::LowerNode(Node* node) { |
135 SimdType rep_type = ReplacementType(node); | 144 SimdType rep_type = ReplacementType(node); |
136 switch (node->opcode()) { | 145 switch (node->opcode()) { |
137 case IrOpcode::kStart: { | 146 case IrOpcode::kStart: { |
138 int parameter_count = GetParameterCountAfterLowering(); | 147 int parameter_count = GetParameterCountAfterLowering(); |
139 // Only exchange the node if the parameter count actually changed. | 148 // Only exchange the node if the parameter count actually changed. |
140 if (parameter_count != static_cast<int>(signature()->parameter_count())) { | 149 if (parameter_count != static_cast<int>(signature()->parameter_count())) { |
141 int delta = | 150 int delta = |
142 parameter_count - static_cast<int>(signature()->parameter_count()); | 151 parameter_count - static_cast<int>(signature()->parameter_count()); |
143 int new_output_count = node->op()->ValueOutputCount() + delta; | 152 int new_output_count = node->op()->ValueOutputCount() + delta; |
(...skipping 24 matching lines...) Expand all Loading... | |
168 for (int i = 1; i < kMaxLanes; i++) { | 177 for (int i = 1; i < kMaxLanes; i++) { |
169 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i), | 178 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i), |
170 graph()->start()); | 179 graph()->start()); |
171 } | 180 } |
172 } | 181 } |
173 ReplaceNode(node, new_node); | 182 ReplaceNode(node, new_node); |
174 } | 183 } |
175 } | 184 } |
176 break; | 185 break; |
177 } | 186 } |
187 case IrOpcode::kLoad: | |
188 case IrOpcode::kUnalignedLoad: { | |
189 MachineRepresentation rep; | |
190 if (node->opcode() == IrOpcode::kLoad) { | |
191 rep = LoadRepresentationOf(node->op()).representation(); | |
192 } else { | |
193 DCHECK(node->opcode() == IrOpcode::kUnalignedLoad); | |
194 rep = UnalignedLoadRepresentationOf(node->op()).representation(); | |
195 } | |
196 | |
197 if (rep == MachineRepresentation::kSimd128) { | |
198 Node* base = node->InputAt(0); | |
199 Node* index = node->InputAt(1); | |
200 Node* indices[kMaxLanes]; | |
201 GetIndexNodes(index, indices); | |
202 const Operator* load_op; | |
203 if (node->opcode() == IrOpcode::kLoad && rep_type == SimdType::kInt32) { | |
titzer
2016/11/15 09:21:17
Can you factor out a subroutines GetLoadOp() and G
aseemgarg
2016/11/19 01:56:54
Done.
| |
204 load_op = machine()->Load(MachineType::Int32()); | |
205 } else if (node->opcode() == IrOpcode::kLoad && | |
206 rep_type == SimdType::kFloat32) { | |
207 load_op = machine()->Load(MachineType::Float32()); | |
208 } else if (node->opcode() == IrOpcode::kUnalignedLoad && | |
209 rep_type == SimdType::kInt32) { | |
210 load_op = machine()->UnalignedLoad(MachineType::Int32()); | |
211 } else if (node->opcode() == IrOpcode::kUnalignedLoad && | |
212 rep_type == SimdType::kFloat32) { | |
213 load_op = machine()->UnalignedLoad(MachineType::Float32()); | |
214 } | |
215 | |
216 Node* rep_nodes[kMaxLanes]; | |
217 rep_nodes[0] = node; | |
218 NodeProperties::ChangeOp(rep_nodes[0], load_op); | |
219 if (node->InputCount() > 2) { | |
220 Node* effect_high = node->InputAt(2); | |
221 Node* control_high = node->InputAt(3); | |
Mircea Trofin
2016/11/15 16:21:27
aren't inputs 0 indexed? in that case, wouldn't In
aseemgarg
2016/11/19 01:56:54
The check for greater than 2 just tells that there
| |
222 rep_nodes[3] = graph()->NewNode(load_op, base, indices[3], | |
Mircea Trofin
2016/11/15 16:21:27
This all hinges on kMaxLanes > 3 (a DCHECK?)
aseemgarg
2016/11/19 01:56:54
Done.
| |
223 effect_high, control_high); | |
224 rep_nodes[2] = graph()->NewNode(load_op, base, indices[2], | |
225 rep_nodes[3], control_high); | |
226 rep_nodes[1] = graph()->NewNode(load_op, base, indices[1], | |
227 rep_nodes[2], control_high); | |
228 rep_nodes[0]->ReplaceInput(2, rep_nodes[1]); | |
229 } else { | |
230 for (size_t i = 1; i < kMaxLanes; i++) { | |
Mircea Trofin
2016/11/15 16:21:27
++i
aseemgarg
2016/11/19 01:56:54
Done.
| |
231 rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]); | |
232 } | |
233 } | |
234 ReplaceNode(node, rep_nodes); | |
235 } else { | |
236 DefaultLowering(node); | |
237 } | |
238 break; | |
239 } | |
240 case IrOpcode::kStore: | |
241 case IrOpcode::kUnalignedStore: { | |
242 MachineRepresentation rep; | |
243 if (node->opcode() == IrOpcode::kStore) { | |
244 rep = StoreRepresentationOf(node->op()).representation(); | |
245 } else { | |
246 DCHECK(node->opcode() == IrOpcode::kUnalignedStore); | |
247 rep = UnalignedStoreRepresentationOf(node->op()); | |
248 } | |
249 | |
250 if (rep == MachineRepresentation::kSimd128) { | |
251 Node* base = node->InputAt(0); | |
252 Node* index = node->InputAt(1); | |
253 Node* indices[4]; | |
Mircea Trofin
2016/11/15 16:21:26
what's "4"?
aseemgarg
2016/11/19 01:56:54
changed to kMaxLanes
| |
254 GetIndexNodes(index, indices); | |
255 Node* value = node->InputAt(2); | |
Mircea Trofin
2016/11/15 16:21:27
DCHECK node's input count
aseemgarg
2016/11/19 01:56:54
Done.
| |
256 DCHECK(HasReplacement(1, value)); | |
257 const Operator* store_op; | |
258 if (node->opcode() == IrOpcode::kStore) { | |
259 WriteBarrierKind write_barrier_kind = | |
260 StoreRepresentationOf(node->op()).write_barrier_kind(); | |
261 if (rep_type == SimdType::kInt32) { | |
262 store_op = machine()->Store(StoreRepresentation( | |
263 MachineRepresentation::kWord32, write_barrier_kind)); | |
264 } else { | |
265 store_op = machine()->Store(StoreRepresentation( | |
266 MachineRepresentation::kFloat32, write_barrier_kind)); | |
267 } | |
268 } else { | |
269 if (rep_type == SimdType::kInt32) { | |
270 store_op = | |
271 machine()->UnalignedStore(MachineRepresentation::kWord32); | |
272 } else { | |
273 store_op = | |
274 machine()->UnalignedStore(MachineRepresentation::kFloat32); | |
275 } | |
276 } | |
277 | |
278 Node* rep_nodes[kMaxLanes]; | |
279 rep_nodes[0] = node; | |
280 Node** rep_inputs = GetReplacementsWithType(value, rep_type); | |
281 rep_nodes[0]->ReplaceInput(2, rep_inputs[0]); | |
282 NodeProperties::ChangeOp(node, store_op); | |
283 if (node->InputCount() > 3) { | |
284 Node* effect_high = node->InputAt(3); | |
Mircea Trofin
2016/11/15 16:21:27
same question about input being 0 indexed
aseemgarg
2016/11/19 01:56:54
see above. Added Dcheck
titzer
2016/11/22 12:01:52
Can you just name this effect_input and control_in
aseemgarg
2016/11/23 23:07:56
Done.
| |
285 Node* control_high = node->InputAt(4); | |
286 rep_nodes[3] = | |
287 graph()->NewNode(store_op, base, indices[3], rep_inputs[3], | |
288 effect_high, control_high); | |
289 rep_nodes[2] = | |
290 graph()->NewNode(store_op, base, indices[2], rep_inputs[2], | |
291 rep_nodes[3], control_high); | |
292 rep_nodes[1] = | |
293 graph()->NewNode(store_op, base, indices[1], rep_inputs[1], | |
294 rep_nodes[2], control_high); | |
295 rep_nodes[0]->ReplaceInput(3, rep_nodes[1]); | |
titzer
2016/11/15 09:21:17
I think the effect chain is messed up here. I thin
aseemgarg
2016/11/19 01:56:54
I am not quite sure I understand how effect nodes
titzer
2016/11/22 12:01:52
Let me clarify a bit here. There isn't really an "
aseemgarg
2016/11/23 23:07:56
Didn't change anything. Leaving as is
On 2016/11/
| |
296 | |
297 } else { | |
298 for (size_t i = 1; i < kMaxLanes; i++) { | |
299 rep_nodes[i] = | |
300 graph()->NewNode(store_op, base, indices[i], rep_inputs[i]); | |
301 } | |
302 } | |
303 | |
304 ReplaceNode(node, rep_nodes); | |
305 } else { | |
306 DefaultLowering(node); | |
307 } | |
308 break; | |
309 } | |
178 case IrOpcode::kReturn: { | 310 case IrOpcode::kReturn: { |
179 DefaultLowering(node); | 311 DefaultLowering(node); |
180 int new_return_count = GetReturnCountAfterLowering(signature()); | 312 int new_return_count = GetReturnCountAfterLowering(signature()); |
181 if (static_cast<int>(signature()->return_count()) != new_return_count) { | 313 if (static_cast<int>(signature()->return_count()) != new_return_count) { |
182 NodeProperties::ChangeOp(node, common()->Return(new_return_count)); | 314 NodeProperties::ChangeOp(node, common()->Return(new_return_count)); |
183 } | 315 } |
184 break; | 316 break; |
185 } | 317 } |
186 case IrOpcode::kCall: { | 318 case IrOpcode::kCall: { |
187 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor. | 319 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 GetReplacementsWithType(node->InputAt(i), rep_type); | 351 GetReplacementsWithType(node->InputAt(i), rep_type); |
220 for (int j = 0; j < kMaxLanes; j++) { | 352 for (int j = 0; j < kMaxLanes; j++) { |
221 rep_node[j]->ReplaceInput(i, rep_input[j]); | 353 rep_node[j]->ReplaceInput(i, rep_input[j]); |
222 } | 354 } |
223 } | 355 } |
224 } else { | 356 } else { |
225 DefaultLowering(node); | 357 DefaultLowering(node); |
226 } | 358 } |
227 break; | 359 break; |
228 } | 360 } |
229 | 361 #define BINOP_CASE(opcode, replacementOp) \ |
titzer
2016/11/15 09:21:17
Can you make this into a call to a subroutine? AFA
aseemgarg
2016/11/19 01:56:54
Done.
| |
230 case IrOpcode::kInt32x4Add: { | 362 case IrOpcode::opcode: { \ |
231 DCHECK(node->InputCount() == 2); | 363 DCHECK(node->InputCount() == 2); \ |
232 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type); | 364 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type); \ |
233 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type); | 365 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type); \ |
366 Node* rep_node[kMaxLanes]; \ | |
367 for (int i = 0; i < kMaxLanes; i++) { \ | |
Mircea Trofin
2016/11/15 16:21:27
++i
aseemgarg
2016/11/19 01:56:54
Done.
| |
368 rep_node[i] = graph()->NewNode(machine()->replacementOp(), rep_left[i], \ | |
369 rep_right[i]); \ | |
370 } \ | |
371 ReplaceNode(node, rep_node); \ | |
372 break; \ | |
373 } | |
374 BINOP_CASE(kInt32x4Add, Int32Add) | |
375 BINOP_CASE(kFloat32x4Add, Float32Add) | |
376 #undef BINOP | |
377 case IrOpcode::kCreateInt32x4: | |
378 case IrOpcode::kCreateFloat32x4: { | |
234 Node* rep_node[kMaxLanes]; | 379 Node* rep_node[kMaxLanes]; |
235 for (int i = 0; i < kMaxLanes; i++) { | 380 for (int i = 0; i < kMaxLanes; i++) { |
Mircea Trofin
2016/11/15 16:21:27
++i
aseemgarg
2016/11/19 01:56:54
Done.
| |
236 rep_node[i] = | 381 if (HasReplacement(0, node->InputAt(i))) { |
237 graph()->NewNode(machine()->Int32Add(), rep_left[i], rep_right[i]); | 382 rep_node[i] = GetReplacements(node->InputAt(i))[0]; |
383 } else { | |
384 rep_node[i] = node->InputAt(i); | |
385 } | |
238 } | 386 } |
239 ReplaceNode(node, rep_node); | 387 ReplaceNode(node, rep_node); |
240 break; | 388 break; |
241 } | 389 } |
242 | 390 case IrOpcode::kInt32x4ExtractLane: |
243 case IrOpcode::kCreateInt32x4: { | 391 case IrOpcode::kFloat32x4ExtractLane: { |
244 Node* rep_node[kMaxLanes]; | |
245 for (int i = 0; i < kMaxLanes; i++) { | |
246 DCHECK(!HasReplacement(1, node->InputAt(i))); | |
247 rep_node[i] = node->InputAt(i); | |
248 } | |
249 ReplaceNode(node, rep_node); | |
250 break; | |
251 } | |
252 | |
253 case IrOpcode::kInt32x4ExtractLane: { | |
254 Node* laneNode = node->InputAt(1); | 392 Node* laneNode = node->InputAt(1); |
255 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); | 393 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); |
256 int32_t lane = OpParameter<int32_t>(laneNode); | 394 int32_t lane = OpParameter<int32_t>(laneNode); |
257 Node* rep_node[kMaxLanes] = { | 395 Node* rep_node[kMaxLanes] = { |
258 GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, | 396 GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, |
259 nullptr, nullptr}; | 397 nullptr, nullptr}; |
260 ReplaceNode(node, rep_node); | 398 ReplaceNode(node, rep_node); |
261 break; | 399 break; |
262 } | 400 } |
263 | 401 case IrOpcode::kInt32x4ReplaceLane: |
264 case IrOpcode::kFloat32x4Add: { | 402 case IrOpcode::kFloat32x4ReplaceLane: { |
265 DCHECK(node->InputCount() == 2); | 403 Node* laneNode = node->InputAt(1); |
266 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type); | 404 Node* repNode = node->InputAt(2); |
Mircea Trofin
2016/11/15 16:21:27
dcheck for input count
aseemgarg
2016/11/19 01:56:54
Done.
| |
267 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type); | 405 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); |
268 Node* rep_node[kMaxLanes]; | 406 int32_t lane = OpParameter<int32_t>(laneNode); |
Mircea Trofin
2016/11/15 16:21:27
dcheck lane is in bounds for rep_node
aseemgarg
2016/11/19 01:56:54
Done.
| |
269 for (int i = 0; i < kMaxLanes; i++) { | 407 Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type); |
270 rep_node[i] = graph()->NewNode(machine()->Float32Add(), rep_left[i], | 408 if (HasReplacement(0, repNode)) { |
271 rep_right[i]); | 409 rep_node[lane] = GetReplacements(repNode)[0]; |
410 } else { | |
411 rep_node[lane] = repNode; | |
272 } | 412 } |
273 ReplaceNode(node, rep_node); | 413 ReplaceNode(node, rep_node); |
274 break; | 414 break; |
275 } | 415 } |
276 | |
277 case IrOpcode::kCreateFloat32x4: { | |
278 Node* rep_node[kMaxLanes]; | |
279 for (int i = 0; i < kMaxLanes; i++) { | |
280 DCHECK(!HasReplacement(1, node->InputAt(i))); | |
281 rep_node[i] = node->InputAt(i); | |
282 } | |
283 ReplaceNode(node, rep_node); | |
284 break; | |
285 } | |
286 | |
287 case IrOpcode::kFloat32x4ExtractLane: { | |
288 Node* laneNode = node->InputAt(1); | |
289 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); | |
290 int32_t lane = OpParameter<int32_t>(laneNode); | |
291 Node* rep_node[kMaxLanes] = { | |
292 GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, | |
293 nullptr, nullptr}; | |
294 ReplaceNode(node, rep_node); | |
295 break; | |
296 } | |
297 | |
298 default: { DefaultLowering(node); } | 416 default: { DefaultLowering(node); } |
299 } | 417 } |
300 } | 418 } |
301 | 419 |
302 bool SimdScalarLowering::DefaultLowering(Node* node) { | 420 bool SimdScalarLowering::DefaultLowering(Node* node) { |
303 bool something_changed = false; | 421 bool something_changed = false; |
304 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { | 422 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { |
305 Node* input = node->InputAt(i); | 423 Node* input = node->InputAt(i); |
306 if (HasReplacement(0, input)) { | 424 if (HasReplacement(0, input)) { |
307 something_changed = true; | 425 something_changed = true; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 } else { | 519 } else { |
402 UNREACHABLE(); | 520 UNREACHABLE(); |
403 } | 521 } |
404 } | 522 } |
405 ReplaceNode(phi, rep_nodes); | 523 ReplaceNode(phi, rep_nodes); |
406 } | 524 } |
407 } | 525 } |
408 } // namespace compiler | 526 } // namespace compiler |
409 } // namespace internal | 527 } // namespace internal |
410 } // namespace v8 | 528 } // namespace v8 |
OLD | NEW |