| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 } else { | 51 } else { |
| 52 // Push the next input onto the stack. | 52 // Push the next input onto the stack. |
| 53 Node* input = top.node->InputAt(top.input_index++); | 53 Node* input = top.node->InputAt(top.input_index++); |
| 54 if (state_.Get(input) == State::kUnvisited) { | 54 if (state_.Get(input) == State::kUnvisited) { |
| 55 SetLoweredType(input, top.node); | 55 SetLoweredType(input, top.node); |
| 56 if (input->opcode() == IrOpcode::kPhi) { | 56 if (input->opcode() == IrOpcode::kPhi) { |
| 57 // To break cycles with phi nodes we push phis on a separate stack so | 57 // To break cycles with phi nodes we push phis on a separate stack so |
| 58 // that they are processed after all other nodes. | 58 // that they are processed after all other nodes. |
| 59 PreparePhiReplacement(input); | 59 PreparePhiReplacement(input); |
| 60 stack_.push_front({input, 0}); | 60 stack_.push_front({input, 0}); |
| 61 } else if (input->opcode() == IrOpcode::kEffectPhi || |
| 62 input->opcode() == IrOpcode::kLoop) { |
| 63 stack_.push_front({input, 0}); |
| 61 } else { | 64 } else { |
| 62 stack_.push_back({input, 0}); | 65 stack_.push_back({input, 0}); |
| 63 } | 66 } |
| 64 state_.Set(input, State::kOnStack); | 67 state_.Set(input, State::kOnStack); |
| 65 } | 68 } |
| 66 } | 69 } |
| 67 } | 70 } |
| 68 } | 71 } |
| 69 | 72 |
| 70 #define FOREACH_INT32X4_OPCODE(V) \ | 73 #define FOREACH_INT32X4_OPCODE(V) \ |
| (...skipping 24 matching lines...) Expand all Loading... |
| 95 default: | 98 default: |
| 96 replacements_[node->id()].type = replacements_[output->id()].type; | 99 replacements_[node->id()].type = replacements_[output->id()].type; |
| 97 } | 100 } |
| 98 } | 101 } |
| 99 | 102 |
| 100 static int GetParameterIndexAfterLowering( | 103 static int GetParameterIndexAfterLowering( |
| 101 Signature<MachineRepresentation>* signature, int old_index) { | 104 Signature<MachineRepresentation>* signature, int old_index) { |
| 102 // In function calls, the simd128 types are passed as 4 Int32 types. The | 105 // In function calls, the simd128 types are passed as 4 Int32 types. The |
| 103 // parameters are typecast to the types as needed for various operations. | 106 // parameters are typecast to the types as needed for various operations. |
| 104 int result = old_index; | 107 int result = old_index; |
| 105 for (int i = 0; i < old_index; i++) { | 108 for (int i = 0; i < old_index; ++i) { |
| 106 if (signature->GetParam(i) == MachineRepresentation::kSimd128) { | 109 if (signature->GetParam(i) == MachineRepresentation::kSimd128) { |
| 107 result += 3; | 110 result += 3; |
| 108 } | 111 } |
| 109 } | 112 } |
| 110 return result; | 113 return result; |
| 111 } | 114 } |
| 112 | 115 |
| 113 int SimdScalarLowering::GetParameterCountAfterLowering() { | 116 int SimdScalarLowering::GetParameterCountAfterLowering() { |
| 114 if (parameter_count_after_lowering_ == -1) { | 117 if (parameter_count_after_lowering_ == -1) { |
| 115 // GetParameterIndexAfterLowering(parameter_count) returns the parameter | 118 // GetParameterIndexAfterLowering(parameter_count) returns the parameter |
| 116 // count after lowering. | 119 // count after lowering. |
| 117 parameter_count_after_lowering_ = GetParameterIndexAfterLowering( | 120 parameter_count_after_lowering_ = GetParameterIndexAfterLowering( |
| 118 signature(), static_cast<int>(signature()->parameter_count())); | 121 signature(), static_cast<int>(signature()->parameter_count())); |
| 119 } | 122 } |
| 120 return parameter_count_after_lowering_; | 123 return parameter_count_after_lowering_; |
| 121 } | 124 } |
| 122 | 125 |
| 123 static int GetReturnCountAfterLowering( | 126 static int GetReturnCountAfterLowering( |
| 124 Signature<MachineRepresentation>* signature) { | 127 Signature<MachineRepresentation>* signature) { |
| 125 int result = static_cast<int>(signature->return_count()); | 128 int result = static_cast<int>(signature->return_count()); |
| 126 for (int i = 0; i < static_cast<int>(signature->return_count()); i++) { | 129 for (int i = 0; i < static_cast<int>(signature->return_count()); ++i) { |
| 127 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) { | 130 if (signature->GetReturn(i) == MachineRepresentation::kSimd128) { |
| 128 result += 3; | 131 result += 3; |
| 129 } | 132 } |
| 130 } | 133 } |
| 131 return result; | 134 return result; |
| 132 } | 135 } |
| 133 | 136 |
| 137 void SimdScalarLowering::GetIndexNodes(Node* index, Node** new_indices) { |
| 138 new_indices[0] = index; |
| 139 for (size_t i = 1; i < kMaxLanes; ++i) { |
| 140 new_indices[i] = graph()->NewNode(machine()->Int32Add(), index, |
| 141 graph()->NewNode(common()->Int32Constant( |
| 142 static_cast<int>(i) * kLaneWidth))); |
| 143 } |
| 144 } |
| 145 |
| 146 void SimdScalarLowering::LowerLoadOp(MachineRepresentation rep, Node* node, |
| 147 const Operator* load_op) { |
| 148 if (rep == MachineRepresentation::kSimd128) { |
| 149 Node* base = node->InputAt(0); |
| 150 Node* index = node->InputAt(1); |
| 151 Node* indices[kMaxLanes]; |
| 152 GetIndexNodes(index, indices); |
| 153 Node* rep_nodes[kMaxLanes]; |
| 154 rep_nodes[0] = node; |
| 155 NodeProperties::ChangeOp(rep_nodes[0], load_op); |
| 156 if (node->InputCount() > 2) { |
| 157 DCHECK(node->InputCount() > 3); |
| 158 Node* effect_input = node->InputAt(2); |
| 159 Node* control_input = node->InputAt(3); |
| 160 rep_nodes[3] = graph()->NewNode(load_op, base, indices[3], effect_input, |
| 161 control_input); |
| 162 rep_nodes[2] = graph()->NewNode(load_op, base, indices[2], rep_nodes[3], |
| 163 control_input); |
| 164 rep_nodes[1] = graph()->NewNode(load_op, base, indices[1], rep_nodes[2], |
| 165 control_input); |
| 166 rep_nodes[0]->ReplaceInput(2, rep_nodes[1]); |
| 167 } else { |
| 168 for (size_t i = 1; i < kMaxLanes; ++i) { |
| 169 rep_nodes[i] = graph()->NewNode(load_op, base, indices[i]); |
| 170 } |
| 171 } |
| 172 ReplaceNode(node, rep_nodes); |
| 173 } else { |
| 174 DefaultLowering(node); |
| 175 } |
| 176 } |
| 177 |
| 178 void SimdScalarLowering::LowerStoreOp(MachineRepresentation rep, Node* node, |
| 179 const Operator* store_op, |
| 180 SimdType rep_type) { |
| 181 if (rep == MachineRepresentation::kSimd128) { |
| 182 Node* base = node->InputAt(0); |
| 183 Node* index = node->InputAt(1); |
| 184 Node* indices[kMaxLanes]; |
| 185 GetIndexNodes(index, indices); |
| 186 DCHECK(node->InputCount() > 2); |
| 187 Node* value = node->InputAt(2); |
| 188 DCHECK(HasReplacement(1, value)); |
| 189 Node* rep_nodes[kMaxLanes]; |
| 190 rep_nodes[0] = node; |
| 191 Node** rep_inputs = GetReplacementsWithType(value, rep_type); |
| 192 rep_nodes[0]->ReplaceInput(2, rep_inputs[0]); |
| 193 NodeProperties::ChangeOp(node, store_op); |
| 194 if (node->InputCount() > 3) { |
| 195 DCHECK(node->InputCount() > 4); |
| 196 Node* effect_input = node->InputAt(3); |
| 197 Node* control_input = node->InputAt(4); |
| 198 rep_nodes[3] = graph()->NewNode(store_op, base, indices[3], rep_inputs[3], |
| 199 effect_input, control_input); |
| 200 rep_nodes[2] = graph()->NewNode(store_op, base, indices[2], rep_inputs[2], |
| 201 rep_nodes[3], control_input); |
| 202 rep_nodes[1] = graph()->NewNode(store_op, base, indices[1], rep_inputs[1], |
| 203 rep_nodes[2], control_input); |
| 204 rep_nodes[0]->ReplaceInput(3, rep_nodes[1]); |
| 205 |
| 206 } else { |
| 207 for (size_t i = 1; i < kMaxLanes; ++i) { |
| 208 rep_nodes[i] = |
| 209 graph()->NewNode(store_op, base, indices[i], rep_inputs[i]); |
| 210 } |
| 211 } |
| 212 |
| 213 ReplaceNode(node, rep_nodes); |
| 214 } else { |
| 215 DefaultLowering(node); |
| 216 } |
| 217 } |
| 218 |
| 219 void SimdScalarLowering::LowerBinaryOp(Node* node, SimdType rep_type, |
| 220 const Operator* op) { |
| 221 DCHECK(node->InputCount() == 2); |
| 222 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type); |
| 223 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type); |
| 224 Node* rep_node[kMaxLanes]; |
| 225 for (int i = 0; i < kMaxLanes; ++i) { |
| 226 rep_node[i] = graph()->NewNode(op, rep_left[i], rep_right[i]); |
| 227 } |
| 228 ReplaceNode(node, rep_node); |
| 229 } |
| 230 |
| 134 void SimdScalarLowering::LowerNode(Node* node) { | 231 void SimdScalarLowering::LowerNode(Node* node) { |
| 135 SimdType rep_type = ReplacementType(node); | 232 SimdType rep_type = ReplacementType(node); |
| 136 switch (node->opcode()) { | 233 switch (node->opcode()) { |
| 137 case IrOpcode::kStart: { | 234 case IrOpcode::kStart: { |
| 138 int parameter_count = GetParameterCountAfterLowering(); | 235 int parameter_count = GetParameterCountAfterLowering(); |
| 139 // Only exchange the node if the parameter count actually changed. | 236 // Only exchange the node if the parameter count actually changed. |
| 140 if (parameter_count != static_cast<int>(signature()->parameter_count())) { | 237 if (parameter_count != static_cast<int>(signature()->parameter_count())) { |
| 141 int delta = | 238 int delta = |
| 142 parameter_count - static_cast<int>(signature()->parameter_count()); | 239 parameter_count - static_cast<int>(signature()->parameter_count()); |
| 143 int new_output_count = node->op()->ValueOutputCount() + delta; | 240 int new_output_count = node->op()->ValueOutputCount() + delta; |
| 144 NodeProperties::ChangeOp(node, common()->Start(new_output_count)); | 241 NodeProperties::ChangeOp(node, common()->Start(new_output_count)); |
| 145 } | 242 } |
| 146 break; | 243 break; |
| 147 } | 244 } |
| 148 case IrOpcode::kParameter: { | 245 case IrOpcode::kParameter: { |
| 149 DCHECK(node->InputCount() == 1); | 246 DCHECK(node->InputCount() == 1); |
| 150 // Only exchange the node if the parameter count actually changed. We do | 247 // Only exchange the node if the parameter count actually changed. We do |
| 151 // not even have to do the default lowering because the the start node, | 248 // not even have to do the default lowering because the the start node, |
| 152 // the only input of a parameter node, only changes if the parameter count | 249 // the only input of a parameter node, only changes if the parameter count |
| 153 // changes. | 250 // changes. |
| 154 if (GetParameterCountAfterLowering() != | 251 if (GetParameterCountAfterLowering() != |
| 155 static_cast<int>(signature()->parameter_count())) { | 252 static_cast<int>(signature()->parameter_count())) { |
| 156 int old_index = ParameterIndexOf(node->op()); | 253 int old_index = ParameterIndexOf(node->op()); |
| 157 int new_index = GetParameterIndexAfterLowering(signature(), old_index); | 254 int new_index = GetParameterIndexAfterLowering(signature(), old_index); |
| 158 if (old_index == new_index) { | 255 if (old_index == new_index) { |
| 159 NodeProperties::ChangeOp(node, common()->Parameter(new_index)); | 256 NodeProperties::ChangeOp(node, common()->Parameter(new_index)); |
| 160 | 257 |
| 161 Node* new_node[kMaxLanes]; | 258 Node* new_node[kMaxLanes]; |
| 162 for (int i = 0; i < kMaxLanes; i++) { | 259 for (int i = 0; i < kMaxLanes; ++i) { |
| 163 new_node[i] = nullptr; | 260 new_node[i] = nullptr; |
| 164 } | 261 } |
| 165 new_node[0] = node; | 262 new_node[0] = node; |
| 166 if (signature()->GetParam(old_index) == | 263 if (signature()->GetParam(old_index) == |
| 167 MachineRepresentation::kSimd128) { | 264 MachineRepresentation::kSimd128) { |
| 168 for (int i = 1; i < kMaxLanes; i++) { | 265 for (int i = 1; i < kMaxLanes; ++i) { |
| 169 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i), | 266 new_node[i] = graph()->NewNode(common()->Parameter(new_index + i), |
| 170 graph()->start()); | 267 graph()->start()); |
| 171 } | 268 } |
| 172 } | 269 } |
| 173 ReplaceNode(node, new_node); | 270 ReplaceNode(node, new_node); |
| 174 } | 271 } |
| 175 } | 272 } |
| 176 break; | 273 break; |
| 177 } | 274 } |
| 275 case IrOpcode::kLoad: { |
| 276 MachineRepresentation rep = |
| 277 LoadRepresentationOf(node->op()).representation(); |
| 278 const Operator* load_op; |
| 279 if (rep_type == SimdType::kInt32) { |
| 280 load_op = machine()->Load(MachineType::Int32()); |
| 281 } else if (rep_type == SimdType::kFloat32) { |
| 282 load_op = machine()->Load(MachineType::Float32()); |
| 283 } |
| 284 LowerLoadOp(rep, node, load_op); |
| 285 break; |
| 286 } |
| 287 case IrOpcode::kUnalignedLoad: { |
| 288 MachineRepresentation rep = |
| 289 UnalignedLoadRepresentationOf(node->op()).representation(); |
| 290 const Operator* load_op; |
| 291 if (rep_type == SimdType::kInt32) { |
| 292 load_op = machine()->UnalignedLoad(MachineType::Int32()); |
| 293 } else if (rep_type == SimdType::kFloat32) { |
| 294 load_op = machine()->UnalignedLoad(MachineType::Float32()); |
| 295 } |
| 296 LowerLoadOp(rep, node, load_op); |
| 297 break; |
| 298 } |
| 299 case IrOpcode::kStore: { |
| 300 MachineRepresentation rep = |
| 301 StoreRepresentationOf(node->op()).representation(); |
| 302 WriteBarrierKind write_barrier_kind = |
| 303 StoreRepresentationOf(node->op()).write_barrier_kind(); |
| 304 const Operator* store_op; |
| 305 if (rep_type == SimdType::kInt32) { |
| 306 store_op = machine()->Store(StoreRepresentation( |
| 307 MachineRepresentation::kWord32, write_barrier_kind)); |
| 308 } else { |
| 309 store_op = machine()->Store(StoreRepresentation( |
| 310 MachineRepresentation::kFloat32, write_barrier_kind)); |
| 311 } |
| 312 LowerStoreOp(rep, node, store_op, rep_type); |
| 313 break; |
| 314 } |
| 315 case IrOpcode::kUnalignedStore: { |
| 316 MachineRepresentation rep = UnalignedStoreRepresentationOf(node->op()); |
| 317 const Operator* store_op; |
| 318 if (rep_type == SimdType::kInt32) { |
| 319 store_op = machine()->UnalignedStore(MachineRepresentation::kWord32); |
| 320 } else { |
| 321 store_op = machine()->UnalignedStore(MachineRepresentation::kFloat32); |
| 322 } |
| 323 LowerStoreOp(rep, node, store_op, rep_type); |
| 324 break; |
| 325 } |
| 178 case IrOpcode::kReturn: { | 326 case IrOpcode::kReturn: { |
| 179 DefaultLowering(node); | 327 DefaultLowering(node); |
| 180 int new_return_count = GetReturnCountAfterLowering(signature()); | 328 int new_return_count = GetReturnCountAfterLowering(signature()); |
| 181 if (static_cast<int>(signature()->return_count()) != new_return_count) { | 329 if (static_cast<int>(signature()->return_count()) != new_return_count) { |
| 182 NodeProperties::ChangeOp(node, common()->Return(new_return_count)); | 330 NodeProperties::ChangeOp(node, common()->Return(new_return_count)); |
| 183 } | 331 } |
| 184 break; | 332 break; |
| 185 } | 333 } |
| 186 case IrOpcode::kCall: { | 334 case IrOpcode::kCall: { |
| 187 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor. | 335 // TODO(turbofan): Make WASM code const-correct wrt. CallDescriptor. |
| 188 CallDescriptor* descriptor = | 336 CallDescriptor* descriptor = |
| 189 const_cast<CallDescriptor*>(CallDescriptorOf(node->op())); | 337 const_cast<CallDescriptor*>(CallDescriptorOf(node->op())); |
| 190 if (DefaultLowering(node) || | 338 if (DefaultLowering(node) || |
| 191 (descriptor->ReturnCount() == 1 && | 339 (descriptor->ReturnCount() == 1 && |
| 192 descriptor->GetReturnType(0) == MachineType::Simd128())) { | 340 descriptor->GetReturnType(0) == MachineType::Simd128())) { |
| 193 // We have to adjust the call descriptor. | 341 // We have to adjust the call descriptor. |
| 194 const Operator* op = | 342 const Operator* op = |
| 195 common()->Call(wasm::ModuleEnv::GetI32WasmCallDescriptorForSimd( | 343 common()->Call(wasm::ModuleEnv::GetI32WasmCallDescriptorForSimd( |
| 196 zone(), descriptor)); | 344 zone(), descriptor)); |
| 197 NodeProperties::ChangeOp(node, op); | 345 NodeProperties::ChangeOp(node, op); |
| 198 } | 346 } |
| 199 if (descriptor->ReturnCount() == 1 && | 347 if (descriptor->ReturnCount() == 1 && |
| 200 descriptor->GetReturnType(0) == MachineType::Simd128()) { | 348 descriptor->GetReturnType(0) == MachineType::Simd128()) { |
| 201 // We access the additional return values through projections. | 349 // We access the additional return values through projections. |
| 202 Node* rep_node[kMaxLanes]; | 350 Node* rep_node[kMaxLanes]; |
| 203 for (int i = 0; i < kMaxLanes; i++) { | 351 for (int i = 0; i < kMaxLanes; ++i) { |
| 204 rep_node[i] = | 352 rep_node[i] = |
| 205 graph()->NewNode(common()->Projection(i), node, graph()->start()); | 353 graph()->NewNode(common()->Projection(i), node, graph()->start()); |
| 206 } | 354 } |
| 207 ReplaceNode(node, rep_node); | 355 ReplaceNode(node, rep_node); |
| 208 } | 356 } |
| 209 break; | 357 break; |
| 210 } | 358 } |
| 211 case IrOpcode::kPhi: { | 359 case IrOpcode::kPhi: { |
| 212 MachineRepresentation rep = PhiRepresentationOf(node->op()); | 360 MachineRepresentation rep = PhiRepresentationOf(node->op()); |
| 213 if (rep == MachineRepresentation::kSimd128) { | 361 if (rep == MachineRepresentation::kSimd128) { |
| 214 // The replacement nodes have already been created, we only have to | 362 // The replacement nodes have already been created, we only have to |
| 215 // replace placeholder nodes. | 363 // replace placeholder nodes. |
| 216 Node** rep_node = GetReplacements(node); | 364 Node** rep_node = GetReplacements(node); |
| 217 for (int i = 0; i < node->op()->ValueInputCount(); i++) { | 365 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |
| 218 Node** rep_input = | 366 Node** rep_input = |
| 219 GetReplacementsWithType(node->InputAt(i), rep_type); | 367 GetReplacementsWithType(node->InputAt(i), rep_type); |
| 220 for (int j = 0; j < kMaxLanes; j++) { | 368 for (int j = 0; j < kMaxLanes; j++) { |
| 221 rep_node[j]->ReplaceInput(i, rep_input[j]); | 369 rep_node[j]->ReplaceInput(i, rep_input[j]); |
| 222 } | 370 } |
| 223 } | 371 } |
| 224 } else { | 372 } else { |
| 225 DefaultLowering(node); | 373 DefaultLowering(node); |
| 226 } | 374 } |
| 227 break; | 375 break; |
| 228 } | 376 } |
| 229 | |
| 230 case IrOpcode::kInt32x4Add: { | 377 case IrOpcode::kInt32x4Add: { |
| 231 DCHECK(node->InputCount() == 2); | 378 LowerBinaryOp(node, rep_type, machine()->Int32Add()); |
| 232 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type); | 379 break; |
| 233 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type); | 380 } |
| 381 case IrOpcode::kFloat32x4Add: { |
| 382 LowerBinaryOp(node, rep_type, machine()->Float32Add()); |
| 383 break; |
| 384 } |
| 385 case IrOpcode::kCreateInt32x4: |
| 386 case IrOpcode::kCreateFloat32x4: { |
| 234 Node* rep_node[kMaxLanes]; | 387 Node* rep_node[kMaxLanes]; |
| 235 for (int i = 0; i < kMaxLanes; i++) { | 388 for (int i = 0; i < kMaxLanes; ++i) { |
| 236 rep_node[i] = | 389 if (HasReplacement(0, node->InputAt(i))) { |
| 237 graph()->NewNode(machine()->Int32Add(), rep_left[i], rep_right[i]); | 390 rep_node[i] = GetReplacements(node->InputAt(i))[0]; |
| 391 } else { |
| 392 rep_node[i] = node->InputAt(i); |
| 393 } |
| 238 } | 394 } |
| 239 ReplaceNode(node, rep_node); | 395 ReplaceNode(node, rep_node); |
| 240 break; | 396 break; |
| 241 } | 397 } |
| 242 | 398 case IrOpcode::kInt32x4ExtractLane: |
| 243 case IrOpcode::kCreateInt32x4: { | 399 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); | 400 Node* laneNode = node->InputAt(1); |
| 255 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); | 401 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); |
| 256 int32_t lane = OpParameter<int32_t>(laneNode); | 402 int32_t lane = OpParameter<int32_t>(laneNode); |
| 257 Node* rep_node[kMaxLanes] = { | 403 Node* rep_node[kMaxLanes] = { |
| 258 GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, | 404 GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, |
| 259 nullptr, nullptr}; | 405 nullptr, nullptr}; |
| 260 ReplaceNode(node, rep_node); | 406 ReplaceNode(node, rep_node); |
| 261 break; | 407 break; |
| 262 } | 408 } |
| 263 | 409 case IrOpcode::kInt32x4ReplaceLane: |
| 264 case IrOpcode::kFloat32x4Add: { | 410 case IrOpcode::kFloat32x4ReplaceLane: { |
| 265 DCHECK(node->InputCount() == 2); | 411 DCHECK_EQ(3, node->InputCount()); |
| 266 Node** rep_left = GetReplacementsWithType(node->InputAt(0), rep_type); | 412 Node* laneNode = node->InputAt(1); |
| 267 Node** rep_right = GetReplacementsWithType(node->InputAt(1), rep_type); | 413 Node* repNode = node->InputAt(2); |
| 268 Node* rep_node[kMaxLanes]; | 414 DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant); |
| 269 for (int i = 0; i < kMaxLanes; i++) { | 415 int32_t lane = OpParameter<int32_t>(laneNode); |
| 270 rep_node[i] = graph()->NewNode(machine()->Float32Add(), rep_left[i], | 416 DCHECK(lane >= 0 && lane <= 3); |
| 271 rep_right[i]); | 417 Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type); |
| 418 if (HasReplacement(0, repNode)) { |
| 419 rep_node[lane] = GetReplacements(repNode)[0]; |
| 420 } else { |
| 421 rep_node[lane] = repNode; |
| 272 } | 422 } |
| 273 ReplaceNode(node, rep_node); | 423 ReplaceNode(node, rep_node); |
| 274 break; | 424 break; |
| 275 } | 425 } |
| 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); } | 426 default: { DefaultLowering(node); } |
| 299 } | 427 } |
| 300 } | 428 } |
| 301 | 429 |
| 302 bool SimdScalarLowering::DefaultLowering(Node* node) { | 430 bool SimdScalarLowering::DefaultLowering(Node* node) { |
| 303 bool something_changed = false; | 431 bool something_changed = false; |
| 304 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { | 432 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) { |
| 305 Node* input = node->InputAt(i); | 433 Node* input = node->InputAt(i); |
| 306 if (HasReplacement(0, input)) { | 434 if (HasReplacement(0, input)) { |
| 307 something_changed = true; | 435 something_changed = true; |
| 308 node->ReplaceInput(i, GetReplacements(input)[0]); | 436 node->ReplaceInput(i, GetReplacements(input)[0]); |
| 309 } | 437 } |
| 310 if (HasReplacement(1, input)) { | 438 if (HasReplacement(1, input)) { |
| 311 something_changed = true; | 439 something_changed = true; |
| 312 for (int j = 1; j < kMaxLanes; j++) { | 440 for (int j = 1; j < kMaxLanes; j++) { |
| 313 node->InsertInput(zone(), i + j, GetReplacements(input)[j]); | 441 node->InsertInput(zone(), i + j, GetReplacements(input)[j]); |
| 314 } | 442 } |
| 315 } | 443 } |
| 316 } | 444 } |
| 317 return something_changed; | 445 return something_changed; |
| 318 } | 446 } |
| 319 | 447 |
| 320 void SimdScalarLowering::ReplaceNode(Node* old, Node** new_node) { | 448 void SimdScalarLowering::ReplaceNode(Node* old, Node** new_node) { |
| 321 // if new_low == nullptr, then also new_high == nullptr. | 449 // if new_low == nullptr, then also new_high == nullptr. |
| 322 DCHECK(new_node[0] != nullptr || | 450 DCHECK(new_node[0] != nullptr || |
| 323 (new_node[1] == nullptr && new_node[2] == nullptr && | 451 (new_node[1] == nullptr && new_node[2] == nullptr && |
| 324 new_node[3] == nullptr)); | 452 new_node[3] == nullptr)); |
| 325 for (int i = 0; i < kMaxLanes; i++) { | 453 for (int i = 0; i < kMaxLanes; ++i) { |
| 326 replacements_[old->id()].node[i] = new_node[i]; | 454 replacements_[old->id()].node[i] = new_node[i]; |
| 327 } | 455 } |
| 328 } | 456 } |
| 329 | 457 |
| 330 bool SimdScalarLowering::HasReplacement(size_t index, Node* node) { | 458 bool SimdScalarLowering::HasReplacement(size_t index, Node* node) { |
| 331 return replacements_[node->id()].node[index] != nullptr; | 459 return replacements_[node->id()].node[index] != nullptr; |
| 332 } | 460 } |
| 333 | 461 |
| 334 SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) { | 462 SimdScalarLowering::SimdType SimdScalarLowering::ReplacementType(Node* node) { |
| 335 return replacements_[node->id()].type; | 463 return replacements_[node->id()].type; |
| 336 } | 464 } |
| 337 | 465 |
| 338 Node** SimdScalarLowering::GetReplacements(Node* node) { | 466 Node** SimdScalarLowering::GetReplacements(Node* node) { |
| 339 Node** result = replacements_[node->id()].node; | 467 Node** result = replacements_[node->id()].node; |
| 340 DCHECK(result); | 468 DCHECK(result); |
| 341 return result; | 469 return result; |
| 342 } | 470 } |
| 343 | 471 |
| 344 Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) { | 472 Node** SimdScalarLowering::GetReplacementsWithType(Node* node, SimdType type) { |
| 345 Node** replacements = GetReplacements(node); | 473 Node** replacements = GetReplacements(node); |
| 346 if (ReplacementType(node) == type) { | 474 if (ReplacementType(node) == type) { |
| 347 return GetReplacements(node); | 475 return GetReplacements(node); |
| 348 } | 476 } |
| 349 Node** result = zone()->NewArray<Node*>(kMaxLanes); | 477 Node** result = zone()->NewArray<Node*>(kMaxLanes); |
| 350 if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) { | 478 if (ReplacementType(node) == SimdType::kInt32 && type == SimdType::kFloat32) { |
| 351 for (int i = 0; i < kMaxLanes; i++) { | 479 for (int i = 0; i < kMaxLanes; ++i) { |
| 352 if (replacements[i] != nullptr) { | 480 if (replacements[i] != nullptr) { |
| 353 result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(), | 481 result[i] = graph()->NewNode(machine()->BitcastInt32ToFloat32(), |
| 354 replacements[i]); | 482 replacements[i]); |
| 355 } else { | 483 } else { |
| 356 result[i] = nullptr; | 484 result[i] = nullptr; |
| 357 } | 485 } |
| 358 } | 486 } |
| 359 } else { | 487 } else { |
| 360 for (int i = 0; i < kMaxLanes; i++) { | 488 for (int i = 0; i < kMaxLanes; ++i) { |
| 361 if (replacements[i] != nullptr) { | 489 if (replacements[i] != nullptr) { |
| 362 result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(), | 490 result[i] = graph()->NewNode(machine()->BitcastFloat32ToInt32(), |
| 363 replacements[i]); | 491 replacements[i]); |
| 364 } else { | 492 } else { |
| 365 result[i] = nullptr; | 493 result[i] = nullptr; |
| 366 } | 494 } |
| 367 } | 495 } |
| 368 } | 496 } |
| 369 return result; | 497 return result; |
| 370 } | 498 } |
| 371 | 499 |
| 372 void SimdScalarLowering::PreparePhiReplacement(Node* phi) { | 500 void SimdScalarLowering::PreparePhiReplacement(Node* phi) { |
| 373 MachineRepresentation rep = PhiRepresentationOf(phi->op()); | 501 MachineRepresentation rep = PhiRepresentationOf(phi->op()); |
| 374 if (rep == MachineRepresentation::kSimd128) { | 502 if (rep == MachineRepresentation::kSimd128) { |
| 375 // We have to create the replacements for a phi node before we actually | 503 // We have to create the replacements for a phi node before we actually |
| 376 // lower the phi to break potential cycles in the graph. The replacements of | 504 // lower the phi to break potential cycles in the graph. The replacements of |
| 377 // input nodes do not exist yet, so we use a placeholder node to pass the | 505 // input nodes do not exist yet, so we use a placeholder node to pass the |
| 378 // graph verifier. | 506 // graph verifier. |
| 379 int value_count = phi->op()->ValueInputCount(); | 507 int value_count = phi->op()->ValueInputCount(); |
| 380 SimdType type = ReplacementType(phi); | 508 SimdType type = ReplacementType(phi); |
| 381 Node** inputs_rep[kMaxLanes]; | 509 Node** inputs_rep[kMaxLanes]; |
| 382 for (int i = 0; i < kMaxLanes; i++) { | 510 for (int i = 0; i < kMaxLanes; ++i) { |
| 383 inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1); | 511 inputs_rep[i] = zone()->NewArray<Node*>(value_count + 1); |
| 384 inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0); | 512 inputs_rep[i][value_count] = NodeProperties::GetControlInput(phi, 0); |
| 385 } | 513 } |
| 386 for (int i = 0; i < value_count; i++) { | 514 for (int i = 0; i < value_count; ++i) { |
| 387 for (int j = 0; j < kMaxLanes; j++) { | 515 for (int j = 0; j < kMaxLanes; j++) { |
| 388 inputs_rep[j][i] = placeholder_; | 516 inputs_rep[j][i] = placeholder_; |
| 389 } | 517 } |
| 390 } | 518 } |
| 391 Node* rep_nodes[kMaxLanes]; | 519 Node* rep_nodes[kMaxLanes]; |
| 392 for (int i = 0; i < kMaxLanes; i++) { | 520 for (int i = 0; i < kMaxLanes; ++i) { |
| 393 if (type == SimdType::kInt32) { | 521 if (type == SimdType::kInt32) { |
| 394 rep_nodes[i] = graph()->NewNode( | 522 rep_nodes[i] = graph()->NewNode( |
| 395 common()->Phi(MachineRepresentation::kWord32, value_count), | 523 common()->Phi(MachineRepresentation::kWord32, value_count), |
| 396 value_count + 1, inputs_rep[i], false); | 524 value_count + 1, inputs_rep[i], false); |
| 397 } else if (type == SimdType::kFloat32) { | 525 } else if (type == SimdType::kFloat32) { |
| 398 rep_nodes[i] = graph()->NewNode( | 526 rep_nodes[i] = graph()->NewNode( |
| 399 common()->Phi(MachineRepresentation::kFloat32, value_count), | 527 common()->Phi(MachineRepresentation::kFloat32, value_count), |
| 400 value_count + 1, inputs_rep[i], false); | 528 value_count + 1, inputs_rep[i], false); |
| 401 } else { | 529 } else { |
| 402 UNREACHABLE(); | 530 UNREACHABLE(); |
| 403 } | 531 } |
| 404 } | 532 } |
| 405 ReplaceNode(phi, rep_nodes); | 533 ReplaceNode(phi, rep_nodes); |
| 406 } | 534 } |
| 407 } | 535 } |
| 408 } // namespace compiler | 536 } // namespace compiler |
| 409 } // namespace internal | 537 } // namespace internal |
| 410 } // namespace v8 | 538 } // namespace v8 |
| OLD | NEW |