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

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

Issue 190383002: Handle non-power-of-2 divisors in division-like operations (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased 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 __ imull(rdx, rdx, Immediate(Abs(divisor)));
1031 __ movl(rax, dividend);
1032 __ subl(rax, rdx);
1033
1034 // Check for negative zero.
1035 HMod* hmod = instr->hydrogen();
1036 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
1037 hmod->left()->CanBeNegative()) {
1038 Label remainder_not_zero;
1039 __ j(not_zero, &remainder_not_zero, Label::kNear);
1040 __ cmpl(dividend, Immediate(0));
1041 DeoptimizeIf(less, instr->environment());
1042 __ bind(&remainder_not_zero);
1043 }
1044 }
1045
1046
1019 void LCodeGen::DoModI(LModI* instr) { 1047 void LCodeGen::DoModI(LModI* instr) {
1020 if (instr->hydrogen()->RightIsPowerOf2()) { 1048 if (instr->hydrogen()->RightIsPowerOf2()) {
1021 return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr)); 1049 return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr));
1022 } 1050 }
1023 HMod* hmod = instr->hydrogen(); 1051 HMod* hmod = instr->hydrogen();
1024 HValue* left = hmod->left(); 1052 HValue* left = hmod->left();
1025 HValue* right = hmod->right(); 1053 HValue* right = hmod->right();
1026 1054
1027 Register left_reg = ToRegister(instr->left()); 1055 Register left_reg = ToRegister(instr->left());
1028 ASSERT(left_reg.is(rax)); 1056 ASSERT(left_reg.is(rax));
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 } 1140 }
1113 __ bind(&not_kmin_int); 1141 __ bind(&not_kmin_int);
1114 __ sarl(dividend, Immediate(shift)); 1142 __ sarl(dividend, Immediate(shift));
1115 __ bind(&done); 1143 __ bind(&done);
1116 } 1144 }
1117 1145
1118 1146
1119 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1147 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1120 Register dividend = ToRegister(instr->dividend()); 1148 Register dividend = ToRegister(instr->dividend());
1121 int32_t divisor = instr->divisor(); 1149 int32_t divisor = instr->divisor();
1122 Register temp = ToRegister(instr->temp()); 1150 ASSERT(ToRegister(instr->result()).is(rdx));
1123 Register result = ToRegister(instr->result());
1124 1151
1125 if (divisor == 0) { 1152 if (divisor == 0) {
1126 DeoptimizeIf(no_condition, instr->environment()); 1153 DeoptimizeIf(no_condition, instr->environment());
1127 return; 1154 return;
1128 } 1155 }
1129 1156
1130 // Find b which: 2^b < divisor_abs < 2^(b+1). 1157 // Check for (0 / -x) that will produce negative zero.
1131 uint32_t divisor_abs = abs(divisor); 1158 HMathFloorOfDiv* hdiv = instr->hydrogen();
1132 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); 1159 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
1133 unsigned shift = 32 + b; // Precision +1bit (effectively). 1160 hdiv->left()->RangeCanInclude(0) && divisor < 0) {
1134 double multiplier_f = 1161 __ 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()); 1162 DeoptimizeIf(zero, instr->environment());
1151 } 1163 }
1152 __ Set(result, multiplier);
1153 // Result just fit in r64, because it's int32 * uint32.
1154 __ imul(result, temp);
1155 1164
1156 __ addq(result, Immediate(1 << 30)); 1165 __ FlooringDiv(dividend, divisor);
1157 __ sar(result, Immediate(shift));
1158 } 1166 }
1159 1167
1160 1168
1161 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1169 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1162 Register dividend = ToRegister(instr->dividend()); 1170 Register dividend = ToRegister(instr->dividend());
1163 int32_t divisor = instr->divisor(); 1171 int32_t divisor = instr->divisor();
1164 Register result = ToRegister(instr->result()); 1172 Register result = ToRegister(instr->result());
1165 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); 1173 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor))));
1166 ASSERT(!result.is(dividend)); 1174 ASSERT(!result.is(dividend));
1167 1175
(...skipping 23 matching lines...) Expand all
1191 // The arithmetic shift is always OK, the 'if' is an optimization only. 1199 // The arithmetic shift is always OK, the 'if' is an optimization only.
1192 if (shift > 1) __ sarl(result, Immediate(31)); 1200 if (shift > 1) __ sarl(result, Immediate(31));
1193 __ shrl(result, Immediate(32 - shift)); 1201 __ shrl(result, Immediate(32 - shift));
1194 __ addl(result, dividend); 1202 __ addl(result, dividend);
1195 __ sarl(result, Immediate(shift)); 1203 __ sarl(result, Immediate(shift));
1196 } 1204 }
1197 if (divisor < 0) __ negl(result); 1205 if (divisor < 0) __ negl(result);
1198 } 1206 }
1199 1207
1200 1208
1209 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1210 Register dividend = ToRegister(instr->dividend());
1211 int32_t divisor = instr->divisor();
1212 ASSERT(ToRegister(instr->result()).is(rdx));
1213
1214 if (divisor == 0) {
1215 DeoptimizeIf(no_condition, instr->environment());
1216 return;
1217 }
1218
1219 // Check for (0 / -x) that will produce negative zero.
1220 HDiv* hdiv = instr->hydrogen();
1221 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
1222 hdiv->left()->RangeCanInclude(0) && divisor < 0) {
1223 __ testl(dividend, dividend);
1224 DeoptimizeIf(zero, instr->environment());
1225 }
1226
1227 __ FlooringDiv(dividend, Abs(divisor));
1228 if (divisor < 0) __ neg(rdx);
1229
1230 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1231 __ movl(rax, rdx);
1232 __ imull(rax, rax, Immediate(divisor));
1233 __ subl(rax, dividend);
1234 DeoptimizeIf(not_equal, instr->environment());
1235 }
1236 }
1237
1238
1201 void LCodeGen::DoDivI(LDivI* instr) { 1239 void LCodeGen::DoDivI(LDivI* instr) {
1202 Register dividend = ToRegister(instr->left()); 1240 Register dividend = ToRegister(instr->left());
1203 Register divisor = ToRegister(instr->right()); 1241 Register divisor = ToRegister(instr->right());
1204 Register remainder = ToRegister(instr->temp()); 1242 Register remainder = ToRegister(instr->temp());
1205 Register result = ToRegister(instr->result()); 1243 Register result = ToRegister(instr->result());
1206 ASSERT(dividend.is(rax)); 1244 ASSERT(dividend.is(rax));
1207 ASSERT(remainder.is(rdx)); 1245 ASSERT(remainder.is(rdx));
1208 ASSERT(result.is(rax)); 1246 ASSERT(result.is(rax));
1209 ASSERT(!divisor.is(rax)); 1247 ASSERT(!divisor.is(rax));
1210 ASSERT(!divisor.is(rdx)); 1248 ASSERT(!divisor.is(rdx));
(...skipping 4387 matching lines...) Expand 10 before | Expand all | Expand 10 after
5598 FixedArray::kHeaderSize - kPointerSize)); 5636 FixedArray::kHeaderSize - kPointerSize));
5599 __ bind(&done); 5637 __ bind(&done);
5600 } 5638 }
5601 5639
5602 5640
5603 #undef __ 5641 #undef __
5604 5642
5605 } } // namespace v8::internal 5643 } } // namespace v8::internal
5606 5644
5607 #endif // V8_TARGET_ARCH_X64 5645 #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