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