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