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

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

Issue 200423004: MIPS: Fix Lithium div, mod and floor. (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 | « no previous file | src/mips/lithium-mips.h » ('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.7 1 // Copyright 2012 the V8 project authors. All rights reserved.7
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 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 __ Branch(USE_DELAY_SLOT, &done); 1093 __ Branch(USE_DELAY_SLOT, &done);
1094 __ subu(dividend, zero_reg, dividend); 1094 __ subu(dividend, zero_reg, dividend);
1095 } 1095 }
1096 1096
1097 __ bind(&dividend_is_not_negative); 1097 __ bind(&dividend_is_not_negative);
1098 __ And(dividend, dividend, Operand(mask)); 1098 __ And(dividend, dividend, Operand(mask));
1099 __ bind(&done); 1099 __ bind(&done);
1100 } 1100 }
1101 1101
1102 1102
1103 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1104 Register dividend = ToRegister(instr->dividend());
1105 int32_t divisor = instr->divisor();
1106 Register result = ToRegister(instr->result());
1107 ASSERT(!dividend.is(result));
1108
1109 if (divisor == 0) {
1110 DeoptimizeIf(al, instr->environment());
1111 return;
1112 }
1113
1114 __ FlooringDiv(result, dividend, Abs(divisor));
1115 __ srl(at, dividend, 31);
1116 __ Addu(result, result, at);
1117 __ Mul(result, result, Operand(Abs(divisor)));
1118 __ Subu(result, dividend, Operand(result));
1119
1120 // Check for negative zero.
1121 HMod* hmod = instr->hydrogen();
1122 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1123 Label remainder_not_zero;
1124 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
1125 DeoptimizeIf(lt, instr->environment(), dividend, Operand(zero_reg));
1126 __ bind(&remainder_not_zero);
1127 }
1128 }
1129
1130
1103 void LCodeGen::DoModI(LModI* instr) { 1131 void LCodeGen::DoModI(LModI* instr) {
1104 HMod* hmod = instr->hydrogen(); 1132 HMod* hmod = instr->hydrogen();
1105 const Register left_reg = ToRegister(instr->left()); 1133 const Register left_reg = ToRegister(instr->left());
1106 const Register right_reg = ToRegister(instr->right()); 1134 const Register right_reg = ToRegister(instr->right());
1107 const Register result_reg = ToRegister(instr->result()); 1135 const Register result_reg = ToRegister(instr->result());
1108 1136
1109 // div runs in the background while we check for special cases. 1137 // div runs in the background while we check for special cases.
1110 __ div(left_reg, right_reg); 1138 __ div(left_reg, right_reg);
1111 1139
1112 Label done; 1140 Label done;
(...skipping 21 matching lines...) Expand all
1134 // If we care about -0, test if the dividend is <0 and the result is 0. 1162 // If we care about -0, test if the dividend is <0 and the result is 0.
1135 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg)); 1163 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
1136 __ mfhi(result_reg); 1164 __ mfhi(result_reg);
1137 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1165 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1138 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); 1166 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
1139 } 1167 }
1140 __ bind(&done); 1168 __ bind(&done);
1141 } 1169 }
1142 1170
1143 1171
1172 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1173 Register dividend = ToRegister(instr->dividend());
1174 int32_t divisor = instr->divisor();
1175 Register result = ToRegister(instr->result());
1176 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor))));
1177 ASSERT(!result.is(dividend));
1178
1179 // Check for (0 / -x) that will produce negative zero.
1180 HDiv* hdiv = instr->hydrogen();
1181 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1182 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1183 }
1184 // Check for (kMinInt / -1).
1185 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1186 DeoptimizeIf(eq, instr->environment(), dividend, Operand(kMinInt));
1187 }
1188 // Deoptimize if remainder will not be 0.
1189 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1190 divisor != 1 && divisor != -1) {
1191 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1192 __ And(at, dividend, Operand(mask));
1193 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
1194 }
1195
1196 if (divisor == -1) { // Nice shortcut, not needed for correctness.
1197 __ Subu(result, zero_reg, dividend);
1198 return;
1199 }
1200 uint16_t shift = WhichPowerOf2Abs(divisor);
1201 if (shift == 0) {
1202 __ Move(result, dividend);
1203 } else if (shift == 1) {
1204 __ srl(result, dividend, 31);
1205 __ Addu(result, dividend, Operand(result));
1206 } else {
1207 __ sra(result, dividend, 31);
1208 __ srl(result, result, 32 - shift);
1209 __ Addu(result, dividend, Operand(result));
1210 }
1211 if (shift > 0) __ sra(result, result, shift);
1212 if (divisor < 0) __ Subu(result, zero_reg, result);
1213 }
1214
1215
1216 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1217 Register dividend = ToRegister(instr->dividend());
1218 int32_t divisor = instr->divisor();
1219 Register result = ToRegister(instr->result());
1220 ASSERT(!dividend.is(result));
1221
1222 if (divisor == 0) {
1223 DeoptimizeIf(al, instr->environment());
1224 return;
1225 }
1226
1227 // Check for (0 / -x) that will produce negative zero.
1228 HDiv* hdiv = instr->hydrogen();
1229 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1230 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1231 }
1232
1233 __ FlooringDiv(result, dividend, Abs(divisor));
1234 __ srl(at, dividend, 31);
1235 __ Addu(result, result, Operand(at));
1236 if (divisor < 0) __ Subu(result, zero_reg, result);
1237
1238 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1239 __ Mul(scratch0(), result, Operand(divisor));
1240 __ Subu(scratch0(), scratch0(), dividend);
1241 DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg));
1242 }
1243 }
1244
1245
1144 void LCodeGen::DoDivI(LDivI* instr) { 1246 void LCodeGen::DoDivI(LDivI* instr) {
1145 HBinaryOperation* hdiv = instr->hydrogen(); 1247 HBinaryOperation* hdiv = instr->hydrogen();
1146 const Register left = ToRegister(instr->left()); 1248 const Register left = ToRegister(instr->left());
1147 const Register right = ToRegister(instr->right()); 1249 const Register right = ToRegister(instr->right());
1148 const Register result = ToRegister(instr->result()); 1250 const Register result = ToRegister(instr->result());
1149 1251
1150 // On MIPS div is asynchronous - it will run in the background while we 1252 // On MIPS div is asynchronous - it will run in the background while we
1151 // check for special cases. 1253 // check for special cases.
1152 __ div(left, right); 1254 __ div(left, right);
1153 1255
(...skipping 12 matching lines...) Expand all
1166 1268
1167 // Check for (kMinInt / -1). 1269 // Check for (kMinInt / -1).
1168 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1270 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1169 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1271 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1170 Label left_not_min_int; 1272 Label left_not_min_int;
1171 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); 1273 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
1172 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); 1274 DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
1173 __ bind(&left_not_min_int); 1275 __ bind(&left_not_min_int);
1174 } 1276 }
1175 1277
1176 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1278 if (hdiv->IsMathFloorOfDiv()) {
1279 // We performed a truncating division. Correct the result if necessary.
1280 Label done;
1281 Register remainder = scratch0();
1282 __ mfhi(remainder);
1283 __ mflo(result);
1284 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1285 __ Xor(remainder, remainder, Operand(right));
1286 __ Branch(&done, ge, remainder, Operand(zero_reg));
1287 __ Subu(result, result, Operand(1));
1288 __ bind(&done);
1289 } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1177 __ mfhi(result); 1290 __ mfhi(result);
1178 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); 1291 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
1292 __ mflo(result);
1293 } else {
1294 __ mflo(result);
1179 } 1295 }
1180 __ mflo(result);
1181 } 1296 }
1182 1297
1183 1298
1184 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { 1299 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1185 DoubleRegister addend = ToDoubleRegister(instr->addend()); 1300 DoubleRegister addend = ToDoubleRegister(instr->addend());
1186 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); 1301 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1187 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); 1302 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1188 1303
1189 // This is computed in-place. 1304 // This is computed in-place.
1190 ASSERT(addend.is(ToDoubleRegister(instr->result()))); 1305 ASSERT(addend.is(ToDoubleRegister(instr->result())));
(...skipping 22 matching lines...) Expand all
1213 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1328 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1214 __ Move(scratch, dividend); 1329 __ Move(scratch, dividend);
1215 } 1330 }
1216 __ Subu(result, zero_reg, dividend); 1331 __ Subu(result, zero_reg, dividend);
1217 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1332 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1218 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); 1333 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
1219 } 1334 }
1220 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1335 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1221 // Note that we could emit branch-free code, but that would need one more 1336 // Note that we could emit branch-free code, but that would need one more
1222 // register. 1337 // register.
1223
1224 __ Xor(at, scratch, result); 1338 __ Xor(at, scratch, result);
1225 if (divisor == -1) { 1339 if (divisor == -1) {
1226 DeoptimizeIf(ge, instr->environment(), at, Operand(zero_reg)); 1340 DeoptimizeIf(ge, instr->environment(), at, Operand(zero_reg));
1227 __ sra(result, dividend, shift); 1341 __ sra(result, dividend, shift);
1228 } else { 1342 } else {
1229 Label no_overflow, done; 1343 Label no_overflow, done;
1230 __ Branch(&no_overflow, lt, at, Operand(zero_reg)); 1344 __ Branch(&no_overflow, lt, at, Operand(zero_reg));
1231 __ li(result, Operand(kMinInt / divisor)); 1345 __ li(result, Operand(kMinInt / divisor));
1232 __ Branch(&done); 1346 __ Branch(&done);
1233 __ bind(&no_overflow); 1347 __ bind(&no_overflow);
(...skipping 20 matching lines...) Expand all
1254 // Check for (0 / -x) that will produce negative zero. 1368 // Check for (0 / -x) that will produce negative zero.
1255 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1369 HMathFloorOfDiv* hdiv = instr->hydrogen();
1256 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1370 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1257 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); 1371 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1258 } 1372 }
1259 1373
1260 __ FlooringDiv(result, dividend, divisor); 1374 __ FlooringDiv(result, dividend, divisor);
1261 } 1375 }
1262 1376
1263 1377
1264 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
1265 const Register result = ToRegister(instr->result());
1266 const Register left = ToRegister(instr->left());
1267 const Register remainder = ToRegister(instr->temp());
1268 const Register scratch = scratch0();
1269
1270 Label done;
1271 const Register right = ToRegister(instr->right());
1272
1273 // On MIPS div is asynchronous - it will run in the background while we
1274 // check for special cases.
1275 __ div(left, right);
1276
1277 // Check for x / 0.
1278 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
1279
1280 // Check for (0 / -x) that will produce negative zero.
1281 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1282 Label left_not_zero;
1283 __ Branch(&left_not_zero, ne, left, Operand(zero_reg));
1284 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg));
1285 __ bind(&left_not_zero);
1286 }
1287
1288 // Check for (kMinInt / -1).
1289 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1290 Label left_not_min_int;
1291 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
1292 DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
1293 __ bind(&left_not_min_int);
1294 }
1295
1296 __ mfhi(remainder);
1297 __ mflo(result);
1298
1299 // We performed a truncating division. Correct the result if necessary.
1300 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1301 __ Xor(scratch , remainder, Operand(right));
1302 __ Branch(&done, ge, scratch, Operand(zero_reg));
1303 __ Subu(result, result, Operand(1));
1304 __ bind(&done);
1305 }
1306
1307
1308 void LCodeGen::DoMulI(LMulI* instr) { 1378 void LCodeGen::DoMulI(LMulI* instr) {
1309 Register scratch = scratch0(); 1379 Register scratch = scratch0();
1310 Register result = ToRegister(instr->result()); 1380 Register result = ToRegister(instr->result());
1311 // Note that result may alias left. 1381 // Note that result may alias left.
1312 Register left = ToRegister(instr->left()); 1382 Register left = ToRegister(instr->left());
1313 LOperand* right_op = instr->right(); 1383 LOperand* right_op = instr->right();
1314 1384
1315 bool bailout_on_minus_zero = 1385 bool bailout_on_minus_zero =
1316 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1386 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1317 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1387 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
(...skipping 4404 matching lines...) Expand 10 before | Expand all | Expand 10 after
5722 __ Subu(scratch, result, scratch); 5792 __ Subu(scratch, result, scratch);
5723 __ lw(result, FieldMemOperand(scratch, 5793 __ lw(result, FieldMemOperand(scratch,
5724 FixedArray::kHeaderSize - kPointerSize)); 5794 FixedArray::kHeaderSize - kPointerSize));
5725 __ bind(&done); 5795 __ bind(&done);
5726 } 5796 }
5727 5797
5728 5798
5729 #undef __ 5799 #undef __
5730 5800
5731 } } // namespace v8::internal 5801 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698