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

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

Issue 191293012: Reland "Handle non-power-of-2 divisors in division-like operations". (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
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 | Annotate | Revision Log
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/lithium-x64.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 998 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 } 1009 }
1010 __ jmp(&done, Label::kNear); 1010 __ jmp(&done, Label::kNear);
1011 } 1011 }
1012 1012
1013 __ bind(&dividend_is_not_negative); 1013 __ bind(&dividend_is_not_negative);
1014 __ andl(dividend, Immediate(mask)); 1014 __ andl(dividend, Immediate(mask));
1015 __ bind(&done); 1015 __ bind(&done);
1016 } 1016 }
1017 1017
1018 1018
1019 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1020 Register dividend = ToRegister(instr->dividend());
1021 int32_t divisor = instr->divisor();
1022 ASSERT(ToRegister(instr->result()).is(rax));
1023
1024 if (divisor == 0) {
1025 DeoptimizeIf(no_condition, instr->environment());
1026 return;
1027 }
1028
1029 __ FlooringDiv(dividend, Abs(divisor));
1030 __ movl(rax, dividend);
1031 __ shrl(rax, Immediate(31));
1032 __ addl(rdx, rax);
1033 __ imull(rdx, rdx, Immediate(Abs(divisor)));
1034 __ movl(rax, dividend);
1035 __ subl(rax, rdx);
1036
1037 // Check for negative zero.
1038 HMod* hmod = instr->hydrogen();
1039 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
1040 hmod->left()->CanBeNegative()) {
1041 Label remainder_not_zero;
1042 __ j(not_zero, &remainder_not_zero, Label::kNear);
1043 __ cmpl(dividend, Immediate(0));
1044 DeoptimizeIf(less, instr->environment());
1045 __ bind(&remainder_not_zero);
1046 }
1047 }
1048
1049
1019 void LCodeGen::DoModI(LModI* instr) { 1050 void LCodeGen::DoModI(LModI* instr) {
1020 if (instr->hydrogen()->RightIsPowerOf2()) { 1051 if (instr->hydrogen()->RightIsPowerOf2()) {
1021 return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr)); 1052 return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr));
1022 } 1053 }
1023 HMod* hmod = instr->hydrogen(); 1054 HMod* hmod = instr->hydrogen();
1024 HValue* left = hmod->left(); 1055 HValue* left = hmod->left();
1025 HValue* right = hmod->right(); 1056 HValue* right = hmod->right();
1026 1057
1027 Register left_reg = ToRegister(instr->left()); 1058 Register left_reg = ToRegister(instr->left());
1028 ASSERT(left_reg.is(rax)); 1059 ASSERT(left_reg.is(rax));
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 } 1143 }
1113 __ bind(&not_kmin_int); 1144 __ bind(&not_kmin_int);
1114 __ sarl(dividend, Immediate(shift)); 1145 __ sarl(dividend, Immediate(shift));
1115 __ bind(&done); 1146 __ bind(&done);
1116 } 1147 }
1117 1148
1118 1149
1119 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1150 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1120 Register dividend = ToRegister(instr->dividend()); 1151 Register dividend = ToRegister(instr->dividend());
1121 int32_t divisor = instr->divisor(); 1152 int32_t divisor = instr->divisor();
1122 Register temp = ToRegister(instr->temp()); 1153 ASSERT(ToRegister(instr->result()).is(rdx));
1123 Register result = ToRegister(instr->result());
1124 1154
1125 if (divisor == 0) { 1155 if (divisor == 0) {
1126 DeoptimizeIf(no_condition, instr->environment()); 1156 DeoptimizeIf(no_condition, instr->environment());
1127 return; 1157 return;
1128 } 1158 }
1129 1159
1130 // Find b which: 2^b < divisor_abs < 2^(b+1). 1160 // Check for (0 / -x) that will produce negative zero.
1131 uint32_t divisor_abs = abs(divisor); 1161 HMathFloorOfDiv* hdiv = instr->hydrogen();
1132 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); 1162 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
1133 unsigned shift = 32 + b; // Precision +1bit (effectively). 1163 hdiv->left()->RangeCanInclude(0) && divisor < 0) {
1134 double multiplier_f = 1164 __ testl(dividend, dividend);
1135 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs;
1136 int64_t multiplier;
1137 if (multiplier_f - std::floor(multiplier_f) < 0.5) {
1138 multiplier = static_cast<int64_t>(std::floor(multiplier_f));
1139 } else {
1140 multiplier = static_cast<int64_t>(std::floor(multiplier_f)) + 1;
1141 }
1142 // The multiplier is a uint32.
1143 ASSERT(multiplier > 0 &&
1144 multiplier < (static_cast<int64_t>(1) << 32));
1145 // The multiply is int64, so sign-extend to r64.
1146 __ movsxlq(temp, dividend);
1147 if (divisor < 0 &&
1148 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1149 __ neg(temp);
1150 DeoptimizeIf(zero, instr->environment()); 1165 DeoptimizeIf(zero, instr->environment());
1151 } 1166 }
1152 __ Set(result, multiplier);
1153 // Result just fit in r64, because it's int32 * uint32.
1154 __ imul(result, temp);
1155 1167
1156 __ addq(result, Immediate(1 << 30)); 1168 __ FlooringDiv(dividend, divisor);
1157 __ sar(result, Immediate(shift));
1158 } 1169 }
1159 1170
1160 1171
1161 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1172 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1162 Register dividend = ToRegister(instr->dividend()); 1173 Register dividend = ToRegister(instr->dividend());
1163 int32_t divisor = instr->divisor(); 1174 int32_t divisor = instr->divisor();
1164 Register result = ToRegister(instr->result()); 1175 Register result = ToRegister(instr->result());
1165 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); 1176 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor))));
1166 ASSERT(!result.is(dividend)); 1177 ASSERT(!result.is(dividend));
1167 1178
(...skipping 23 matching lines...) Expand all
1191 // The arithmetic shift is always OK, the 'if' is an optimization only. 1202 // The arithmetic shift is always OK, the 'if' is an optimization only.
1192 if (shift > 1) __ sarl(result, Immediate(31)); 1203 if (shift > 1) __ sarl(result, Immediate(31));
1193 __ shrl(result, Immediate(32 - shift)); 1204 __ shrl(result, Immediate(32 - shift));
1194 __ addl(result, dividend); 1205 __ addl(result, dividend);
1195 __ sarl(result, Immediate(shift)); 1206 __ sarl(result, Immediate(shift));
1196 } 1207 }
1197 if (divisor < 0) __ negl(result); 1208 if (divisor < 0) __ negl(result);
1198 } 1209 }
1199 1210
1200 1211
1212 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1213 Register dividend = ToRegister(instr->dividend());
1214 int32_t divisor = instr->divisor();
1215 ASSERT(ToRegister(instr->result()).is(rdx));
1216
1217 if (divisor == 0) {
1218 DeoptimizeIf(no_condition, instr->environment());
1219 return;
1220 }
1221
1222 // Check for (0 / -x) that will produce negative zero.
1223 HDiv* hdiv = instr->hydrogen();
1224 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
1225 hdiv->left()->RangeCanInclude(0) && divisor < 0) {
1226 __ testl(dividend, dividend);
1227 DeoptimizeIf(zero, instr->environment());
1228 }
1229
1230 __ FlooringDiv(dividend, Abs(divisor));
1231 __ movl(rax, dividend);
1232 __ shrl(rax, Immediate(31));
1233 __ addl(rdx, rax);
1234 if (divisor < 0) __ neg(rdx);
1235
1236 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1237 __ movl(rax, rdx);
1238 __ imull(rax, rax, Immediate(divisor));
1239 __ subl(rax, dividend);
1240 DeoptimizeIf(not_equal, instr->environment());
1241 }
1242 }
1243
1244
1201 void LCodeGen::DoDivI(LDivI* instr) { 1245 void LCodeGen::DoDivI(LDivI* instr) {
1202 Register dividend = ToRegister(instr->left()); 1246 Register dividend = ToRegister(instr->left());
1203 Register divisor = ToRegister(instr->right()); 1247 Register divisor = ToRegister(instr->right());
1204 Register remainder = ToRegister(instr->temp()); 1248 Register remainder = ToRegister(instr->temp());
1205 Register result = ToRegister(instr->result()); 1249 Register result = ToRegister(instr->result());
1206 ASSERT(dividend.is(rax)); 1250 ASSERT(dividend.is(rax));
1207 ASSERT(remainder.is(rdx)); 1251 ASSERT(remainder.is(rdx));
1208 ASSERT(result.is(rax)); 1252 ASSERT(result.is(rax));
1209 ASSERT(!divisor.is(rax)); 1253 ASSERT(!divisor.is(rax));
1210 ASSERT(!divisor.is(rdx)); 1254 ASSERT(!divisor.is(rdx));
(...skipping 4411 matching lines...) Expand 10 before | Expand all | Expand 10 after
5622 FixedArray::kHeaderSize - kPointerSize)); 5666 FixedArray::kHeaderSize - kPointerSize));
5623 __ bind(&done); 5667 __ bind(&done);
5624 } 5668 }
5625 5669
5626 5670
5627 #undef __ 5671 #undef __
5628 5672
5629 } } // namespace v8::internal 5673 } } // namespace v8::internal
5630 5674
5631 #endif // V8_TARGET_ARCH_X64 5675 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698