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

Side by Side Diff: src/arm/lithium-arm.cc

Issue 23703014: Orthogonalize Lithium binary op instructions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 } 703 }
704 704
705 705
706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { 706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
707 return AssignEnvironment(new(zone()) LDeoptimize); 707 return AssignEnvironment(new(zone()) LDeoptimize);
708 } 708 }
709 709
710 710
711 LInstruction* LChunkBuilder::DoShift(Token::Value op, 711 LInstruction* LChunkBuilder::DoShift(Token::Value op,
712 HBitwiseBinaryOperation* instr) { 712 HBitwiseBinaryOperation* instr) {
713 if (instr->representation().IsTagged()) { 713 if (instr->representation().IsSmiOrInteger32()) {
714 ASSERT(instr->left()->representation().IsTagged()); 714 ASSERT(instr->left()->representation().Equals(instr->representation()));
715 ASSERT(instr->right()->representation().IsTagged()); 715 ASSERT(instr->right()->representation().Equals(instr->representation()));
716 LOperand* left = UseRegisterAtStart(instr->left());
716 717
717 LOperand* left = UseFixed(instr->left(), r1); 718 HValue* right_value = instr->right();
718 LOperand* right = UseFixed(instr->right(), r0); 719 LOperand* right = NULL;
719 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); 720 int constant_value = 0;
720 return MarkAsCall(DefineFixed(result, r0), instr); 721 bool does_deopt = false;
722 if (right_value->IsConstant()) {
723 HConstant* constant = HConstant::cast(right_value);
724 right = chunk_->DefineConstantOperand(constant);
725 constant_value = constant->Integer32Value() & 0x1f;
726 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
727 // truncated to smi.
728 if (instr->representation().IsSmi() && constant_value > 0) {
729 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
730 }
731 } else {
732 right = UseRegisterAtStart(right_value);
733 }
734
735 // Shift operations can only deoptimize if we do a logical shift
736 // by 0 and the result cannot be truncated to int32.
737 if (op == Token::SHR && constant_value == 0) {
738 if (FLAG_opt_safe_uint32_operations) {
739 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
740 } else {
741 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
742 }
743 }
744
745 LInstruction* result =
746 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
747 return does_deopt ? AssignEnvironment(result) : result;
748 } else {
749 return DoArithmeticT(op, instr);
721 } 750 }
722
723 ASSERT(instr->representation().IsSmiOrInteger32());
724 ASSERT(instr->left()->representation().Equals(instr->representation()));
725 ASSERT(instr->right()->representation().Equals(instr->representation()));
726 LOperand* left = UseRegisterAtStart(instr->left());
727
728 HValue* right_value = instr->right();
729 LOperand* right = NULL;
730 int constant_value = 0;
731 bool does_deopt = false;
732 if (right_value->IsConstant()) {
733 HConstant* constant = HConstant::cast(right_value);
734 right = chunk_->DefineConstantOperand(constant);
735 constant_value = constant->Integer32Value() & 0x1f;
736 // Left shifts can deoptimize if we shift by > 0 and the result cannot be
737 // truncated to smi.
738 if (instr->representation().IsSmi() && constant_value > 0) {
739 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi);
740 }
741 } else {
742 right = UseRegisterAtStart(right_value);
743 }
744
745 // Shift operations can only deoptimize if we do a logical shift
746 // by 0 and the result cannot be truncated to int32.
747 if (op == Token::SHR && constant_value == 0) {
748 if (FLAG_opt_safe_uint32_operations) {
749 does_deopt = !instr->CheckFlag(HInstruction::kUint32);
750 } else {
751 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
752 }
753 }
754
755 LInstruction* result =
756 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
757 return does_deopt ? AssignEnvironment(result) : result;
758 } 751 }
759 752
760 753
761 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, 754 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
762 HArithmeticBinaryOperation* instr) { 755 HArithmeticBinaryOperation* instr) {
763 ASSERT(instr->representation().IsDouble()); 756 ASSERT(instr->representation().IsDouble());
764 ASSERT(instr->left()->representation().IsDouble()); 757 ASSERT(instr->left()->representation().IsDouble());
765 ASSERT(instr->right()->representation().IsDouble()); 758 ASSERT(instr->right()->representation().IsDouble());
766 ASSERT(op != Token::MOD); 759 LOperand* left = (op == Token::MOD)
Sven Panne 2013/09/16 13:10:32 Refactor this into if (op == Token::MOD) { ... }
767 LOperand* left = UseRegisterAtStart(instr->left()); 760 ? UseFixedDouble(instr->left(), d1)
768 LOperand* right = UseRegisterAtStart(instr->right()); 761 : UseRegisterAtStart(instr->left());
762 LOperand* right = (op == Token::MOD)
763 ? UseFixedDouble(instr->right(), d2)
764 : UseRegisterAtStart(instr->right());
769 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); 765 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
766
767 // We call a C function for double modulo. It can't trigger a GC. We need
768 // to use fixed result register for the call.
769 // TODO(fschneider): Allow any register as input registers.
770 if (op == Token::MOD) return MarkAsCall(DefineFixedDouble(result, d1), instr);
770 return DefineAsRegister(result); 771 return DefineAsRegister(result);
771 } 772 }
772 773
773 774
774 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, 775 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
775 HArithmeticBinaryOperation* instr) { 776 HBinaryOperation* instr) {
776 ASSERT(op == Token::ADD ||
777 op == Token::DIV ||
778 op == Token::MOD ||
779 op == Token::MUL ||
780 op == Token::SUB);
781 HValue* left = instr->left(); 777 HValue* left = instr->left();
782 HValue* right = instr->right(); 778 HValue* right = instr->right();
783 ASSERT(left->representation().IsTagged()); 779 ASSERT(left->representation().IsTagged());
784 ASSERT(right->representation().IsTagged()); 780 ASSERT(right->representation().IsTagged());
785 LOperand* left_operand = UseFixed(left, r1); 781 LOperand* left_operand = UseFixed(left, r1);
786 LOperand* right_operand = UseFixed(right, r0); 782 LOperand* right_operand = UseFixed(right, r0);
787 LArithmeticT* result = 783 LArithmeticT* result =
788 new(zone()) LArithmeticT(op, left_operand, right_operand); 784 new(zone()) LArithmeticT(op, left_operand, right_operand);
789 return MarkAsCall(DefineFixed(result, r0), instr); 785 return MarkAsCall(DefineFixed(result, r0), instr);
790 } 786 }
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 1336
1341 LInstruction* LChunkBuilder::DoShl(HShl* instr) { 1337 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
1342 return DoShift(Token::SHL, instr); 1338 return DoShift(Token::SHL, instr);
1343 } 1339 }
1344 1340
1345 1341
1346 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { 1342 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
1347 if (instr->representation().IsSmiOrInteger32()) { 1343 if (instr->representation().IsSmiOrInteger32()) {
1348 ASSERT(instr->left()->representation().Equals(instr->representation())); 1344 ASSERT(instr->left()->representation().Equals(instr->representation()));
1349 ASSERT(instr->right()->representation().Equals(instr->representation())); 1345 ASSERT(instr->right()->representation().Equals(instr->representation()));
1346 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32));
1350 1347
1351 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1348 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1352 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 1349 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1353 return DefineAsRegister(new(zone()) LBitI(left, right)); 1350 return DefineAsRegister(new(zone()) LBitI(left, right));
1354 } else { 1351 } else {
1355 ASSERT(instr->representation().IsTagged()); 1352 return DoArithmeticT(instr->op(), instr);
1356 ASSERT(instr->left()->representation().IsTagged());
1357 ASSERT(instr->right()->representation().IsTagged());
1358
1359 LOperand* left = UseFixed(instr->left(), r1);
1360 LOperand* right = UseFixed(instr->right(), r0);
1361 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right);
1362 return MarkAsCall(DefineFixed(result, r0), instr);
1363 } 1353 }
1364 } 1354 }
1365 1355
1366 1356
1367 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1357 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1368 if (instr->representation().IsDouble()) { 1358 if (instr->representation().IsSmiOrInteger32()) {
1369 return DoArithmeticD(Token::DIV, instr);
1370 } else if (instr->representation().IsSmiOrInteger32()) {
1371 ASSERT(instr->left()->representation().Equals(instr->representation())); 1359 ASSERT(instr->left()->representation().Equals(instr->representation()));
1372 ASSERT(instr->right()->representation().Equals(instr->representation())); 1360 ASSERT(instr->right()->representation().Equals(instr->representation()));
1373 if (instr->HasPowerOf2Divisor()) { 1361 if (instr->HasPowerOf2Divisor()) {
1374 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); 1362 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1375 LOperand* value = UseRegisterAtStart(instr->left()); 1363 LOperand* value = UseRegisterAtStart(instr->left());
1376 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); 1364 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL);
1377 return AssignEnvironment(DefineAsRegister(div)); 1365 return AssignEnvironment(DefineAsRegister(div));
1378 } 1366 }
1379 LOperand* dividend = UseRegister(instr->left()); 1367 LOperand* dividend = UseRegister(instr->left());
1380 LOperand* divisor = UseRegister(instr->right()); 1368 LOperand* divisor = UseRegister(instr->right());
1381 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); 1369 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
1382 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); 1370 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1383 return AssignEnvironment(DefineAsRegister(div)); 1371 return AssignEnvironment(DefineAsRegister(div));
1372 } else if (instr->representation().IsDouble()) {
1373 return DoArithmeticD(Token::DIV, instr);
1384 } else { 1374 } else {
1385 return DoArithmeticT(Token::DIV, instr); 1375 return DoArithmeticT(Token::DIV, instr);
1386 } 1376 }
1387 } 1377 }
1388 1378
1389 1379
1390 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { 1380 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
1391 uint32_t divisor_abs = abs(divisor); 1381 uint32_t divisor_abs = abs(divisor);
1392 // Dividing by 0, 1, and powers of 2 is easy. 1382 // Dividing by 0, 1, and powers of 2 is easy.
1393 // Note that IsPowerOf2(0) returns true; 1383 // Note that IsPowerOf2(0) returns true;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1494 FixedTemp(d10), 1484 FixedTemp(d10),
1495 FixedTemp(d11)); 1485 FixedTemp(d11));
1496 LInstruction* result = DefineAsRegister(mod); 1486 LInstruction* result = DefineAsRegister(mod);
1497 return (right->CanBeZero() || 1487 return (right->CanBeZero() ||
1498 (left->CanBeNegative() && 1488 (left->CanBeNegative() &&
1499 instr->CanBeZero() && 1489 instr->CanBeZero() &&
1500 instr->CheckFlag(HValue::kBailoutOnMinusZero))) 1490 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1501 ? AssignEnvironment(result) 1491 ? AssignEnvironment(result)
1502 : result; 1492 : result;
1503 } 1493 }
1504 } else if (instr->representation().IsTagged()) { 1494 } else if (instr->representation().IsDouble()) {
1495 return DoArithmeticD(Token::MOD, instr);
1496 } else {
1505 return DoArithmeticT(Token::MOD, instr); 1497 return DoArithmeticT(Token::MOD, instr);
1506 } else {
1507 ASSERT(instr->representation().IsDouble());
1508 // We call a C function for double modulo. It can't trigger a GC. We need
1509 // to use fixed result register for the call.
1510 // TODO(fschneider): Allow any register as input registers.
1511 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
1512 UseFixedDouble(left, d1),
1513 UseFixedDouble(right, d2));
1514 return MarkAsCall(DefineFixedDouble(mod, d1), instr);
1515 } 1498 }
1516 } 1499 }
1517 1500
1518 1501
1519 LInstruction* LChunkBuilder::DoMul(HMul* instr) { 1502 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1520 if (instr->representation().IsSmiOrInteger32()) { 1503 if (instr->representation().IsSmiOrInteger32()) {
1521 ASSERT(instr->left()->representation().Equals(instr->representation())); 1504 ASSERT(instr->left()->representation().Equals(instr->representation()));
1522 ASSERT(instr->right()->representation().Equals(instr->representation())); 1505 ASSERT(instr->right()->representation().Equals(instr->representation()));
1523 HValue* left = instr->BetterLeftOperand(); 1506 HValue* left = instr->BetterLeftOperand();
1524 HValue* right = instr->BetterRightOperand(); 1507 HValue* right = instr->BetterRightOperand();
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1671 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); 1654 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
1672 } 1655 }
1673 1656
1674 if (instr->right()->IsMul()) { 1657 if (instr->right()->IsMul()) {
1675 ASSERT(!instr->left()->IsMul()); 1658 ASSERT(!instr->left()->IsMul());
1676 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); 1659 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left());
1677 } 1660 }
1678 1661
1679 return DoArithmeticD(Token::ADD, instr); 1662 return DoArithmeticD(Token::ADD, instr);
1680 } else { 1663 } else {
1681 ASSERT(instr->representation().IsTagged());
1682 return DoArithmeticT(Token::ADD, instr); 1664 return DoArithmeticT(Token::ADD, instr);
1683 } 1665 }
1684 } 1666 }
1685 1667
1686 1668
1687 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { 1669 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
1688 LOperand* left = NULL; 1670 LOperand* left = NULL;
1689 LOperand* right = NULL; 1671 LOperand* right = NULL;
1690 if (instr->representation().IsSmiOrInteger32()) { 1672 if (instr->representation().IsSmiOrInteger32()) {
1691 ASSERT(instr->left()->representation().Equals(instr->representation())); 1673 ASSERT(instr->left()->representation().Equals(instr->representation()));
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after
2621 2603
2622 2604
2623 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { 2605 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2624 LOperand* object = UseRegister(instr->object()); 2606 LOperand* object = UseRegister(instr->object());
2625 LOperand* index = UseRegister(instr->index()); 2607 LOperand* index = UseRegister(instr->index());
2626 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); 2608 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2627 } 2609 }
2628 2610
2629 2611
2630 } } // namespace v8::internal 2612 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-arm.h ('k') | src/arm/lithium-codegen-arm.cc » ('j') | src/ia32/lithium-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698