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