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

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

Issue 191293012: Reland "Handle non-power-of-2 divisors in division-like operations". (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 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
« no previous file with comments | « src/arm/lithium-arm.h ('k') | src/arm/lithium-codegen-arm.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 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 1239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && 1250 (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1251 instr->left()->RangeCanInclude(0) && divisor < 0) || 1251 instr->left()->RangeCanInclude(0) && divisor < 0) ||
1252 (instr->CheckFlag(HValue::kCanOverflow) && 1252 (instr->CheckFlag(HValue::kCanOverflow) &&
1253 instr->left()->RangeCanInclude(kMinInt) && divisor == -1) || 1253 instr->left()->RangeCanInclude(kMinInt) && divisor == -1) ||
1254 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1254 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1255 divisor != 1 && divisor != -1); 1255 divisor != 1 && divisor != -1);
1256 return can_deopt ? AssignEnvironment(result) : result; 1256 return can_deopt ? AssignEnvironment(result) : result;
1257 } 1257 }
1258 1258
1259 1259
1260 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
1261 ASSERT(instr->representation().IsInteger32());
1262 ASSERT(instr->left()->representation().Equals(instr->representation()));
1263 ASSERT(instr->right()->representation().Equals(instr->representation()));
1264 LOperand* dividend = UseRegister(instr->left());
1265 int32_t divisor = instr->right()->GetInteger32Constant();
1266 LInstruction* result =
1267 DefineAsRegister(new(zone()) LDivByConstI(dividend, divisor));
1268 bool can_deopt =
1269 divisor == 0 ||
1270 (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1271 instr->left()->RangeCanInclude(0) && divisor < 0) ||
1272 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
1273 return can_deopt ? AssignEnvironment(result) : result;
1274 }
1275
1276
1260 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { 1277 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
1261 ASSERT(instr->representation().IsSmiOrInteger32()); 1278 ASSERT(instr->representation().IsSmiOrInteger32());
1262 ASSERT(instr->left()->representation().Equals(instr->representation())); 1279 ASSERT(instr->left()->representation().Equals(instr->representation()));
1263 ASSERT(instr->right()->representation().Equals(instr->representation())); 1280 ASSERT(instr->right()->representation().Equals(instr->representation()));
1264 LOperand* dividend = UseRegister(instr->left()); 1281 LOperand* dividend = UseRegister(instr->left());
1265 LOperand* divisor = UseRegister(instr->right()); 1282 LOperand* divisor = UseRegister(instr->right());
1266 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); 1283 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
1267 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); 1284 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1268 return AssignEnvironment(DefineAsRegister(div)); 1285 return AssignEnvironment(DefineAsRegister(div));
1269 } 1286 }
1270 1287
1271 1288
1272 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1289 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1273 if (instr->representation().IsSmiOrInteger32()) { 1290 if (instr->representation().IsSmiOrInteger32()) {
1274 return instr->RightIsPowerOf2() ? DoDivByPowerOf2I(instr) : DoDivI(instr); 1291 if (instr->RightIsPowerOf2()) {
1292 return DoDivByPowerOf2I(instr);
1293 } else if (instr->right()->IsConstant()) {
1294 return DoDivByConstI(instr);
1295 } else {
1296 return DoDivI(instr);
1297 }
1275 } else if (instr->representation().IsDouble()) { 1298 } else if (instr->representation().IsDouble()) {
1276 return DoArithmeticD(Token::DIV, instr); 1299 return DoArithmeticD(Token::DIV, instr);
1277 } else { 1300 } else {
1278 return DoArithmeticT(Token::DIV, instr); 1301 return DoArithmeticT(Token::DIV, instr);
1279 } 1302 }
1280 } 1303 }
1281 1304
1282 1305
1283 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
1284 uint32_t divisor_abs = abs(divisor);
1285 // Dividing by 0 or powers of 2 is easy.
1286 if (divisor == 0 || IsPowerOf2(divisor_abs)) return true;
1287
1288 // We have magic numbers for a few specific divisors.
1289 // Details and proofs can be found in:
1290 // - Hacker's Delight, Henry S. Warren, Jr.
1291 // - The PowerPC Compiler Writer’s Guide
1292 // and probably many others.
1293 //
1294 // We handle
1295 // <divisor with magic numbers> * <power of 2>
1296 // but not
1297 // <divisor with magic numbers> * <other divisor with magic numbers>
1298 int32_t power_of_2_factor =
1299 CompilerIntrinsics::CountTrailingZeros(divisor_abs);
1300 DivMagicNumbers magic_numbers =
1301 DivMagicNumberFor(divisor_abs >> power_of_2_factor);
1302 return magic_numbers.M != InvalidDivMagicNumber.M;
1303 }
1304
1305
1306 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { 1306 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1307 LOperand* dividend = UseRegisterAtStart(instr->left()); 1307 LOperand* dividend = UseRegisterAtStart(instr->left());
1308 int32_t divisor = instr->right()->GetInteger32Constant(); 1308 int32_t divisor = instr->right()->GetInteger32Constant();
1309 LInstruction* result = 1309 LInstruction* result =
1310 DefineSameAsFirst( 1310 DefineSameAsFirst(
1311 new(zone()) LFlooringDivByPowerOf2I(dividend, divisor)); 1311 new(zone()) LFlooringDivByPowerOf2I(dividend, divisor));
1312 bool can_deopt = 1312 bool can_deopt =
1313 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || 1313 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1314 (instr->left()->RangeCanInclude(kMinInt) && divisor == -1); 1314 (instr->left()->RangeCanInclude(kMinInt) && divisor == -1);
1315 return can_deopt ? AssignEnvironment(result) : result; 1315 return can_deopt ? AssignEnvironment(result) : result;
1316 } 1316 }
1317 1317
1318 1318
1319 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { 1319 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1320 ASSERT(instr->representation().IsInteger32());
1321 ASSERT(instr->left()->representation().Equals(instr->representation()));
1322 ASSERT(instr->right()->representation().Equals(instr->representation()));
1320 LOperand* dividend = UseRegister(instr->left()); 1323 LOperand* dividend = UseRegister(instr->left());
1321 LOperand* divisor = CpuFeatures::IsSupported(SUDIV) 1324 int32_t divisor = instr->right()->GetInteger32Constant();
1322 ? UseRegister(instr->right())
1323 : UseOrConstant(instr->right());
1324 LOperand* remainder = TempRegister();
1325 LInstruction* result = 1325 LInstruction* result =
1326 DefineAsRegister( 1326 DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
1327 new(zone()) LFlooringDivByConstI(dividend, divisor, remainder)); 1327 bool can_deopt =
1328 return AssignEnvironment(result); 1328 divisor == 0 ||
1329 (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1330 instr->left()->RangeCanInclude(0) && divisor < 0);
1331 return can_deopt ? AssignEnvironment(result) : result;
1329 } 1332 }
1330 1333
1331 1334
1332 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { 1335 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1333 if (instr->RightIsPowerOf2()) { 1336 if (instr->RightIsPowerOf2()) {
1334 return DoFlooringDivByPowerOf2I(instr); 1337 return DoFlooringDivByPowerOf2I(instr);
1335 } else if (instr->right()->IsConstant()) { 1338 } else if (instr->right()->IsConstant()) {
1336 // LMathFloorOfDiv can currently only handle a subset of divisors, so fall 1339 return DoFlooringDivByConstI(instr);
1337 // back to a flooring division in all other cases.
1338 return (CpuFeatures::IsSupported(SUDIV) ||
1339 HasMagicNumberForDivisor(instr->right()->GetInteger32Constant()))
1340 ? DoFlooringDivByConstI(instr)
1341 : DoDivI(instr);
1342 } else { 1340 } else {
1343 return DoDivI(instr); 1341 return DoDivI(instr);
1344 } 1342 }
1345 } 1343 }
1346 1344
1347 1345
1348 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { 1346 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1349 ASSERT(instr->representation().IsSmiOrInteger32()); 1347 ASSERT(instr->representation().IsSmiOrInteger32());
1350 ASSERT(instr->left()->representation().Equals(instr->representation())); 1348 ASSERT(instr->left()->representation().Equals(instr->representation()));
1351 ASSERT(instr->right()->representation().Equals(instr->representation())); 1349 ASSERT(instr->right()->representation().Equals(instr->representation()));
1352 LOperand* dividend = UseRegisterAtStart(instr->left()); 1350 LOperand* dividend = UseRegisterAtStart(instr->left());
1353 int32_t divisor = instr->right()->GetInteger32Constant(); 1351 int32_t divisor = instr->right()->GetInteger32Constant();
1354 LInstruction* result = 1352 LInstruction* result =
1355 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor)); 1353 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
1356 bool can_deopt = 1354 bool can_deopt =
1357 instr->CheckFlag(HValue::kBailoutOnMinusZero) && 1355 instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1358 instr->left()->CanBeNegative(); 1356 instr->left()->CanBeNegative();
1359 return can_deopt ? AssignEnvironment(result) : result; 1357 return can_deopt ? AssignEnvironment(result) : result;
1360 } 1358 }
1361 1359
1362 1360
1361 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
1362 ASSERT(instr->representation().IsSmiOrInteger32());
1363 ASSERT(instr->left()->representation().Equals(instr->representation()));
1364 ASSERT(instr->right()->representation().Equals(instr->representation()));
1365 LOperand* dividend = UseRegister(instr->left());
1366 int32_t divisor = instr->right()->GetInteger32Constant();
1367 LInstruction* result =
1368 DefineAsRegister(new(zone()) LModByConstI(dividend, divisor));
1369 bool can_deopt =
1370 divisor == 0 ||
1371 (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1372 instr->left()->CanBeNegative());
1373 return can_deopt ? AssignEnvironment(result) : result;
1374 }
1375
1376
1363 LInstruction* LChunkBuilder::DoModI(HMod* instr) { 1377 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1364 ASSERT(instr->representation().IsSmiOrInteger32()); 1378 ASSERT(instr->representation().IsSmiOrInteger32());
1365 ASSERT(instr->left()->representation().Equals(instr->representation())); 1379 ASSERT(instr->left()->representation().Equals(instr->representation()));
1366 ASSERT(instr->right()->representation().Equals(instr->representation())); 1380 ASSERT(instr->right()->representation().Equals(instr->representation()));
1367 if (CpuFeatures::IsSupported(SUDIV)) { 1381 if (CpuFeatures::IsSupported(SUDIV)) {
1368 LOperand* dividend = UseRegister(instr->left()); 1382 LOperand* dividend = UseRegister(instr->left());
1369 LOperand* divisor = UseRegister(instr->right()); 1383 LOperand* divisor = UseRegister(instr->right());
1370 LInstruction* result = 1384 LInstruction* result =
1371 DefineAsRegister(new(zone()) LModI(dividend, divisor, NULL, NULL)); 1385 DefineAsRegister(new(zone()) LModI(dividend, divisor, NULL, NULL));
1372 bool can_deopt = (instr->right()->CanBeZero() || 1386 bool can_deopt = (instr->right()->CanBeZero() ||
(...skipping 15 matching lines...) Expand all
1388 (instr->left()->CanBeNegative() && 1402 (instr->left()->CanBeNegative() &&
1389 instr->CanBeZero() && 1403 instr->CanBeZero() &&
1390 instr->CheckFlag(HValue::kBailoutOnMinusZero))); 1404 instr->CheckFlag(HValue::kBailoutOnMinusZero)));
1391 return can_deopt ? AssignEnvironment(result) : result; 1405 return can_deopt ? AssignEnvironment(result) : result;
1392 } 1406 }
1393 } 1407 }
1394 1408
1395 1409
1396 LInstruction* LChunkBuilder::DoMod(HMod* instr) { 1410 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1397 if (instr->representation().IsSmiOrInteger32()) { 1411 if (instr->representation().IsSmiOrInteger32()) {
1398 return instr->RightIsPowerOf2() ? DoModByPowerOf2I(instr) : DoModI(instr); 1412 if (instr->RightIsPowerOf2()) {
1413 return DoModByPowerOf2I(instr);
1414 } else if (instr->right()->IsConstant()) {
1415 return DoModByConstI(instr);
1416 } else {
1417 return DoModI(instr);
1418 }
1399 } else if (instr->representation().IsDouble()) { 1419 } else if (instr->representation().IsDouble()) {
1400 return DoArithmeticD(Token::MOD, instr); 1420 return DoArithmeticD(Token::MOD, instr);
1401 } else { 1421 } else {
1402 return DoArithmeticT(Token::MOD, instr); 1422 return DoArithmeticT(Token::MOD, instr);
1403 } 1423 }
1404 } 1424 }
1405 1425
1406 1426
1407 LInstruction* LChunkBuilder::DoMul(HMul* instr) { 1427 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1408 if (instr->representation().IsSmiOrInteger32()) { 1428 if (instr->representation().IsSmiOrInteger32()) {
(...skipping 1125 matching lines...) Expand 10 before | Expand all | Expand 10 after
2534 } 2554 }
2535 2555
2536 2556
2537 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { 2557 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2538 LOperand* object = UseRegister(instr->object()); 2558 LOperand* object = UseRegister(instr->object());
2539 LOperand* index = UseRegister(instr->index()); 2559 LOperand* index = UseRegister(instr->index());
2540 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); 2560 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2541 } 2561 }
2542 2562
2543 } } // namespace v8::internal 2563 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-arm.h ('k') | src/arm/lithium-codegen-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698