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

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 727673002: [turbofan] Optimize remainder of integer division by unknown power of two. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix broken Int32Mod on ARM Created 6 years, 1 month 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/machine-operator.h ('k') | test/mjsunit/asm/int32mod.js » ('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/simplified-lowering.h" 5 #include "src/compiler/simplified-lowering.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 Node* div = 1318 Node* div =
1319 graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_minus_one.if_false); 1319 graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_minus_one.if_false);
1320 1320
1321 return if_zero.Phi(kMachInt32, zero, if_minus_one.Phi(kMachInt32, sub, div)); 1321 return if_zero.Phi(kMachInt32, zero, if_minus_one.Phi(kMachInt32, sub, div));
1322 } 1322 }
1323 1323
1324 1324
1325 Node* SimplifiedLowering::Int32Mod(Node* const node) { 1325 Node* SimplifiedLowering::Int32Mod(Node* const node) {
1326 Int32BinopMatcher m(node); 1326 Int32BinopMatcher m(node);
1327 Node* const zero = jsgraph()->Int32Constant(0); 1327 Node* const zero = jsgraph()->Int32Constant(0);
1328 Node* const minus_one = jsgraph()->Int32Constant(-1);
1328 Node* const lhs = m.left().node(); 1329 Node* const lhs = m.left().node();
1329 Node* const rhs = m.right().node(); 1330 Node* const rhs = m.right().node();
1330 1331
1331 if (m.right().Is(-1) || m.right().Is(0)) { 1332 if (m.right().Is(-1) || m.right().Is(0)) {
1332 return zero; 1333 return zero;
1333 } else if (machine()->Int32ModIsSafe() || m.right().HasValue()) { 1334 } else if (m.right().HasValue()) {
1334 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start()); 1335 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
1335 } 1336 }
1336 1337
1337 Diamond if_zero(graph(), common(), 1338 // General case for signed integer modulus, with optimization for (unknown)
1338 graph()->NewNode(machine()->Word32Equal(), rhs, zero), 1339 // power of 2 right hand side.
1339 BranchHint::kFalse); 1340 //
1341 // if 0 < rhs then
1342 // msk = rhs - 1
1343 // if rhs & msk != 0 then
1344 // lhs % rhs
1345 // else
1346 // if lhs < 0 then
1347 // -(-lhs & msk)
1348 // else
1349 // lhs & msk
1350 // else
1351 // if rhs < -1 then
1352 // lhs % rhs
1353 // else
1354 // zero
1355 //
1356 // Note: We do not use the Diamond helper class here, because it really hurts
1357 // readability with nested diamonds.
1358 const Operator* const merge_op = common()->Merge(2);
1359 const Operator* const phi_op = common()->Phi(kMachInt32, 2);
1340 1360
1341 Diamond if_minus_one(graph(), common(), 1361 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1342 graph()->NewNode(machine()->Word32Equal(), rhs, 1362 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1343 jsgraph()->Int32Constant(-1)), 1363 graph()->start());
1344 BranchHint::kFalse);
1345 if_minus_one.Nest(if_zero, false);
1346 Node* mod =
1347 graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_minus_one.if_false);
1348 1364
1349 return if_zero.Phi(kMachInt32, zero, if_minus_one.Phi(kMachInt32, zero, mod)); 1365 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1366 Node* true0;
1367 {
1368 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
1369
1370 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
1371 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1372
1373 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1374 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1375
1376 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1377 Node* false1;
1378 {
1379 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
1380 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1381 check2, if_false1);
1382
1383 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1384 Node* true2 = graph()->NewNode(
1385 machine()->Int32Sub(), zero,
1386 graph()->NewNode(machine()->Word32And(),
1387 graph()->NewNode(machine()->Int32Sub(), zero, lhs),
1388 msk));
1389
1390 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1391 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1392
1393 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
1394 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
1395 }
1396
1397 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
1398 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
1399 }
1400
1401 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1402 Node* false0;
1403 {
1404 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
1405 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1406 check1, if_false0);
1407
1408 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1409 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1410
1411 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1412 Node* false1 = zero;
1413
1414 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
1415 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
1416 }
1417
1418 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1419 return graph()->NewNode(phi_op, true0, false0, merge0);
1350 } 1420 }
1351 1421
1352 1422
1353 Node* SimplifiedLowering::Uint32Div(Node* const node) { 1423 Node* SimplifiedLowering::Uint32Div(Node* const node) {
1354 Uint32BinopMatcher m(node); 1424 Uint32BinopMatcher m(node);
1355 Node* const zero = jsgraph()->Uint32Constant(0); 1425 Node* const zero = jsgraph()->Uint32Constant(0);
1356 Node* const lhs = m.left().node(); 1426 Node* const lhs = m.left().node();
1357 Node* const rhs = m.right().node(); 1427 Node* const rhs = m.right().node();
1358 1428
1359 if (m.right().Is(0)) { 1429 if (m.right().Is(0)) {
1360 return zero; 1430 return zero;
1361 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) { 1431 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
1362 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start()); 1432 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
1363 } 1433 }
1364 1434
1365 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 1435 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1366 Diamond d(graph(), common(), check, BranchHint::kFalse); 1436 Diamond d(graph(), common(), check, BranchHint::kFalse);
1367 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false); 1437 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
1368 return d.Phi(kMachUint32, zero, div); 1438 return d.Phi(kMachUint32, zero, div);
1369 } 1439 }
1370 1440
1371 1441
1372 Node* SimplifiedLowering::Uint32Mod(Node* const node) { 1442 Node* SimplifiedLowering::Uint32Mod(Node* const node) {
1373 Uint32BinopMatcher m(node); 1443 Uint32BinopMatcher m(node);
1444 Node* const minus_one = jsgraph()->Int32Constant(-1);
1374 Node* const zero = jsgraph()->Uint32Constant(0); 1445 Node* const zero = jsgraph()->Uint32Constant(0);
1375 Node* const lhs = m.left().node(); 1446 Node* const lhs = m.left().node();
1376 Node* const rhs = m.right().node(); 1447 Node* const rhs = m.right().node();
1377 1448
1378 if (m.right().Is(0)) { 1449 if (m.right().Is(0)) {
1379 return zero; 1450 return zero;
1380 } else if (machine()->Uint32ModIsSafe() || m.right().HasValue()) { 1451 } else if (m.right().HasValue()) {
1381 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start()); 1452 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
1382 } 1453 }
1383 1454
1384 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); 1455 // General case for unsigned integer modulus, with optimization for (unknown)
1385 Diamond d(graph(), common(), check, BranchHint::kFalse); 1456 // power of 2 right hand side.
1386 Node* mod = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, d.if_false); 1457 //
1387 return d.Phi(kMachUint32, zero, mod); 1458 // if rhs then
1459 // msk = rhs - 1
1460 // if rhs & msk != 0 then
1461 // lhs % rhs
1462 // else
1463 // lhs & msk
1464 // else
1465 // zero
1466 //
1467 // Note: We do not use the Diamond helper class here, because it really hurts
1468 // readability with nested diamonds.
1469 const Operator* const merge_op = common()->Merge(2);
1470 const Operator* const phi_op = common()->Phi(kMachInt32, 2);
1471
1472 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
1473 graph()->start());
1474
1475 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1476 Node* true0;
1477 {
1478 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
1479
1480 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
1481 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1482
1483 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1484 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
1485
1486 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1487 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1488
1489 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
1490 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
1491 }
1492
1493 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1494 Node* false0 = zero;
1495
1496 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1497 return graph()->NewNode(phi_op, true0, false0, merge0);
1388 } 1498 }
1389 1499
1390 1500
1391 void SimplifiedLowering::DoStringEqual(Node* node) { 1501 void SimplifiedLowering::DoStringEqual(Node* node) {
1392 node->set_op(machine()->WordEqual()); 1502 node->set_op(machine()->WordEqual());
1393 node->ReplaceInput(0, StringComparison(node, false)); 1503 node->ReplaceInput(0, StringComparison(node, false));
1394 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); 1504 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
1395 } 1505 }
1396 1506
1397 1507
1398 void SimplifiedLowering::DoStringLessThan(Node* node) { 1508 void SimplifiedLowering::DoStringLessThan(Node* node) {
1399 node->set_op(machine()->IntLessThan()); 1509 node->set_op(machine()->IntLessThan());
1400 node->ReplaceInput(0, StringComparison(node, true)); 1510 node->ReplaceInput(0, StringComparison(node, true));
1401 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); 1511 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
1402 } 1512 }
1403 1513
1404 1514
1405 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { 1515 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
1406 node->set_op(machine()->IntLessThanOrEqual()); 1516 node->set_op(machine()->IntLessThanOrEqual());
1407 node->ReplaceInput(0, StringComparison(node, true)); 1517 node->ReplaceInput(0, StringComparison(node, true));
1408 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); 1518 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
1409 } 1519 }
1410 1520
1411 } // namespace compiler 1521 } // namespace compiler
1412 } // namespace internal 1522 } // namespace internal
1413 } // namespace v8 1523 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/machine-operator.h ('k') | test/mjsunit/asm/int32mod.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698