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