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

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. 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 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 } 1214 }
1215 } 1215 }
1216 1216
1217 1217
1218 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1218 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1219 // Nothing to do. 1219 // Nothing to do.
1220 } 1220 }
1221 1221
1222 1222
1223 void LCodeGen::DoModI(LModI* instr) { 1223 void LCodeGen::DoModI(LModI* instr) {
1224 if (instr->hydrogen()->HasPowerOf2Divisor()) { 1224 HMod* hmod = instr->hydrogen();
1225 Register dividend = ToRegister(instr->left()); 1225 HValue* left = hmod->left();
1226 HValue* right = hmod->right();
1227 if (hmod->HasPowerOf2Divisor()) {
1228 // TODO(svenpanne) We should really do the strength reduction on the
1229 // Hydrogen level.
1230 Register left_reg = ToRegister(instr->left());
1231 ASSERT(left_reg.is(ToRegister(instr->result())));
1226 1232
1227 int32_t divisor = 1233 // Note: The code below even works when right contains kMinInt.
1228 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 1234 int32_t divisor = Abs(right->GetInteger32Constant());
1229 1235
1230 if (divisor < 0) divisor = -divisor; 1236 Label left_is_not_negative, done;
1231 1237 if (left->CanBeNegative()) {
1232 Label positive_dividend, done; 1238 __ test(left_reg, Operand(left_reg));
1233 __ test(dividend, Operand(dividend)); 1239 __ j(not_sign, &left_is_not_negative, Label::kNear);
1234 __ j(not_sign, &positive_dividend, Label::kNear); 1240 __ neg(left_reg);
1235 __ neg(dividend); 1241 __ and_(left_reg, divisor - 1);
1236 __ and_(dividend, divisor - 1); 1242 __ neg(left_reg);
1237 __ neg(dividend); 1243 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1238 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1244 DeoptimizeIf(zero, instr->environment());
1239 __ j(not_zero, &done, Label::kNear); 1245 }
1240 DeoptimizeIf(no_condition, instr->environment());
1241 } else {
1242 __ jmp(&done, Label::kNear); 1246 __ jmp(&done, Label::kNear);
1243 } 1247 }
1244 __ bind(&positive_dividend); 1248
1245 __ and_(dividend, divisor - 1); 1249 __ bind(&left_is_not_negative);
1250 __ and_(left_reg, divisor - 1);
1246 __ bind(&done); 1251 __ bind(&done);
1252
1253 } else if (hmod->has_fixed_right_arg()) {
1254 Register left_reg = ToRegister(instr->left());
1255 ASSERT(left_reg.is(ToRegister(instr->result())));
1256 Register right_reg = ToRegister(instr->right());
1257
1258 int32_t divisor = hmod->fixed_right_arg_value();
1259 ASSERT(IsPowerOf2(divisor));
1260
1261 // Check if our assumption of a fixed right operand still holds.
1262 __ cmp(right_reg, Immediate(divisor));
1263 DeoptimizeIf(not_equal, instr->environment());
1264
1265 Label left_is_not_negative, done;
1266 if (left->CanBeNegative()) {
1267 __ test(left_reg, Operand(left_reg));
1268 __ j(not_sign, &left_is_not_negative, Label::kNear);
1269 __ neg(left_reg);
1270 __ and_(left_reg, divisor - 1);
1271 __ neg(left_reg);
1272 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1273 DeoptimizeIf(zero, instr->environment());
1274 }
1275 __ jmp(&done, Label::kNear);
1276 }
1277
1278 __ bind(&left_is_not_negative);
1279 __ and_(left_reg, divisor - 1);
1280 __ bind(&done);
1281
1247 } else { 1282 } else {
1248 Label done, remainder_eq_dividend, slow, both_positive;
1249 Register left_reg = ToRegister(instr->left()); 1283 Register left_reg = ToRegister(instr->left());
1284 ASSERT(left_reg.is(eax));
1250 Register right_reg = ToRegister(instr->right()); 1285 Register right_reg = ToRegister(instr->right());
1251 Register result_reg = ToRegister(instr->result());
1252
1253 ASSERT(left_reg.is(eax));
1254 ASSERT(result_reg.is(edx));
1255 ASSERT(!right_reg.is(eax)); 1286 ASSERT(!right_reg.is(eax));
1256 ASSERT(!right_reg.is(edx)); 1287 ASSERT(!right_reg.is(edx));
1288 Register result_reg = ToRegister(instr->result());
1289 ASSERT(result_reg.is(edx));
1257 1290
1258 // Check for x % 0. 1291 Label done;
1259 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1292 // Check for x % 0, idiv would signal a divide error. We have to
1293 // deopt in this case because we can't return a NaN.
1294 if (right->CanBeZero()) {
1260 __ test(right_reg, Operand(right_reg)); 1295 __ test(right_reg, Operand(right_reg));
1261 DeoptimizeIf(zero, instr->environment()); 1296 DeoptimizeIf(zero, instr->environment());
1262 } 1297 }
1263 1298
1264 __ test(left_reg, Operand(left_reg)); 1299 // Check for kMinInt % -1, idiv would signal a divide error. We
1265 __ j(zero, &remainder_eq_dividend, Label::kNear); 1300 // have to deopt if we care about -0, because we can't return that.
1266 __ j(sign, &slow, Label::kNear); 1301 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
1267 1302 Label no_overflow_possible;
1268 __ test(right_reg, Operand(right_reg));
1269 __ j(not_sign, &both_positive, Label::kNear);
1270 // The sign of the divisor doesn't matter.
1271 __ neg(right_reg);
1272
1273 __ bind(&both_positive);
1274 // If the dividend is smaller than the nonnegative
1275 // divisor, the dividend is the result.
1276 __ cmp(left_reg, Operand(right_reg));
1277 __ j(less, &remainder_eq_dividend, Label::kNear);
1278
1279 // Check if the divisor is a PowerOfTwo integer.
1280 Register scratch = ToRegister(instr->temp());
1281 __ mov(scratch, right_reg);
1282 __ sub(Operand(scratch), Immediate(1));
1283 __ test(scratch, Operand(right_reg));
1284 __ j(not_zero, &slow, Label::kNear);
1285 __ and_(left_reg, Operand(scratch));
1286 __ jmp(&remainder_eq_dividend, Label::kNear);
1287
1288 // Slow case, using idiv instruction.
1289 __ bind(&slow);
1290
1291 // Check for (kMinInt % -1).
1292 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1293 Label left_not_min_int;
1294 __ cmp(left_reg, kMinInt); 1303 __ cmp(left_reg, kMinInt);
1295 __ j(not_zero, &left_not_min_int, Label::kNear); 1304 __ j(not_equal, &no_overflow_possible, Label::kNear);
1296 __ cmp(right_reg, -1); 1305 __ cmp(right_reg, -1);
1297 DeoptimizeIf(zero, instr->environment()); 1306 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1298 __ bind(&left_not_min_int); 1307 DeoptimizeIf(equal, instr->environment());
1308 } else {
1309 __ j(not_equal, &no_overflow_possible, Label::kNear);
1310 __ Set(result_reg, Immediate(0));
1311 __ jmp(&done, Label::kNear);
1312 }
1313 __ bind(&no_overflow_possible);
1299 } 1314 }
1300 1315
1301 // Sign extend to edx. 1316 // Sign extend dividend in eax into edx:eax.
1302 __ cdq(); 1317 __ cdq();
1303 1318
1304 // Check for (0 % -x) that will produce negative zero. 1319 // If we care about -0, test if the dividend is <0 and the result is 0.
1305 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1320 if (left->CanBeNegative() &&
1321 hmod->CanBeZero() &&
1322 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1306 Label positive_left; 1323 Label positive_left;
1307 Label done;
1308 __ test(left_reg, Operand(left_reg)); 1324 __ test(left_reg, Operand(left_reg));
1309 __ j(not_sign, &positive_left, Label::kNear); 1325 __ j(not_sign, &positive_left, Label::kNear);
1310 __ idiv(right_reg); 1326 __ idiv(right_reg);
1311
1312 // Test the remainder for 0, because then the result would be -0.
1313 __ test(result_reg, Operand(result_reg)); 1327 __ test(result_reg, Operand(result_reg));
1314 __ j(not_zero, &done, Label::kNear); 1328 DeoptimizeIf(zero, instr->environment());
1315 1329 __ jmp(&done, Label::kNear);
1316 DeoptimizeIf(no_condition, instr->environment());
1317 __ bind(&positive_left); 1330 __ bind(&positive_left);
1318 __ idiv(right_reg);
1319 __ bind(&done);
1320 } else {
1321 __ idiv(right_reg);
1322 } 1331 }
1323 __ jmp(&done, Label::kNear); 1332 __ idiv(right_reg);
1324
1325 __ bind(&remainder_eq_dividend);
1326 __ mov(result_reg, left_reg);
1327
1328 __ bind(&done); 1333 __ bind(&done);
1329 } 1334 }
1330 } 1335 }
1331 1336
1332 1337
1333 void LCodeGen::DoDivI(LDivI* instr) { 1338 void LCodeGen::DoDivI(LDivI* instr) {
1334 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { 1339 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) {
1335 Register dividend = ToRegister(instr->left()); 1340 Register dividend = ToRegister(instr->left());
1336 int32_t divisor = 1341 int32_t divisor =
1337 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 1342 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
(...skipping 5156 matching lines...) Expand 10 before | Expand all | Expand 10 after
6494 FixedArray::kHeaderSize - kPointerSize)); 6499 FixedArray::kHeaderSize - kPointerSize));
6495 __ bind(&done); 6500 __ bind(&done);
6496 } 6501 }
6497 6502
6498 6503
6499 #undef __ 6504 #undef __
6500 6505
6501 } } // namespace v8::internal 6506 } } // namespace v8::internal
6502 6507
6503 #endif // V8_TARGET_ARCH_IA32 6508 #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