OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 1267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1278 return ValueEffectControl(value, effect, control); | 1278 return ValueEffectControl(value, effect, control); |
1279 } | 1279 } |
1280 | 1280 |
1281 EffectControlLinearizer::ValueEffectControl | 1281 EffectControlLinearizer::ValueEffectControl |
1282 EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state, | 1282 EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state, |
1283 Node* effect, Node* control) { | 1283 Node* effect, Node* control) { |
1284 Node* zero = jsgraph()->Int32Constant(0); | 1284 Node* zero = jsgraph()->Int32Constant(0); |
1285 Node* minusone = jsgraph()->Int32Constant(-1); | 1285 Node* minusone = jsgraph()->Int32Constant(-1); |
1286 Node* minint = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::min()); | 1286 Node* minint = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::min()); |
1287 | 1287 |
| 1288 // General case for signed integer modulus, with optimization for (unknown) |
| 1289 // power of 2 right hand side. |
| 1290 // |
| 1291 // if 0 < rhs then |
| 1292 // msk = rhs - 1 |
| 1293 // if rhs & msk == 0 then |
| 1294 // if lhs < 0 then |
| 1295 // -(-lhs & msk) |
| 1296 // else |
| 1297 // lhs & msk |
| 1298 // else |
| 1299 // lhs % rhs |
| 1300 // else |
| 1301 // if rhs < -1 then |
| 1302 // lhs % rhs |
| 1303 // else |
| 1304 // deopt if rhs == 0 |
| 1305 // deopt if lhs == minint |
| 1306 // zero |
| 1307 // |
1288 Node* lhs = node->InputAt(0); | 1308 Node* lhs = node->InputAt(0); |
1289 Node* rhs = node->InputAt(1); | 1309 Node* rhs = node->InputAt(1); |
1290 | 1310 |
1291 // Ensure that {rhs} is not zero, otherwise we'd have to return NaN. | 1311 // Check if {rhs} is strictly positive. |
1292 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero); | 1312 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs); |
1293 control = effect = graph()->NewNode( | |
1294 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check, | |
1295 frame_state, effect, control); | |
1296 | |
1297 // Check if {lhs} is positive or zero. | |
1298 Node* check0 = graph()->NewNode(machine()->Int32LessThanOrEqual(), zero, lhs); | |
1299 Node* branch0 = | 1313 Node* branch0 = |
1300 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | 1314 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); |
1301 | 1315 |
1302 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 1316 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
1303 Node* etrue0 = effect; | 1317 Node* etrue0 = effect; |
1304 Node* vtrue0; | 1318 Node* vtrue0; |
1305 { | 1319 { |
1306 // Fast case, no additional checking required. | 1320 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minusone); |
1307 vtrue0 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true0); | 1321 |
| 1322 // Check if {rhs} minus one is a valid mask. |
| 1323 Node* check1 = graph()->NewNode( |
| 1324 machine()->Word32Equal(), |
| 1325 graph()->NewNode(machine()->Word32And(), rhs, msk), zero); |
| 1326 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); |
| 1327 |
| 1328 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 1329 Node* vtrue1; |
| 1330 { |
| 1331 // Check if {lhs} is negative. |
| 1332 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero); |
| 1333 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| 1334 check2, if_true1); |
| 1335 |
| 1336 // Compute the remainder as {-(-lhs & msk)}. |
| 1337 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 1338 Node* vtrue2 = graph()->NewNode( |
| 1339 machine()->Int32Sub(), zero, |
| 1340 graph()->NewNode(machine()->Word32And(), |
| 1341 graph()->NewNode(machine()->Int32Sub(), zero, lhs), |
| 1342 msk)); |
| 1343 |
| 1344 // Compute the remainder as {lhs & msk}. |
| 1345 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 1346 Node* vfalse2 = graph()->NewNode(machine()->Word32And(), lhs, msk); |
| 1347 |
| 1348 if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 1349 vtrue1 = |
| 1350 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 1351 vtrue2, vfalse2, if_true1); |
| 1352 } |
| 1353 |
| 1354 // Compute the remainder using the generic {lhs % rhs}. |
| 1355 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 1356 Node* vfalse1 = |
| 1357 graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false1); |
| 1358 |
| 1359 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 1360 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 1361 vtrue1, vfalse1, if_true0); |
1308 } | 1362 } |
1309 | 1363 |
1310 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | 1364 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); |
1311 Node* efalse0 = effect; | 1365 Node* efalse0 = effect; |
1312 Node* vfalse0; | 1366 Node* vfalse0; |
1313 { | 1367 { |
1314 // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have | 1368 // Check if {rhs} is strictly less than -1. |
1315 // to return -0. | 1369 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minusone); |
1316 Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); | 1370 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
1317 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
1318 check1, if_false0); | 1371 check1, if_false0); |
1319 | 1372 |
| 1373 // Compute the remainder using the generic {lhs % rhs}. |
1320 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | 1374 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
1321 Node* etrue1 = efalse0; | 1375 Node* etrue1 = efalse0; |
1322 { | 1376 Node* vtrue1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1); |
1323 // Check if {rhs} is -1. | |
1324 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, minusone); | |
1325 if_true1 = etrue1 = | |
1326 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), | |
1327 check, frame_state, etrue1, if_true1); | |
1328 } | |
1329 | 1377 |
1330 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | 1378 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
1331 Node* efalse1 = efalse0; | 1379 Node* efalse1 = efalse0; |
| 1380 Node* vfalse1; |
| 1381 { |
| 1382 // Ensure that {rhs} is not zero. |
| 1383 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero); |
| 1384 if_false1 = efalse1 = graph()->NewNode( |
| 1385 common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check2, |
| 1386 frame_state, efalse1, if_false1); |
| 1387 |
| 1388 // Now we know that {rhs} is -1, so make sure {lhs} is not kMinInt, as |
| 1389 // we would otherwise have to return -0. |
| 1390 Node* check3 = graph()->NewNode(machine()->Word32Equal(), lhs, minint); |
| 1391 if_false1 = efalse1 = |
| 1392 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), |
| 1393 check3, frame_state, efalse1, if_false1); |
| 1394 |
| 1395 // The remainder is zero. |
| 1396 vfalse1 = zero; |
| 1397 } |
1332 | 1398 |
1333 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | 1399 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
1334 efalse0 = | 1400 efalse0 = |
1335 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); | 1401 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0); |
1336 | 1402 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
1337 // Perform the actual integer modulos. | 1403 vtrue1, vfalse1, if_false0); |
1338 vfalse0 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false0); | |
1339 | |
1340 // Check if the result is zero, because in that case we'd have to return | |
1341 // -0 here since we always take the signe of the {lhs} which is negative. | |
1342 Node* check = graph()->NewNode(machine()->Word32Equal(), vfalse0, zero); | |
1343 if_false0 = efalse0 = | |
1344 graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero), | |
1345 check, frame_state, efalse0, if_false0); | |
1346 } | 1404 } |
1347 | 1405 |
1348 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 1406 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
1349 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | 1407 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
1350 Node* value = | 1408 Node* value = |
1351 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0, | 1409 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0, |
1352 vfalse0, control); | 1410 vfalse0, control); |
1353 | 1411 |
1354 return ValueEffectControl(value, effect, control); | 1412 return ValueEffectControl(value, effect, control); |
1355 } | 1413 } |
(...skipping 1221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2577 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 2635 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
2578 Operator::kNoThrow); | 2636 Operator::kNoThrow); |
2579 to_number_operator_.set(common()->Call(desc)); | 2637 to_number_operator_.set(common()->Call(desc)); |
2580 } | 2638 } |
2581 return to_number_operator_.get(); | 2639 return to_number_operator_.get(); |
2582 } | 2640 } |
2583 | 2641 |
2584 } // namespace compiler | 2642 } // namespace compiler |
2585 } // namespace internal | 2643 } // namespace internal |
2586 } // namespace v8 | 2644 } // namespace v8 |
OLD | NEW |