Chromium Code Reviews| 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 |