OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved.7 | 1 // Copyright 2012 the V8 project authors. All rights reserved.7 |
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 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1053 UNREACHABLE(); | 1053 UNREACHABLE(); |
1054 } | 1054 } |
1055 } | 1055 } |
1056 | 1056 |
1057 | 1057 |
1058 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1058 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
1059 GenerateOsrPrologue(); | 1059 GenerateOsrPrologue(); |
1060 } | 1060 } |
1061 | 1061 |
1062 | 1062 |
| 1063 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { |
| 1064 Register dividend = ToRegister(instr->dividend()); |
| 1065 int32_t divisor = instr->divisor(); |
| 1066 ASSERT(dividend.is(ToRegister(instr->result()))); |
| 1067 |
| 1068 // Theoretically, a variation of the branch-free code for integer division by |
| 1069 // a power of 2 (calculating the remainder via an additional multiplication |
| 1070 // (which gets simplified to an 'and') and subtraction) should be faster, and |
| 1071 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to |
| 1072 // indicate that positive dividends are heavily favored, so the branching |
| 1073 // version performs better. |
| 1074 HMod* hmod = instr->hydrogen(); |
| 1075 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1076 Label dividend_is_not_negative, done; |
| 1077 |
| 1078 if (hmod->left()->CanBeNegative()) { |
| 1079 __ Branch(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); |
| 1080 // Note: The code below even works when right contains kMinInt. |
| 1081 __ subu(dividend, zero_reg, dividend); |
| 1082 __ And(dividend, dividend, Operand(mask)); |
| 1083 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1084 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); |
| 1085 } |
| 1086 __ Branch(USE_DELAY_SLOT, &done); |
| 1087 __ subu(dividend, zero_reg, dividend); |
| 1088 } |
| 1089 |
| 1090 __ bind(÷nd_is_not_negative); |
| 1091 __ And(dividend, dividend, Operand(mask)); |
| 1092 __ bind(&done); |
| 1093 } |
| 1094 |
| 1095 |
1063 void LCodeGen::DoModI(LModI* instr) { | 1096 void LCodeGen::DoModI(LModI* instr) { |
1064 HMod* hmod = instr->hydrogen(); | 1097 HMod* hmod = instr->hydrogen(); |
1065 HValue* left = hmod->left(); | 1098 HValue* left = hmod->left(); |
1066 HValue* right = hmod->right(); | 1099 HValue* right = hmod->right(); |
1067 if (hmod->RightIsPowerOf2()) { | 1100 const Register left_reg = ToRegister(instr->left()); |
1068 const Register left_reg = ToRegister(instr->left()); | 1101 const Register right_reg = ToRegister(instr->right()); |
1069 const Register result_reg = ToRegister(instr->result()); | 1102 const Register result_reg = ToRegister(instr->result()); |
1070 | 1103 |
1071 // Note: The code below even works when right contains kMinInt. | 1104 // div runs in the background while we check for special cases. |
1072 int32_t divisor = Abs(right->GetInteger32Constant()); | 1105 __ div(left_reg, right_reg); |
1073 | 1106 |
1074 Label left_is_not_negative, done; | 1107 Label done; |
1075 if (left->CanBeNegative()) { | 1108 // Check for x % 0, we have to deopt in this case because we can't return a |
1076 __ Branch(left_reg.is(result_reg) ? PROTECT : USE_DELAY_SLOT, | 1109 // NaN. |
1077 &left_is_not_negative, ge, left_reg, Operand(zero_reg)); | 1110 if (right->CanBeZero()) { |
1078 __ subu(result_reg, zero_reg, left_reg); | 1111 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); |
1079 __ And(result_reg, result_reg, divisor - 1); | 1112 } |
1080 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1081 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); | |
1082 } | |
1083 __ Branch(USE_DELAY_SLOT, &done); | |
1084 __ subu(result_reg, zero_reg, result_reg); | |
1085 } | |
1086 | 1113 |
1087 __ bind(&left_is_not_negative); | 1114 // Check for kMinInt % -1, we have to deopt if we care about -0, because we |
1088 __ And(result_reg, left_reg, divisor - 1); | 1115 // can't return that. |
1089 __ bind(&done); | 1116 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { |
1090 } else { | 1117 Label left_not_min_int; |
1091 const Register scratch = scratch0(); | 1118 __ Branch(&left_not_min_int, ne, left_reg, Operand(kMinInt)); |
1092 const Register left_reg = ToRegister(instr->left()); | 1119 // TODO(svenpanne) Don't deopt when we don't care about -0. |
1093 const Register result_reg = ToRegister(instr->result()); | 1120 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1)); |
| 1121 __ bind(&left_not_min_int); |
| 1122 } |
1094 | 1123 |
1095 // div runs in the background while we check for special cases. | 1124 // TODO(svenpanne) Only emit the test/deopt if we have to. |
1096 Register right_reg = EmitLoadRegister(instr->right(), scratch); | 1125 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); |
1097 __ div(left_reg, right_reg); | 1126 __ mfhi(result_reg); |
1098 | 1127 |
1099 Label done; | 1128 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1100 // Check for x % 0, we have to deopt in this case because we can't return a | 1129 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); |
1101 // NaN. | |
1102 if (right->CanBeZero()) { | |
1103 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); | |
1104 } | |
1105 | |
1106 // Check for kMinInt % -1, we have to deopt if we care about -0, because we | |
1107 // can't return that. | |
1108 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { | |
1109 Label left_not_min_int; | |
1110 __ Branch(&left_not_min_int, ne, left_reg, Operand(kMinInt)); | |
1111 // TODO(svenpanne) Don't deopt when we don't care about -0. | |
1112 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1)); | |
1113 __ bind(&left_not_min_int); | |
1114 } | |
1115 | |
1116 // TODO(svenpanne) Only emit the test/deopt if we have to. | |
1117 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); | |
1118 __ mfhi(result_reg); | |
1119 | |
1120 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1121 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); | |
1122 } | |
1123 __ bind(&done); | |
1124 } | 1130 } |
| 1131 __ bind(&done); |
1125 } | 1132 } |
1126 | 1133 |
1127 | 1134 |
1128 void LCodeGen::EmitSignedIntegerDivisionByConstant( | 1135 void LCodeGen::EmitSignedIntegerDivisionByConstant( |
1129 Register result, | 1136 Register result, |
1130 Register dividend, | 1137 Register dividend, |
1131 int32_t divisor, | 1138 int32_t divisor, |
1132 Register remainder, | 1139 Register remainder, |
1133 Register scratch, | 1140 Register scratch, |
1134 LEnvironment* environment) { | 1141 LEnvironment* environment) { |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1277 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); |
1271 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1278 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
1272 | 1279 |
1273 // This is computed in-place. | 1280 // This is computed in-place. |
1274 ASSERT(addend.is(ToDoubleRegister(instr->result()))); | 1281 ASSERT(addend.is(ToDoubleRegister(instr->result()))); |
1275 | 1282 |
1276 __ madd_d(addend, addend, multiplier, multiplicand); | 1283 __ madd_d(addend, addend, multiplier, multiplicand); |
1277 } | 1284 } |
1278 | 1285 |
1279 | 1286 |
| 1287 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
| 1288 Register left = ToRegister(instr->dividend()); |
| 1289 Register remainder = ToRegister(instr->temp()); |
| 1290 Register scratch = scratch0(); |
| 1291 Register result = ToRegister(instr->result()); |
| 1292 |
| 1293 ASSERT(instr->divisor()->IsConstantOperand()); |
| 1294 Label done; |
| 1295 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->divisor())); |
| 1296 if (divisor < 0) { |
| 1297 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); |
| 1298 } |
| 1299 EmitSignedIntegerDivisionByConstant(result, |
| 1300 left, |
| 1301 divisor, |
| 1302 remainder, |
| 1303 scratch, |
| 1304 instr->environment()); |
| 1305 // We performed a truncating division. Correct the result if necessary. |
| 1306 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
| 1307 __ Xor(scratch , remainder, Operand(divisor)); |
| 1308 __ Branch(&done, ge, scratch, Operand(zero_reg)); |
| 1309 __ Subu(result, result, Operand(1)); |
| 1310 __ bind(&done); |
| 1311 } |
| 1312 |
| 1313 |
1280 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 1314 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
1281 const Register result = ToRegister(instr->result()); | 1315 const Register result = ToRegister(instr->result()); |
1282 const Register left = ToRegister(instr->left()); | 1316 const Register left = ToRegister(instr->left()); |
1283 const Register remainder = ToRegister(instr->temp()); | 1317 const Register remainder = ToRegister(instr->temp()); |
1284 const Register scratch = scratch0(); | 1318 const Register scratch = scratch0(); |
1285 | 1319 |
1286 if (instr->right()->IsConstantOperand()) { | 1320 Label done; |
1287 Label done; | 1321 const Register right = ToRegister(instr->right()); |
1288 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); | |
1289 if (divisor < 0) { | |
1290 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | |
1291 } | |
1292 EmitSignedIntegerDivisionByConstant(result, | |
1293 left, | |
1294 divisor, | |
1295 remainder, | |
1296 scratch, | |
1297 instr->environment()); | |
1298 // We performed a truncating division. Correct the result if necessary. | |
1299 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); | |
1300 __ Xor(scratch , remainder, Operand(divisor)); | |
1301 __ Branch(&done, ge, scratch, Operand(zero_reg)); | |
1302 __ Subu(result, result, Operand(1)); | |
1303 __ bind(&done); | |
1304 } else { | |
1305 Label done; | |
1306 const Register right = ToRegister(instr->right()); | |
1307 | 1322 |
1308 // On MIPS div is asynchronous - it will run in the background while we | 1323 // On MIPS div is asynchronous - it will run in the background while we |
1309 // check for special cases. | 1324 // check for special cases. |
1310 __ div(left, right); | 1325 __ div(left, right); |
1311 | 1326 |
1312 // Check for x / 0. | 1327 // Check for x / 0. |
1313 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); | 1328 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); |
1314 | 1329 |
1315 // Check for (0 / -x) that will produce negative zero. | 1330 // Check for (0 / -x) that will produce negative zero. |
1316 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1331 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1317 Label left_not_zero; | 1332 Label left_not_zero; |
1318 __ Branch(&left_not_zero, ne, left, Operand(zero_reg)); | 1333 __ Branch(&left_not_zero, ne, left, Operand(zero_reg)); |
1319 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg)); | 1334 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg)); |
1320 __ bind(&left_not_zero); | 1335 __ bind(&left_not_zero); |
1321 } | 1336 } |
1322 | 1337 |
1323 // Check for (kMinInt / -1). | 1338 // Check for (kMinInt / -1). |
1324 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1339 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1325 Label left_not_min_int; | 1340 Label left_not_min_int; |
1326 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); | 1341 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); |
1327 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); | 1342 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); |
1328 __ bind(&left_not_min_int); | 1343 __ bind(&left_not_min_int); |
1329 } | 1344 } |
1330 | 1345 |
1331 __ mfhi(remainder); | 1346 __ mfhi(remainder); |
1332 __ mflo(result); | 1347 __ mflo(result); |
1333 | 1348 |
1334 // We performed a truncating division. Correct the result if necessary. | 1349 // We performed a truncating division. Correct the result if necessary. |
1335 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); | 1350 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
1336 __ Xor(scratch , remainder, Operand(right)); | 1351 __ Xor(scratch , remainder, Operand(right)); |
1337 __ Branch(&done, ge, scratch, Operand(zero_reg)); | 1352 __ Branch(&done, ge, scratch, Operand(zero_reg)); |
1338 __ Subu(result, result, Operand(1)); | 1353 __ Subu(result, result, Operand(1)); |
1339 __ bind(&done); | 1354 __ bind(&done); |
1340 } | |
1341 } | 1355 } |
1342 | 1356 |
1343 | 1357 |
1344 void LCodeGen::DoMulI(LMulI* instr) { | 1358 void LCodeGen::DoMulI(LMulI* instr) { |
1345 Register scratch = scratch0(); | 1359 Register scratch = scratch0(); |
1346 Register result = ToRegister(instr->result()); | 1360 Register result = ToRegister(instr->result()); |
1347 // Note that result may alias left. | 1361 // Note that result may alias left. |
1348 Register left = ToRegister(instr->left()); | 1362 Register left = ToRegister(instr->left()); |
1349 LOperand* right_op = instr->right(); | 1363 LOperand* right_op = instr->right(); |
1350 | 1364 |
(...skipping 4401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5752 __ Subu(scratch, result, scratch); | 5766 __ Subu(scratch, result, scratch); |
5753 __ lw(result, FieldMemOperand(scratch, | 5767 __ lw(result, FieldMemOperand(scratch, |
5754 FixedArray::kHeaderSize - kPointerSize)); | 5768 FixedArray::kHeaderSize - kPointerSize)); |
5755 __ bind(&done); | 5769 __ bind(&done); |
5756 } | 5770 } |
5757 | 5771 |
5758 | 5772 |
5759 #undef __ | 5773 #undef __ |
5760 | 5774 |
5761 } } // namespace v8::internal | 5775 } } // namespace v8::internal |
OLD | NEW |