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

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

Issue 11821013: MIPS: Optimise Math.floor(x/y) to use integer division for MIPS. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixed mjsunit test. Created 7 years, 7 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/mips/lithium-codegen-mips.h ('k') | 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. 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 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 __ mfhi(result); 1100 __ mfhi(result);
1101 1101
1102 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1102 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1103 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); 1103 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
1104 } 1104 }
1105 } 1105 }
1106 __ bind(&done); 1106 __ bind(&done);
1107 } 1107 }
1108 1108
1109 1109
1110 void LCodeGen::EmitSignedIntegerDivisionByConstant(
1111 Register result,
1112 Register dividend,
1113 int32_t divisor,
1114 Register remainder,
1115 Register scratch,
1116 LEnvironment* environment) {
1117 ASSERT(!AreAliased(dividend, scratch, at, no_reg));
1118
1119 uint32_t divisor_abs = abs(divisor);
1120
1121 int32_t power_of_2_factor =
1122 CompilerIntrinsics::CountTrailingZeros(divisor_abs);
1123
1124 switch (divisor_abs) {
1125 case 0:
1126 DeoptimizeIf(al, environment);
1127 return;
1128
1129 case 1:
1130 if (divisor > 0) {
1131 __ Move(result, dividend);
1132 } else {
1133 __ SubuAndCheckForOverflow(result, zero_reg, dividend, scratch);
1134 DeoptimizeIf(lt, environment, scratch, Operand(zero_reg));
1135 }
1136 // Compute the remainder.
1137 __ Move(remainder, zero_reg);
1138 return;
1139
1140 default:
1141 if (IsPowerOf2(divisor_abs)) {
1142 // Branch and condition free code for integer division by a power
1143 // of two.
1144 int32_t power = WhichPowerOf2(divisor_abs);
1145 if (power > 1) {
1146 __ sra(scratch, dividend, power - 1);
1147 }
1148 __ srl(scratch, scratch, 32 - power);
1149 __ Addu(scratch, dividend, Operand(scratch));
1150 __ sra(result, scratch, power);
1151 // Negate if necessary.
1152 // We don't need to check for overflow because the case '-1' is
1153 // handled separately.
1154 if (divisor < 0) {
1155 ASSERT(divisor != -1);
1156 __ Subu(result, zero_reg, Operand(result));
1157 }
1158 // Compute the remainder.
1159 if (divisor > 0) {
1160 __ sll(scratch, result, power);
1161 __ Subu(remainder, dividend, Operand(scratch));
1162 } else {
1163 __ sll(scratch, result, power);
1164 __ Addu(remainder, dividend, Operand(scratch));
1165 }
1166 return;
1167 } else if (LChunkBuilder::HasMagicNumberForDivisor(divisor)) {
1168 // Use magic numbers for a few specific divisors.
1169 // Details and proofs can be found in:
1170 // - Hacker's Delight, Henry S. Warren, Jr.
1171 // - The PowerPC Compiler Writer's Guide
1172 // and probably many others.
1173 //
1174 // We handle
1175 // <divisor with magic numbers> * <power of 2>
1176 // but not
1177 // <divisor with magic numbers> * <other divisor with magic numbers>
1178 DivMagicNumbers magic_numbers =
1179 DivMagicNumberFor(divisor_abs >> power_of_2_factor);
1180 // Branch and condition free code for integer division by a power
1181 // of two.
1182 const int32_t M = magic_numbers.M;
1183 const int32_t s = magic_numbers.s + power_of_2_factor;
1184
1185 __ li(scratch, Operand(M));
1186 __ mult(dividend, scratch);
1187 __ mfhi(scratch);
1188 if (M < 0) {
1189 __ Addu(scratch, scratch, Operand(dividend));
1190 }
1191 if (s > 0) {
1192 __ sra(scratch, scratch, s);
1193 __ mov(scratch, scratch);
1194 }
1195 __ srl(at, dividend, 31);
1196 __ Addu(result, scratch, Operand(at));
1197 if (divisor < 0) __ Subu(result, zero_reg, Operand(result));
1198 // Compute the remainder.
1199 __ li(scratch, Operand(divisor));
1200 // This sequence could be replaced with 'mls' when
1201 // it gets implemented.
1202 __ Mul(scratch, result, Operand(scratch));
1203 __ Subu(remainder, dividend, Operand(scratch));
1204 } else {
1205 __ li(scratch, Operand(divisor));
1206 __ div(dividend, scratch);
1207 __ mfhi(remainder);
1208 __ mflo(result);
1209 }
1210 }
1211 }
1212
1213
1110 void LCodeGen::DoDivI(LDivI* instr) { 1214 void LCodeGen::DoDivI(LDivI* instr) {
1111 const Register left = ToRegister(instr->left()); 1215 const Register left = ToRegister(instr->left());
1112 const Register right = ToRegister(instr->right()); 1216 const Register right = ToRegister(instr->right());
1113 const Register result = ToRegister(instr->result()); 1217 const Register result = ToRegister(instr->result());
1114 1218
1115 // On MIPS div is asynchronous - it will run in the background while we 1219 // On MIPS div is asynchronous - it will run in the background while we
1116 // check for special cases. 1220 // check for special cases.
1117 __ div(left, right); 1221 __ div(left, right);
1118 1222
1119 // Check for x / 0. 1223 // Check for x / 0.
(...skipping 28 matching lines...) Expand all
1148 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); 1252 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1149 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); 1253 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1150 1254
1151 // This is computed in-place. 1255 // This is computed in-place.
1152 ASSERT(addend.is(ToDoubleRegister(instr->result()))); 1256 ASSERT(addend.is(ToDoubleRegister(instr->result())));
1153 1257
1154 __ madd_d(addend, addend, multiplier, multiplicand); 1258 __ madd_d(addend, addend, multiplier, multiplicand);
1155 } 1259 }
1156 1260
1157 1261
1262 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
1263 const Register result = ToRegister(instr->result());
1264 const Register left = ToRegister(instr->left());
1265 const Register remainder = ToRegister(instr->temp());
1266 const Register scratch = scratch0();
1267
1268 Label done;
1269 // We only optimize this for division by constants, because the standard
1270 // integer division routine is usually slower than transitionning to FPU.
1271 ASSERT(instr->right()->IsConstantOperand());
1272 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
1273 if (divisor < 0) {
1274 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg));
1275 }
1276 EmitSignedIntegerDivisionByConstant(result,
1277 left,
1278 divisor,
1279 remainder,
1280 scratch,
1281 instr->environment());
1282 // We operated a truncating division. Correct the result if necessary.
1283 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1284 __ Xor(scratch , remainder, Operand(divisor));
1285 __ Branch(&done, ge, scratch, Operand(zero_reg));
1286 __ Subu(result, result, Operand(1));
1287 __ bind(&done);
1288 }
1289
1290
1158 void LCodeGen::DoMulI(LMulI* instr) { 1291 void LCodeGen::DoMulI(LMulI* instr) {
1159 Register scratch = scratch0(); 1292 Register scratch = scratch0();
1160 Register result = ToRegister(instr->result()); 1293 Register result = ToRegister(instr->result());
1161 // Note that result may alias left. 1294 // Note that result may alias left.
1162 Register left = ToRegister(instr->left()); 1295 Register left = ToRegister(instr->left());
1163 LOperand* right_op = instr->right(); 1296 LOperand* right_op = instr->right();
1164 1297
1165 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1298 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1166 bool bailout_on_minus_zero = 1299 bool bailout_on_minus_zero =
1167 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1300 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
(...skipping 4639 matching lines...) Expand 10 before | Expand all | Expand 10 after
5807 __ Subu(scratch, result, scratch); 5940 __ Subu(scratch, result, scratch);
5808 __ lw(result, FieldMemOperand(scratch, 5941 __ lw(result, FieldMemOperand(scratch,
5809 FixedArray::kHeaderSize - kPointerSize)); 5942 FixedArray::kHeaderSize - kPointerSize));
5810 __ bind(&done); 5943 __ bind(&done);
5811 } 5944 }
5812 5945
5813 5946
5814 #undef __ 5947 #undef __
5815 5948
5816 } } // namespace v8::internal 5949 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698