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

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 15769010: Improve code for integral modulus calculation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 6 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/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.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 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 } 1227 }
1228 } 1228 }
1229 1229
1230 1230
1231 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1231 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1232 // Nothing to do. 1232 // Nothing to do.
1233 } 1233 }
1234 1234
1235 1235
1236 void LCodeGen::DoModI(LModI* instr) { 1236 void LCodeGen::DoModI(LModI* instr) {
1237 if (instr->hydrogen()->HasPowerOf2Divisor()) { 1237 HMod* hmod = instr->hydrogen();
1238 Register dividend = ToRegister(instr->left()); 1238 HValue* left = hmod->left();
1239 HValue* right = hmod->right();
1240 if (hmod->HasPowerOf2Divisor()) {
1241 // TODO(svenpanne) We should really do the strength reduction on the
1242 // Hydrogen level.
1243 Register left_reg = ToRegister(instr->left());
1244 ASSERT(left_reg.is(ToRegister(instr->result())));
1239 1245
1240 int32_t divisor = 1246 int32_t divisor = HConstant::cast(right)->Integer32Value();
Jakob Kummerow 2013/06/05 17:08:41 even shorter: right->GetInteger32Constant()
Sven Panne 2013/06/06 06:50:23 Done. Lame excuse: It has been there before. ;-) F
1241 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
1242
1243 if (divisor < 0) divisor = -divisor; 1247 if (divisor < 0) divisor = -divisor;
1244 1248
1245 Label positive_dividend, done; 1249 Label left_is_not_negative, done;
1246 __ test(dividend, Operand(dividend)); 1250 if (left->CanBeNegative()) {
1247 __ j(not_sign, &positive_dividend, Label::kNear); 1251 __ test(left_reg, Operand(left_reg));
1248 __ neg(dividend); 1252 __ j(not_sign, &left_is_not_negative, Label::kNear);
1249 __ and_(dividend, divisor - 1); 1253 __ neg(left_reg);
1250 __ neg(dividend); 1254 __ and_(left_reg, divisor - 1);
1251 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1255 __ neg(left_reg);
1252 __ j(not_zero, &done, Label::kNear); 1256 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1253 DeoptimizeIf(no_condition, instr->environment()); 1257 DeoptimizeIf(zero, instr->environment());
1254 } else { 1258 }
1255 __ jmp(&done, Label::kNear); 1259 __ jmp(&done, Label::kNear);
1256 } 1260 }
1257 __ bind(&positive_dividend); 1261
1258 __ and_(dividend, divisor - 1); 1262 __ bind(&left_is_not_negative);
1263 __ and_(left_reg, divisor - 1);
1259 __ bind(&done); 1264 __ bind(&done);
1265
1266 } else if (hmod->has_fixed_right_arg()) {
1267 Register left_reg = ToRegister(instr->left());
1268 ASSERT(left_reg.is(ToRegister(instr->result())));
1269 Register right_reg = ToRegister(instr->right());
1270
1271 int32_t divisor = hmod->fixed_right_arg_value();
1272 ASSERT(IsPowerOf2(divisor));
1273
1274 // Check if our assumption of a fixed right operand still holds.
1275 __ cmp(right_reg, Immediate(divisor));
1276 DeoptimizeIf(not_equal, instr->environment());
1277
1278 Label left_is_not_negative, done;
1279 if (left->CanBeNegative()) {
1280 __ test(left_reg, Operand(left_reg));
1281 __ j(not_sign, &left_is_not_negative, Label::kNear);
1282 __ neg(left_reg);
1283 __ and_(left_reg, divisor - 1);
1284 __ neg(left_reg);
1285 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1286 DeoptimizeIf(zero, instr->environment());
1287 }
1288 __ jmp(&done, Label::kNear);
1289 }
1290
1291 __ bind(&left_is_not_negative);
1292 __ and_(left_reg, divisor - 1);
1293 __ bind(&done);
1294
1260 } else { 1295 } else {
1261 Label done, remainder_eq_dividend, slow, both_positive;
1262 Register left_reg = ToRegister(instr->left()); 1296 Register left_reg = ToRegister(instr->left());
1297 ASSERT(left_reg.is(eax));
1263 Register right_reg = ToRegister(instr->right()); 1298 Register right_reg = ToRegister(instr->right());
1264 Register result_reg = ToRegister(instr->result());
1265
1266 ASSERT(left_reg.is(eax));
1267 ASSERT(result_reg.is(edx));
1268 ASSERT(!right_reg.is(eax)); 1299 ASSERT(!right_reg.is(eax));
1269 ASSERT(!right_reg.is(edx)); 1300 ASSERT(!right_reg.is(edx));
1301 Register result_reg = ToRegister(instr->result());
1302 ASSERT(result_reg.is(edx));
1270 1303
1271 // Check for x % 0. 1304 Label done;
1272 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1305 // Check for x % 0, idiv would signal a divide error. We have to
1306 // deopt in this case because we can't return a NaN.
1307 if (right->CanBeZero()) {
1273 __ test(right_reg, Operand(right_reg)); 1308 __ test(right_reg, Operand(right_reg));
1274 DeoptimizeIf(zero, instr->environment()); 1309 DeoptimizeIf(zero, instr->environment());
1275 } 1310 }
1276 1311
1277 __ test(left_reg, Operand(left_reg)); 1312 // Check for kMinInt % -1, idiv would signal a divide error. We
1278 __ j(zero, &remainder_eq_dividend, Label::kNear); 1313 // have to deopt if we care about -0, because we can't return that.
1279 __ j(sign, &slow, Label::kNear); 1314 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
1280 1315 Label no_overflow_possible;
1281 __ test(right_reg, Operand(right_reg));
1282 __ j(not_sign, &both_positive, Label::kNear);
1283 // The sign of the divisor doesn't matter.
1284 __ neg(right_reg);
1285
1286 __ bind(&both_positive);
1287 // If the dividend is smaller than the nonnegative
1288 // divisor, the dividend is the result.
1289 __ cmp(left_reg, Operand(right_reg));
1290 __ j(less, &remainder_eq_dividend, Label::kNear);
1291
1292 // Check if the divisor is a PowerOfTwo integer.
1293 Register scratch = ToRegister(instr->temp());
1294 __ mov(scratch, right_reg);
1295 __ sub(Operand(scratch), Immediate(1));
1296 __ test(scratch, Operand(right_reg));
1297 __ j(not_zero, &slow, Label::kNear);
1298 __ and_(left_reg, Operand(scratch));
1299 __ jmp(&remainder_eq_dividend, Label::kNear);
1300
1301 // Slow case, using idiv instruction.
1302 __ bind(&slow);
1303
1304 // Check for (kMinInt % -1).
1305 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1306 Label left_not_min_int;
1307 __ cmp(left_reg, kMinInt); 1316 __ cmp(left_reg, kMinInt);
1308 __ j(not_zero, &left_not_min_int, Label::kNear); 1317 __ j(not_equal, &no_overflow_possible, Label::kNear);
1309 __ cmp(right_reg, -1); 1318 __ cmp(right_reg, -1);
1310 DeoptimizeIf(zero, instr->environment()); 1319 __ j(not_equal, &no_overflow_possible, Label::kNear);
1311 __ bind(&left_not_min_int); 1320 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1321 __ test(left_reg, Operand(left_reg));
Jakob Kummerow 2013/06/05 17:08:41 Why this test? You already know that left_reg == k
Sven Panne 2013/06/06 06:50:23 Ooops, this is a remnant of several iterations of
1322 DeoptimizeIf(sign, instr->environment());
1323 }
1324 __ Set(result_reg, Immediate(0));
1325 __ jmp(&done);
1326 __ bind(&no_overflow_possible);
1312 } 1327 }
1313 1328
1314 // Sign extend to edx. 1329 // Sign extend dividend in eax into edx:eax.
1315 __ cdq(); 1330 __ cdq();
1316 1331
1317 // Check for (0 % -x) that will produce negative zero. 1332 // If we care about -0, test if the dividend is <0 and the result is 0.
1318 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1333 if (left->CanBeNegative() &&
1334 hmod->CanBeZero() &&
1335 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1319 Label positive_left; 1336 Label positive_left;
1320 Label done;
1321 __ test(left_reg, Operand(left_reg)); 1337 __ test(left_reg, Operand(left_reg));
1322 __ j(not_sign, &positive_left, Label::kNear); 1338 __ j(not_sign, &positive_left, Label::kNear);
1339
1323 __ idiv(right_reg); 1340 __ idiv(right_reg);
1341 __ test(result_reg, Operand(result_reg));
1342 DeoptimizeIf(zero, instr->environment());
1343 __ jmp(&done, Label::kNear);
1324 1344
1325 // Test the remainder for 0, because then the result would be -0.
1326 __ test(result_reg, Operand(result_reg));
1327 __ j(not_zero, &done, Label::kNear);
1328
1329 DeoptimizeIf(no_condition, instr->environment());
1330 __ bind(&positive_left); 1345 __ bind(&positive_left);
1331 __ idiv(right_reg); 1346 __ idiv(right_reg);
1332 __ bind(&done);
1333 } else { 1347 } else {
1334 __ idiv(right_reg); 1348 __ idiv(right_reg);
1335 } 1349 }
1336 __ jmp(&done, Label::kNear);
1337
1338 __ bind(&remainder_eq_dividend);
1339 __ mov(result_reg, left_reg);
1340
1341 __ bind(&done); 1350 __ bind(&done);
1342 } 1351 }
1343 } 1352 }
1344 1353
1345 1354
1346 void LCodeGen::DoDivI(LDivI* instr) { 1355 void LCodeGen::DoDivI(LDivI* instr) {
1347 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { 1356 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) {
1348 Register dividend = ToRegister(instr->left()); 1357 Register dividend = ToRegister(instr->left());
1349 int32_t divisor = 1358 int32_t divisor =
1350 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 1359 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
(...skipping 5163 matching lines...) Expand 10 before | Expand all | Expand 10 after
6514 FixedArray::kHeaderSize - kPointerSize)); 6523 FixedArray::kHeaderSize - kPointerSize));
6515 __ bind(&done); 6524 __ bind(&done);
6516 } 6525 }
6517 6526
6518 6527
6519 #undef __ 6528 #undef __
6520 6529
6521 } } // namespace v8::internal 6530 } } // namespace v8::internal
6522 6531
6523 #endif // V8_TARGET_ARCH_IA32 6532 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698