Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: src/compiler/arm64/instruction-selector-arm64.cc

Issue 2101123005: [turbofan] Introduce integer multiplication with overflow. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/arm64/instruction-codes-arm64.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/arm64/instruction-codes-arm64.h ('k') | src/compiler/code-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698