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

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

Issue 175143002: Consistenly handle power-of-2 divisors in division-like operations (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased 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.cc » ('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 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1231 1231
1232 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1232 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1233 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 1233 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1234 return DefineAsRegister(new(zone()) LBitI(left, right)); 1234 return DefineAsRegister(new(zone()) LBitI(left, right));
1235 } else { 1235 } else {
1236 return DoArithmeticT(instr->op(), instr); 1236 return DoArithmeticT(instr->op(), instr);
1237 } 1237 }
1238 } 1238 }
1239 1239
1240 1240
1241 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
1242 ASSERT(instr->representation().IsSmiOrInteger32());
1243 ASSERT(instr->left()->representation().Equals(instr->representation()));
1244 ASSERT(instr->right()->representation().Equals(instr->representation()));
1245 LOperand* dividend = UseRegister(instr->left());
1246 int32_t divisor = instr->right()->GetInteger32Constant();
1247 LInstruction* result =
1248 DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor));
1249 bool can_deopt =
1250 (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1251 instr->left()->RangeCanInclude(0) && divisor < 0) ||
1252 (instr->CheckFlag(HValue::kCanOverflow) &&
1253 instr->left()->RangeCanInclude(kMinInt) && divisor == -1) ||
1254 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1255 divisor != 1 && divisor != -1);
1256 return can_deopt ? AssignEnvironment(result) : result;
1257 }
1258
1259
1260 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
1261 ASSERT(instr->representation().IsSmiOrInteger32());
1262 ASSERT(instr->left()->representation().Equals(instr->representation()));
1263 ASSERT(instr->right()->representation().Equals(instr->representation()));
1264 LOperand* dividend = UseRegister(instr->left());
1265 LOperand* divisor = UseRegister(instr->right());
1266 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
1267 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1268 return AssignEnvironment(DefineAsRegister(div));
1269 }
1270
1271
1241 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1272 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1242 if (instr->representation().IsSmiOrInteger32()) { 1273 if (instr->representation().IsSmiOrInteger32()) {
1243 ASSERT(instr->left()->representation().Equals(instr->representation())); 1274 return instr->RightIsPowerOf2() ? DoDivByPowerOf2I(instr) : DoDivI(instr);
1244 ASSERT(instr->right()->representation().Equals(instr->representation()));
1245 if (instr->RightIsPowerOf2()) {
1246 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
1247 LOperand* value = UseRegister(instr->left());
1248 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL);
1249 return AssignEnvironment(DefineAsRegister(div));
1250 }
1251 LOperand* dividend = UseRegister(instr->left());
1252 LOperand* divisor = UseRegister(instr->right());
1253 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
1254 LDivI* div = new(zone()) LDivI(dividend, divisor, temp);
1255 return AssignEnvironment(DefineAsRegister(div));
1256 } else if (instr->representation().IsDouble()) { 1275 } else if (instr->representation().IsDouble()) {
1257 return DoArithmeticD(Token::DIV, instr); 1276 return DoArithmeticD(Token::DIV, instr);
1258 } else { 1277 } else {
1259 return DoArithmeticT(Token::DIV, instr); 1278 return DoArithmeticT(Token::DIV, instr);
1260 } 1279 }
1261 } 1280 }
1262 1281
1263 1282
1264 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { 1283 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
1265 uint32_t divisor_abs = abs(divisor); 1284 uint32_t divisor_abs = abs(divisor);
1266 // Dividing by 0, 1, and powers of 2 is easy. 1285 // Dividing by 0 or powers of 2 is easy.
1267 // Note that IsPowerOf2(0) returns true; 1286 if (divisor == 0 || IsPowerOf2(divisor_abs)) return true;
1268 ASSERT(IsPowerOf2(0) == true);
1269 if (IsPowerOf2(divisor_abs)) return true;
1270 1287
1271 // We have magic numbers for a few specific divisors. 1288 // We have magic numbers for a few specific divisors.
1272 // Details and proofs can be found in: 1289 // Details and proofs can be found in:
1273 // - Hacker's Delight, Henry S. Warren, Jr. 1290 // - Hacker's Delight, Henry S. Warren, Jr.
1274 // - The PowerPC Compiler Writer’s Guide 1291 // - The PowerPC Compiler Writer’s Guide
1275 // and probably many others. 1292 // and probably many others.
1276 // 1293 //
1277 // We handle 1294 // We handle
1278 // <divisor with magic numbers> * <power of 2> 1295 // <divisor with magic numbers> * <power of 2>
1279 // but not 1296 // but not
1280 // <divisor with magic numbers> * <other divisor with magic numbers> 1297 // <divisor with magic numbers> * <other divisor with magic numbers>
1281 int32_t power_of_2_factor = 1298 int32_t power_of_2_factor =
1282 CompilerIntrinsics::CountTrailingZeros(divisor_abs); 1299 CompilerIntrinsics::CountTrailingZeros(divisor_abs);
1283 DivMagicNumbers magic_numbers = 1300 DivMagicNumbers magic_numbers =
1284 DivMagicNumberFor(divisor_abs >> power_of_2_factor); 1301 DivMagicNumberFor(divisor_abs >> power_of_2_factor);
1285 if (magic_numbers.M != InvalidDivMagicNumber.M) return true; 1302 return magic_numbers.M != InvalidDivMagicNumber.M;
1303 }
1286 1304
1287 return false; 1305
1306 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
1307 LOperand* dividend = UseRegisterAtStart(instr->left());
1308 int32_t divisor = instr->right()->GetInteger32Constant();
1309 LInstruction* result =
1310 DefineSameAsFirst(
1311 new(zone()) LFlooringDivByPowerOf2I(dividend, divisor));
1312 bool can_deopt =
1313 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
1314 (instr->left()->RangeCanInclude(kMinInt) && divisor == -1);
1315 return can_deopt ? AssignEnvironment(result) : result;
1316 }
1317
1318
1319 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1320 LOperand* dividend = UseRegister(instr->left());
1321 LOperand* divisor = CpuFeatures::IsSupported(SUDIV)
1322 ? UseRegister(instr->right())
1323 : UseOrConstant(instr->right());
1324 LOperand* remainder = TempRegister();
1325 LInstruction* result =
1326 DefineAsRegister(
1327 new(zone()) LFlooringDivByConstI(dividend, divisor, remainder));
1328 return AssignEnvironment(result);
1288 } 1329 }
1289 1330
1290 1331
1291 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { 1332 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1292 // LMathFloorOfDiv can only handle a subset of divisors, so fall 1333 if (instr->RightIsPowerOf2()) {
1293 // back to a flooring division in all other cases. 1334 return DoFlooringDivByPowerOf2I(instr);
1294 HValue* right = instr->right(); 1335 } else if (instr->right()->IsConstant()) {
1295 if (!right->IsInteger32Constant() || 1336 // LMathFloorOfDiv can currently only handle a subset of divisors, so fall
1296 (!CpuFeatures::IsSupported(SUDIV) && 1337 // back to a flooring division in all other cases.
1297 !HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()))) { 1338 return (CpuFeatures::IsSupported(SUDIV) ||
1339 HasMagicNumberForDivisor(instr->right()->GetInteger32Constant()))
1340 ? DoFlooringDivByConstI(instr)
1341 : DoDivI(instr);
1342 } else {
1343 return DoDivI(instr);
1344 }
1345 }
1346
1347
1348 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1349 ASSERT(instr->representation().IsSmiOrInteger32());
1350 ASSERT(instr->left()->representation().Equals(instr->representation()));
1351 ASSERT(instr->right()->representation().Equals(instr->representation()));
1352 LOperand* dividend = UseRegisterAtStart(instr->left());
1353 int32_t divisor = instr->right()->GetInteger32Constant();
1354 LInstruction* result =
1355 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
1356 bool can_deopt =
1357 instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1358 instr->left()->CanBeNegative();
1359 return can_deopt ? AssignEnvironment(result) : result;
1360 }
1361
1362
1363 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1364 ASSERT(instr->representation().IsSmiOrInteger32());
1365 ASSERT(instr->left()->representation().Equals(instr->representation()));
1366 ASSERT(instr->right()->representation().Equals(instr->representation()));
1367 if (CpuFeatures::IsSupported(SUDIV)) {
1298 LOperand* dividend = UseRegister(instr->left()); 1368 LOperand* dividend = UseRegister(instr->left());
1299 LOperand* divisor = UseRegister(right); 1369 LOperand* divisor = UseRegister(instr->right());
1300 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); 1370 LInstruction* result =
1301 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); 1371 DefineAsRegister(new(zone()) LModI(dividend, divisor, NULL, NULL));
1302 return AssignEnvironment(DefineAsRegister(div)); 1372 bool can_deopt = (instr->right()->CanBeZero() ||
1373 (instr->left()->RangeCanInclude(kMinInt) &&
1374 instr->right()->RangeCanInclude(-1) &&
1375 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1376 (instr->left()->CanBeNegative() &&
1377 instr->CanBeZero() &&
1378 instr->CheckFlag(HValue::kBailoutOnMinusZero)));
1379 return can_deopt ? AssignEnvironment(result) : result;
1380 } else {
1381 LOperand* dividend = UseRegister(instr->left());
1382 LOperand* divisor = UseRegister(instr->right());
1383 LOperand* temp = FixedTemp(d10);
1384 LOperand* temp2 = FixedTemp(d11);
1385 LInstruction* result =
1386 DefineAsRegister(new(zone()) LModI(dividend, divisor, temp, temp2));
1387 bool can_deopt = (instr->right()->CanBeZero() ||
1388 (instr->left()->CanBeNegative() &&
1389 instr->CanBeZero() &&
1390 instr->CheckFlag(HValue::kBailoutOnMinusZero)));
1391 return can_deopt ? AssignEnvironment(result) : result;
1303 } 1392 }
1304
1305 LOperand* dividend = UseRegister(instr->left());
1306 LOperand* divisor = CpuFeatures::IsSupported(SUDIV)
1307 ? UseRegister(right)
1308 : UseOrConstant(right);
1309 LOperand* remainder = TempRegister();
1310 return AssignEnvironment(DefineAsRegister(
1311 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
1312 } 1393 }
1313 1394
1314 1395
1315 LInstruction* LChunkBuilder::DoMod(HMod* instr) { 1396 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1316 HValue* left = instr->left();
1317 HValue* right = instr->right();
1318 if (instr->representation().IsSmiOrInteger32()) { 1397 if (instr->representation().IsSmiOrInteger32()) {
1319 ASSERT(instr->left()->representation().Equals(instr->representation())); 1398 return instr->RightIsPowerOf2() ? DoModByPowerOf2I(instr) : DoModI(instr);
1320 ASSERT(instr->right()->representation().Equals(instr->representation()));
1321 if (instr->RightIsPowerOf2()) {
1322 ASSERT(!right->CanBeZero());
1323 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
1324 UseConstant(right));
1325 LInstruction* result = DefineAsRegister(mod);
1326 return (left->CanBeNegative() &&
1327 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1328 ? AssignEnvironment(result)
1329 : result;
1330 } else if (CpuFeatures::IsSupported(SUDIV)) {
1331 LModI* mod = new(zone()) LModI(UseRegister(left),
1332 UseRegister(right));
1333 LInstruction* result = DefineAsRegister(mod);
1334 return (right->CanBeZero() ||
1335 (left->RangeCanInclude(kMinInt) &&
1336 right->RangeCanInclude(-1) &&
1337 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1338 (left->CanBeNegative() &&
1339 instr->CanBeZero() &&
1340 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1341 ? AssignEnvironment(result)
1342 : result;
1343 } else {
1344 LModI* mod = new(zone()) LModI(UseRegister(left),
1345 UseRegister(right),
1346 FixedTemp(d10),
1347 FixedTemp(d11));
1348 LInstruction* result = DefineAsRegister(mod);
1349 return (right->CanBeZero() ||
1350 (left->CanBeNegative() &&
1351 instr->CanBeZero() &&
1352 instr->CheckFlag(HValue::kBailoutOnMinusZero)))
1353 ? AssignEnvironment(result)
1354 : result;
1355 }
1356 } else if (instr->representation().IsDouble()) { 1399 } else if (instr->representation().IsDouble()) {
1357 return DoArithmeticD(Token::MOD, instr); 1400 return DoArithmeticD(Token::MOD, instr);
1358 } else { 1401 } else {
1359 return DoArithmeticT(Token::MOD, instr); 1402 return DoArithmeticT(Token::MOD, instr);
1360 } 1403 }
1361 } 1404 }
1362 1405
1363 1406
1364 LInstruction* LChunkBuilder::DoMul(HMul* instr) { 1407 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1365 if (instr->representation().IsSmiOrInteger32()) { 1408 if (instr->representation().IsSmiOrInteger32()) {
(...skipping 1111 matching lines...) Expand 10 before | Expand all | Expand 10 after
2477 } 2520 }
2478 2521
2479 2522
2480 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { 2523 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2481 LOperand* object = UseRegister(instr->object()); 2524 LOperand* object = UseRegister(instr->object());
2482 LOperand* index = UseRegister(instr->index()); 2525 LOperand* index = UseRegister(instr->index());
2483 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); 2526 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2484 } 2527 }
2485 2528
2486 } } // namespace v8::internal 2529 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-arm.h ('k') | src/arm/lithium-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698