OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 g.UseRegister(mright.left().node()), | 1263 g.UseRegister(mright.left().node()), |
1264 g.UseRegister(mright.right().node()), | 1264 g.UseRegister(mright.right().node()), |
1265 g.UseRegister(m.left().node())); | 1265 g.UseRegister(m.left().node())); |
1266 return; | 1266 return; |
1267 } | 1267 } |
1268 } | 1268 } |
1269 | 1269 |
1270 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); | 1270 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); |
1271 } | 1271 } |
1272 | 1272 |
| 1273 namespace { |
| 1274 |
| 1275 void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node, |
| 1276 FlagsContinuation* cont) { |
| 1277 Arm64OperandGenerator g(selector); |
| 1278 Int32BinopMatcher m(node); |
| 1279 InstructionOperand result = g.DefineAsRegister(node); |
| 1280 InstructionOperand left = g.UseRegister(m.left().node()); |
| 1281 InstructionOperand right = g.UseRegister(m.right().node()); |
| 1282 selector->Emit(kArm64Smull, result, left, right); |
| 1283 |
| 1284 InstructionCode opcode = cont->Encode(kArm64Cmp) | |
| 1285 AddressingModeField::encode(kMode_Operand2_R_SXTW); |
| 1286 if (cont->IsBranch()) { |
| 1287 selector->Emit(opcode, g.NoOutput(), result, result, |
| 1288 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1289 } else if (cont->IsDeoptimize()) { |
| 1290 InstructionOperand in[] = {result, result}; |
| 1291 selector->EmitDeoptimize(opcode, 0, nullptr, 2, in, cont->frame_state()); |
| 1292 } else { |
| 1293 DCHECK(cont->IsSet()); |
| 1294 selector->Emit(opcode, g.DefineAsRegister(cont->result()), result, result); |
| 1295 } |
| 1296 } |
| 1297 |
| 1298 } // namespace |
1273 | 1299 |
1274 void InstructionSelector::VisitInt32Mul(Node* node) { | 1300 void InstructionSelector::VisitInt32Mul(Node* node) { |
1275 Arm64OperandGenerator g(this); | 1301 Arm64OperandGenerator g(this); |
1276 Int32BinopMatcher m(node); | 1302 Int32BinopMatcher m(node); |
1277 | 1303 |
1278 // First, try to reduce the multiplication to addition with left shift. | 1304 // First, try to reduce the multiplication to addition with left shift. |
1279 // x * (2^k + 1) -> x + (x << k) | 1305 // x * (2^k + 1) -> x + (x << k) |
1280 int32_t shift = LeftShiftForReducedMultiply(&m); | 1306 int32_t shift = LeftShiftForReducedMultiply(&m); |
1281 if (shift > 0) { | 1307 if (shift > 0) { |
1282 Emit(kArm64Add32 | AddressingModeField::encode(kMode_Operand2_R_LSL_I), | 1308 Emit(kArm64Add32 | AddressingModeField::encode(kMode_Operand2_R_LSL_I), |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 if (mright.left().Is(0)) { | 1372 if (mright.left().Is(0)) { |
1347 Emit(kArm64Mneg, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 1373 Emit(kArm64Mneg, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
1348 g.UseRegister(mright.right().node())); | 1374 g.UseRegister(mright.right().node())); |
1349 return; | 1375 return; |
1350 } | 1376 } |
1351 } | 1377 } |
1352 | 1378 |
1353 VisitRRR(this, kArm64Mul, node); | 1379 VisitRRR(this, kArm64Mul, node); |
1354 } | 1380 } |
1355 | 1381 |
1356 | |
1357 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 1382 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
1358 Arm64OperandGenerator g(this); | 1383 Arm64OperandGenerator g(this); |
1359 InstructionOperand const smull_operand = g.TempRegister(); | 1384 InstructionOperand const smull_operand = g.TempRegister(); |
1360 Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)), | 1385 Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)), |
1361 g.UseRegister(node->InputAt(1))); | 1386 g.UseRegister(node->InputAt(1))); |
1362 Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); | 1387 Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); |
1363 } | 1388 } |
1364 | 1389 |
1365 | 1390 |
1366 void InstructionSelector::VisitUint32MulHigh(Node* node) { | 1391 void InstructionSelector::VisitUint32MulHigh(Node* node) { |
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2241 if (result == nullptr || selector->IsDefined(result)) { | 2266 if (result == nullptr || selector->IsDefined(result)) { |
2242 switch (node->opcode()) { | 2267 switch (node->opcode()) { |
2243 case IrOpcode::kInt32AddWithOverflow: | 2268 case IrOpcode::kInt32AddWithOverflow: |
2244 cont->OverwriteAndNegateIfEqual(kOverflow); | 2269 cont->OverwriteAndNegateIfEqual(kOverflow); |
2245 return VisitBinop<Int32BinopMatcher>( | 2270 return VisitBinop<Int32BinopMatcher>( |
2246 selector, node, kArm64Add32, kArithmeticImm, cont); | 2271 selector, node, kArm64Add32, kArithmeticImm, cont); |
2247 case IrOpcode::kInt32SubWithOverflow: | 2272 case IrOpcode::kInt32SubWithOverflow: |
2248 cont->OverwriteAndNegateIfEqual(kOverflow); | 2273 cont->OverwriteAndNegateIfEqual(kOverflow); |
2249 return VisitBinop<Int32BinopMatcher>( | 2274 return VisitBinop<Int32BinopMatcher>( |
2250 selector, node, kArm64Sub32, kArithmeticImm, cont); | 2275 selector, node, kArm64Sub32, kArithmeticImm, cont); |
| 2276 case IrOpcode::kInt32MulWithOverflow: |
| 2277 // ARM64 doesn't set the overflow flag for multiplication, so we |
| 2278 // need to test on kNotEqual. Here is the code sequence used: |
| 2279 // smull result, left, right |
| 2280 // cmp result.X(), Operand(result, SXTW) |
| 2281 cont->OverwriteAndNegateIfEqual(kNotEqual); |
| 2282 return EmitInt32MulWithOverflow(selector, node, cont); |
2251 case IrOpcode::kInt64AddWithOverflow: | 2283 case IrOpcode::kInt64AddWithOverflow: |
2252 cont->OverwriteAndNegateIfEqual(kOverflow); | 2284 cont->OverwriteAndNegateIfEqual(kOverflow); |
2253 return VisitBinop<Int64BinopMatcher>(selector, node, kArm64Add, | 2285 return VisitBinop<Int64BinopMatcher>(selector, node, kArm64Add, |
2254 kArithmeticImm, cont); | 2286 kArithmeticImm, cont); |
2255 case IrOpcode::kInt64SubWithOverflow: | 2287 case IrOpcode::kInt64SubWithOverflow: |
2256 cont->OverwriteAndNegateIfEqual(kOverflow); | 2288 cont->OverwriteAndNegateIfEqual(kOverflow); |
2257 return VisitBinop<Int64BinopMatcher>(selector, node, kArm64Sub, | 2289 return VisitBinop<Int64BinopMatcher>(selector, node, kArm64Sub, |
2258 kArithmeticImm, cont); | 2290 kArithmeticImm, cont); |
2259 default: | 2291 default: |
2260 break; | 2292 break; |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2448 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { | 2480 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) { |
2449 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 2481 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
2450 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 2482 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
2451 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, | 2483 return VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, |
2452 kArithmeticImm, &cont); | 2484 kArithmeticImm, &cont); |
2453 } | 2485 } |
2454 FlagsContinuation cont; | 2486 FlagsContinuation cont; |
2455 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, &cont); | 2487 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, &cont); |
2456 } | 2488 } |
2457 | 2489 |
| 2490 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) { |
| 2491 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
| 2492 // ARM64 doesn't set the overflow flag for multiplication, so we need to |
| 2493 // test on kNotEqual. Here is the code sequence used: |
| 2494 // smull result, left, right |
| 2495 // cmp result.X(), Operand(result, SXTW) |
| 2496 FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf); |
| 2497 return EmitInt32MulWithOverflow(this, node, &cont); |
| 2498 } |
| 2499 FlagsContinuation cont; |
| 2500 EmitInt32MulWithOverflow(this, node, &cont); |
| 2501 } |
2458 | 2502 |
2459 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { | 2503 void InstructionSelector::VisitInt64AddWithOverflow(Node* node) { |
2460 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { | 2504 if (Node* ovf = NodeProperties::FindProjection(node, 1)) { |
2461 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); | 2505 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf); |
2462 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, | 2506 return VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, |
2463 &cont); | 2507 &cont); |
2464 } | 2508 } |
2465 FlagsContinuation cont; | 2509 FlagsContinuation cont; |
2466 VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, &cont); | 2510 VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm, &cont); |
2467 } | 2511 } |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2678 // static | 2722 // static |
2679 MachineOperatorBuilder::AlignmentRequirements | 2723 MachineOperatorBuilder::AlignmentRequirements |
2680 InstructionSelector::AlignmentRequirements() { | 2724 InstructionSelector::AlignmentRequirements() { |
2681 return MachineOperatorBuilder::AlignmentRequirements:: | 2725 return MachineOperatorBuilder::AlignmentRequirements:: |
2682 FullUnalignedAccessSupport(); | 2726 FullUnalignedAccessSupport(); |
2683 } | 2727 } |
2684 | 2728 |
2685 } // namespace compiler | 2729 } // namespace compiler |
2686 } // namespace internal | 2730 } // namespace internal |
2687 } // namespace v8 | 2731 } // namespace v8 |
OLD | NEW |