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

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

Issue 189433008: MIPS: Consistenly handle power-of-2 divisors in division-like operations. (Closed) Base URL: https://github.com/v8/v8.git@gbl
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
« no previous file with comments | « src/mips/lithium-mips.h ('k') | no next file » | 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 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 1237
1238 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); 1238 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
1239 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); 1239 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand());
1240 return DefineAsRegister(new(zone()) LBitI(left, right)); 1240 return DefineAsRegister(new(zone()) LBitI(left, right));
1241 } else { 1241 } else {
1242 return DoArithmeticT(instr->op(), instr); 1242 return DoArithmeticT(instr->op(), instr);
1243 } 1243 }
1244 } 1244 }
1245 1245
1246 1246
1247 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
1248 ASSERT(instr->representation().IsSmiOrInteger32());
1249 ASSERT(instr->left()->representation().Equals(instr->representation()));
1250 ASSERT(instr->right()->representation().Equals(instr->representation()));
1251 LOperand* dividend = UseRegister(instr->left());
1252 LOperand* divisor = UseRegister(instr->right());
1253 LDivI* div = new(zone()) LDivI(dividend, divisor);
1254 return AssignEnvironment(DefineAsRegister(div));
1255 }
1256
1257
1247 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 1258 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
1248 if (instr->representation().IsSmiOrInteger32()) { 1259 if (instr->representation().IsSmiOrInteger32()) {
1249 ASSERT(instr->left()->representation().Equals(instr->representation())); 1260 return DoDivI(instr);
1250 ASSERT(instr->right()->representation().Equals(instr->representation()));
1251 LOperand* dividend = UseRegister(instr->left());
1252 LOperand* divisor = UseRegister(instr->right());
1253 LDivI* div = new(zone()) LDivI(dividend, divisor);
1254 return AssignEnvironment(DefineAsRegister(div));
1255 } else if (instr->representation().IsDouble()) { 1261 } else if (instr->representation().IsDouble()) {
1256 return DoArithmeticD(Token::DIV, instr); 1262 return DoArithmeticD(Token::DIV, instr);
1257 } else { 1263 } else {
1258 return DoArithmeticT(Token::DIV, instr); 1264 return DoArithmeticT(Token::DIV, instr);
1259 } 1265 }
1260 } 1266 }
1261 1267
1262 1268
1263 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { 1269 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) {
1264 uint32_t divisor_abs = abs(divisor); 1270 uint32_t divisor_abs = abs(divisor);
1265 // Dividing by 0, 1, and powers of 2 is easy. 1271 // Dividing by 0 or powers of 2 is easy.
1266 // Note that IsPowerOf2(0) returns true; 1272 if (divisor == 0 || IsPowerOf2(divisor_abs)) return true;
1267 ASSERT(IsPowerOf2(0) == true);
1268 if (IsPowerOf2(divisor_abs)) return true;
1269 1273
1270 // We have magic numbers for a few specific divisors. 1274 // We have magic numbers for a few specific divisors.
1271 // Details and proofs can be found in: 1275 // Details and proofs can be found in:
1272 // - Hacker's Delight, Henry S. Warren, Jr. 1276 // - Hacker's Delight, Henry S. Warren, Jr.
1273 // - The PowerPC Compiler Writer's Guide 1277 // - The PowerPC Compiler Writer's Guide
1274 // and probably many others. 1278 // and probably many others.
1275 // 1279 //
1276 // We handle 1280 // We handle
1277 // <divisor with magic numbers> * <power of 2> 1281 // <divisor with magic numbers> * <power of 2>
1278 // but not 1282 // but not
1279 // <divisor with magic numbers> * <other divisor with magic numbers> 1283 // <divisor with magic numbers> * <other divisor with magic numbers>
1280 int32_t power_of_2_factor = 1284 int32_t power_of_2_factor =
1281 CompilerIntrinsics::CountTrailingZeros(divisor_abs); 1285 CompilerIntrinsics::CountTrailingZeros(divisor_abs);
1282 DivMagicNumbers magic_numbers = 1286 DivMagicNumbers magic_numbers =
1283 DivMagicNumberFor(divisor_abs >> power_of_2_factor); 1287 DivMagicNumberFor(divisor_abs >> power_of_2_factor);
1284 if (magic_numbers.M != InvalidDivMagicNumber.M) return true; 1288 return magic_numbers.M != InvalidDivMagicNumber.M;
1289 }
1285 1290
1286 return false; 1291
1292 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
1293 LOperand* dividend = UseRegister(instr->left());
1294 LOperand* divisor = UseOrConstant(instr->right());
1295 LOperand* remainder = TempRegister();
1296 LInstruction* result =
1297 DefineAsRegister(
1298 new(zone()) LFlooringDivByConstI(dividend, divisor, remainder));
1299 return AssignEnvironment(result);
1287 } 1300 }
1288 1301
1289 1302
1290 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { 1303 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
1304 if (instr->right()->IsConstant()) {
1305 return DoFlooringDivByConstI(instr);
1306 } else {
1291 HValue* right = instr->right(); 1307 HValue* right = instr->right();
1292 LOperand* dividend = UseRegister(instr->left()); 1308 LOperand* dividend = UseRegister(instr->left());
1293 LOperand* divisor = UseRegisterOrConstant(right); 1309 LOperand* divisor = UseRegisterOrConstant(right);
1294 LOperand* remainder = TempRegister(); 1310 LOperand* remainder = TempRegister();
1295 return AssignEnvironment(DefineAsRegister( 1311 return AssignEnvironment(DefineAsRegister(
1296 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); 1312 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder)));
1313 }
1314 }
1315
1316
1317 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
1318 ASSERT(instr->representation().IsSmiOrInteger32());
1319 ASSERT(instr->left()->representation().Equals(instr->representation()));
1320 ASSERT(instr->right()->representation().Equals(instr->representation()));
1321 LOperand* dividend = UseRegisterAtStart(instr->left());
1322 int32_t divisor = instr->right()->GetInteger32Constant();
1323 LInstruction* result =
1324 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
1325 bool can_deopt =
1326 instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
1327 instr->left()->CanBeNegative();
1328 return can_deopt ? AssignEnvironment(result) : result;
1329 }
1330
1331
1332 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
1333 ASSERT(instr->representation().IsSmiOrInteger32());
1334 ASSERT(instr->left()->representation().Equals(instr->representation()));
1335 ASSERT(instr->right()->representation().Equals(instr->representation()));
1336 LOperand* dividend = UseRegister(instr->left());
1337 LOperand* divisor = UseRegister(instr->right());
1338 LModI* mod = new(zone()) LModI(dividend,
1339 divisor);
1340 LInstruction* result = DefineAsRegister(mod);
1341 bool can_deopt = (instr->right()->CanBeZero() ||
1342 (instr->left()->RangeCanInclude(kMinInt) &&
1343 instr->right()->RangeCanInclude(-1) &&
1344 instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
1345 (instr->left()->CanBeNegative() &&
1346 instr->CanBeZero() &&
1347 instr->CheckFlag(HValue::kBailoutOnMinusZero)));
1348 return can_deopt ? AssignEnvironment(result) : result;
1297 } 1349 }
1298 1350
1299 1351
1300 LInstruction* LChunkBuilder::DoMod(HMod* instr) { 1352 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
1301 HValue* left = instr->left();
1302 HValue* right = instr->right();
1303 if (instr->representation().IsSmiOrInteger32()) { 1353 if (instr->representation().IsSmiOrInteger32()) {
1304 ASSERT(instr->left()->representation().Equals(instr->representation())); 1354 return instr->RightIsPowerOf2() ? DoModByPowerOf2I(instr) : DoModI(instr);
1305 ASSERT(instr->right()->representation().Equals(instr->representation()));
1306 if (instr->RightIsPowerOf2()) {
1307 ASSERT(!right->CanBeZero());
1308 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
1309 UseConstant(right));
1310 LInstruction* result = DefineAsRegister(mod);
1311 return (left->CanBeNegative() &&
1312 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1313 ? AssignEnvironment(result)
1314 : result;
1315 } else {
1316 LModI* mod = new(zone()) LModI(UseRegister(left),
1317 UseRegister(right),
1318 TempRegister(),
1319 FixedTemp(f20),
1320 FixedTemp(f22));
1321 LInstruction* result = DefineAsRegister(mod);
1322 return (right->CanBeZero() ||
1323 (left->RangeCanInclude(kMinInt) &&
1324 right->RangeCanInclude(-1)) ||
1325 instr->CheckFlag(HValue::kBailoutOnMinusZero))
1326 ? AssignEnvironment(result)
1327 : result;
1328 }
1329 } else if (instr->representation().IsDouble()) { 1355 } else if (instr->representation().IsDouble()) {
1330 return DoArithmeticD(Token::MOD, instr); 1356 return DoArithmeticD(Token::MOD, instr);
1331 } else { 1357 } else {
1332 return DoArithmeticT(Token::MOD, instr); 1358 return DoArithmeticT(Token::MOD, instr);
1333 } 1359 }
1334 } 1360 }
1335 1361
1336 1362
1337 LInstruction* LChunkBuilder::DoMul(HMul* instr) { 1363 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
1338 if (instr->representation().IsSmiOrInteger32()) { 1364 if (instr->representation().IsSmiOrInteger32()) {
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after
2407 2433
2408 2434
2409 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { 2435 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
2410 LOperand* object = UseRegister(instr->object()); 2436 LOperand* object = UseRegister(instr->object());
2411 LOperand* index = UseRegister(instr->index()); 2437 LOperand* index = UseRegister(instr->index());
2412 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); 2438 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index));
2413 } 2439 }
2414 2440
2415 2441
2416 } } // namespace v8::internal 2442 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mips/lithium-mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698