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

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: Rebased. ia32/x64/ARM done, MIPS restructured. 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
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
Jakob Kummerow 2013/06/07 16:50:07 I'm not sure this comment adds value either.
Sven Panne 2013/06/10 11:05:39 Actually it does: This part of DoModI is basically
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 = Abs(right->GetInteger32Constant());
Jakob Kummerow 2013/06/07 16:50:07 This just works by accident for right->GetInteger3
Sven Panne 2013/06/10 11:05:39 Yep, this clever handling has been there before, b
1241 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
1242 1247
1243 if (divisor < 0) divisor = -divisor; 1248 Label left_is_not_negative, done;
1244 1249 if (left->CanBeNegative()) {
1245 Label positive_dividend, done; 1250 __ test(left_reg, Operand(left_reg));
1246 __ test(dividend, Operand(dividend)); 1251 __ j(not_sign, &left_is_not_negative, Label::kNear);
1247 __ j(not_sign, &positive_dividend, Label::kNear); 1252 __ neg(left_reg);
1248 __ neg(dividend); 1253 __ and_(left_reg, divisor - 1);
1249 __ and_(dividend, divisor - 1); 1254 __ neg(left_reg);
1250 __ neg(dividend); 1255 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1251 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1256 DeoptimizeIf(zero, instr->environment());
1252 __ j(not_zero, &done, Label::kNear); 1257 }
1253 DeoptimizeIf(no_condition, instr->environment());
1254 } else {
1255 __ jmp(&done, Label::kNear); 1258 __ jmp(&done, Label::kNear);
1256 } 1259 }
1257 __ bind(&positive_dividend); 1260
1258 __ and_(dividend, divisor - 1); 1261 __ bind(&left_is_not_negative);
1262 __ and_(left_reg, divisor - 1);
1259 __ bind(&done); 1263 __ bind(&done);
1264
1265 } else if (hmod->has_fixed_right_arg()) {
1266 Register left_reg = ToRegister(instr->left());
1267 ASSERT(left_reg.is(ToRegister(instr->result())));
1268 Register right_reg = ToRegister(instr->right());
1269
1270 int32_t divisor = hmod->fixed_right_arg_value();
1271 ASSERT(IsPowerOf2(divisor));
1272
1273 // Check if our assumption of a fixed right operand still holds.
1274 __ cmp(right_reg, Immediate(divisor));
1275 DeoptimizeIf(not_equal, instr->environment());
1276
1277 Label left_is_not_negative, done;
1278 if (left->CanBeNegative()) {
1279 __ test(left_reg, Operand(left_reg));
1280 __ j(not_sign, &left_is_not_negative, Label::kNear);
1281 __ neg(left_reg);
1282 __ and_(left_reg, divisor - 1);
1283 __ neg(left_reg);
1284 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1285 DeoptimizeIf(zero, instr->environment());
1286 }
1287 __ jmp(&done, Label::kNear);
1288 }
1289
1290 __ bind(&left_is_not_negative);
1291 __ and_(left_reg, divisor - 1);
1292 __ bind(&done);
1293
1260 } else { 1294 } else {
1261 Label done, remainder_eq_dividend, slow, both_positive;
1262 Register left_reg = ToRegister(instr->left()); 1295 Register left_reg = ToRegister(instr->left());
1296 ASSERT(left_reg.is(eax));
1263 Register right_reg = ToRegister(instr->right()); 1297 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)); 1298 ASSERT(!right_reg.is(eax));
1269 ASSERT(!right_reg.is(edx)); 1299 ASSERT(!right_reg.is(edx));
1300 Register result_reg = ToRegister(instr->result());
1301 ASSERT(result_reg.is(edx));
1270 1302
1271 // Check for x % 0. 1303 Label done;
1272 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1304 // Check for x % 0, idiv would signal a divide error. We have to
1305 // deopt in this case because we can't return a NaN.
1306 if (right->CanBeZero()) {
1273 __ test(right_reg, Operand(right_reg)); 1307 __ test(right_reg, Operand(right_reg));
1274 DeoptimizeIf(zero, instr->environment()); 1308 DeoptimizeIf(zero, instr->environment());
1275 } 1309 }
1276 1310
1277 __ test(left_reg, Operand(left_reg)); 1311 // Check for kMinInt % -1, idiv would signal a divide error. We
1278 __ j(zero, &remainder_eq_dividend, Label::kNear); 1312 // have to deopt if we care about -0, because we can't return that.
1279 __ j(sign, &slow, Label::kNear); 1313 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
1280 1314 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); 1315 __ cmp(left_reg, kMinInt);
1308 __ j(not_zero, &left_not_min_int, Label::kNear); 1316 __ j(not_equal, &no_overflow_possible, Label::kNear);
1309 __ cmp(right_reg, -1); 1317 __ cmp(right_reg, -1);
1310 DeoptimizeIf(zero, instr->environment()); 1318 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1311 __ bind(&left_not_min_int); 1319 DeoptimizeIf(equal, instr->environment());
1320 } else {
1321 __ j(not_equal, &no_overflow_possible, Label::kNear);
1322 __ Set(result_reg, Immediate(0));
1323 __ jmp(&done, Label::kNear);
1324 }
1325 __ bind(&no_overflow_possible);
1312 } 1326 }
1313 1327
1314 // Sign extend to edx. 1328 // Sign extend dividend in eax into edx:eax.
1315 __ cdq(); 1329 __ cdq();
1316 1330
1317 // Check for (0 % -x) that will produce negative zero. 1331 // If we care about -0, test if the dividend is <0 and the result is 0.
1318 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1332 if (left->CanBeNegative() &&
1333 hmod->CanBeZero() &&
1334 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1319 Label positive_left; 1335 Label positive_left;
1320 Label done;
1321 __ test(left_reg, Operand(left_reg)); 1336 __ test(left_reg, Operand(left_reg));
1322 __ j(not_sign, &positive_left, Label::kNear); 1337 __ j(not_sign, &positive_left, Label::kNear);
1323 __ idiv(right_reg); 1338 __ idiv(right_reg);
1324
1325 // Test the remainder for 0, because then the result would be -0.
1326 __ test(result_reg, Operand(result_reg)); 1339 __ test(result_reg, Operand(result_reg));
1327 __ j(not_zero, &done, Label::kNear); 1340 DeoptimizeIf(zero, instr->environment());
1328 1341 __ jmp(&done, Label::kNear);
1329 DeoptimizeIf(no_condition, instr->environment());
1330 __ bind(&positive_left); 1342 __ bind(&positive_left);
1331 __ idiv(right_reg);
1332 __ bind(&done);
1333 } else {
1334 __ idiv(right_reg);
1335 } 1343 }
1336 __ jmp(&done, Label::kNear); 1344 __ idiv(right_reg);
1337
1338 __ bind(&remainder_eq_dividend);
1339 __ mov(result_reg, left_reg);
1340
1341 __ bind(&done); 1345 __ bind(&done);
1342 } 1346 }
1343 } 1347 }
1344 1348
1345 1349
1346 void LCodeGen::DoDivI(LDivI* instr) { 1350 void LCodeGen::DoDivI(LDivI* instr) {
1347 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { 1351 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) {
1348 Register dividend = ToRegister(instr->left()); 1352 Register dividend = ToRegister(instr->left());
1349 int32_t divisor = 1353 int32_t divisor =
1350 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 1354 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
(...skipping 5163 matching lines...) Expand 10 before | Expand all | Expand 10 after
6514 FixedArray::kHeaderSize - kPointerSize)); 6518 FixedArray::kHeaderSize - kPointerSize));
6515 __ bind(&done); 6519 __ bind(&done);
6516 } 6520 }
6517 6521
6518 6522
6519 #undef __ 6523 #undef __
6520 6524
6521 } } // namespace v8::internal 6525 } } // namespace v8::internal
6522 6526
6523 #endif // V8_TARGET_ARCH_IA32 6527 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698