OLD | NEW |
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 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 __ FlooringDiv(dividend, Abs(divisor)); | 1029 __ FlooringDiv(dividend, Abs(divisor)); |
1030 __ movl(rax, dividend); | 1030 __ movl(rax, dividend); |
1031 __ shrl(rax, Immediate(31)); | 1031 __ shrl(rax, Immediate(31)); |
1032 __ addl(rdx, rax); | 1032 __ addl(rdx, rax); |
1033 __ imull(rdx, rdx, Immediate(Abs(divisor))); | 1033 __ imull(rdx, rdx, Immediate(Abs(divisor))); |
1034 __ movl(rax, dividend); | 1034 __ movl(rax, dividend); |
1035 __ subl(rax, rdx); | 1035 __ subl(rax, rdx); |
1036 | 1036 |
1037 // Check for negative zero. | 1037 // Check for negative zero. |
1038 HMod* hmod = instr->hydrogen(); | 1038 HMod* hmod = instr->hydrogen(); |
1039 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) && | 1039 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1040 hmod->left()->CanBeNegative()) { | |
1041 Label remainder_not_zero; | 1040 Label remainder_not_zero; |
1042 __ j(not_zero, &remainder_not_zero, Label::kNear); | 1041 __ j(not_zero, &remainder_not_zero, Label::kNear); |
1043 __ cmpl(dividend, Immediate(0)); | 1042 __ cmpl(dividend, Immediate(0)); |
1044 DeoptimizeIf(less, instr->environment()); | 1043 DeoptimizeIf(less, instr->environment()); |
1045 __ bind(&remainder_not_zero); | 1044 __ bind(&remainder_not_zero); |
1046 } | 1045 } |
1047 } | 1046 } |
1048 | 1047 |
1049 | 1048 |
1050 void LCodeGen::DoModI(LModI* instr) { | 1049 void LCodeGen::DoModI(LModI* instr) { |
1051 if (instr->hydrogen()->RightIsPowerOf2()) { | |
1052 return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr)); | |
1053 } | |
1054 HMod* hmod = instr->hydrogen(); | 1050 HMod* hmod = instr->hydrogen(); |
1055 HValue* left = hmod->left(); | |
1056 HValue* right = hmod->right(); | |
1057 | 1051 |
1058 Register left_reg = ToRegister(instr->left()); | 1052 Register left_reg = ToRegister(instr->left()); |
1059 ASSERT(left_reg.is(rax)); | 1053 ASSERT(left_reg.is(rax)); |
1060 Register right_reg = ToRegister(instr->right()); | 1054 Register right_reg = ToRegister(instr->right()); |
1061 ASSERT(!right_reg.is(rax)); | 1055 ASSERT(!right_reg.is(rax)); |
1062 ASSERT(!right_reg.is(rdx)); | 1056 ASSERT(!right_reg.is(rdx)); |
1063 Register result_reg = ToRegister(instr->result()); | 1057 Register result_reg = ToRegister(instr->result()); |
1064 ASSERT(result_reg.is(rdx)); | 1058 ASSERT(result_reg.is(rdx)); |
1065 | 1059 |
1066 Label done; | 1060 Label done; |
1067 // Check for x % 0, idiv would signal a divide error. We have to | 1061 // Check for x % 0, idiv would signal a divide error. We have to |
1068 // deopt in this case because we can't return a NaN. | 1062 // deopt in this case because we can't return a NaN. |
1069 if (right->CanBeZero()) { | 1063 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
1070 __ testl(right_reg, right_reg); | 1064 __ testl(right_reg, right_reg); |
1071 DeoptimizeIf(zero, instr->environment()); | 1065 DeoptimizeIf(zero, instr->environment()); |
1072 } | 1066 } |
1073 | 1067 |
1074 // Check for kMinInt % -1, idiv would signal a divide error. We | 1068 // Check for kMinInt % -1, idiv would signal a divide error. We |
1075 // have to deopt if we care about -0, because we can't return that. | 1069 // have to deopt if we care about -0, because we can't return that. |
1076 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { | 1070 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
1077 Label no_overflow_possible; | 1071 Label no_overflow_possible; |
1078 __ cmpl(left_reg, Immediate(kMinInt)); | 1072 __ cmpl(left_reg, Immediate(kMinInt)); |
1079 __ j(not_zero, &no_overflow_possible, Label::kNear); | 1073 __ j(not_zero, &no_overflow_possible, Label::kNear); |
1080 __ cmpl(right_reg, Immediate(-1)); | 1074 __ cmpl(right_reg, Immediate(-1)); |
1081 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1075 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1082 DeoptimizeIf(equal, instr->environment()); | 1076 DeoptimizeIf(equal, instr->environment()); |
1083 } else { | 1077 } else { |
1084 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1078 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1085 __ Set(result_reg, 0); | 1079 __ Set(result_reg, 0); |
1086 __ jmp(&done, Label::kNear); | 1080 __ jmp(&done, Label::kNear); |
1087 } | 1081 } |
1088 __ bind(&no_overflow_possible); | 1082 __ bind(&no_overflow_possible); |
1089 } | 1083 } |
1090 | 1084 |
1091 // Sign extend dividend in eax into edx:eax, since we are using only the low | 1085 // Sign extend dividend in eax into edx:eax, since we are using only the low |
1092 // 32 bits of the values. | 1086 // 32 bits of the values. |
1093 __ cdq(); | 1087 __ cdq(); |
1094 | 1088 |
1095 // If we care about -0, test if the dividend is <0 and the result is 0. | 1089 // If we care about -0, test if the dividend is <0 and the result is 0. |
1096 if (left->CanBeNegative() && | 1090 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1097 hmod->CanBeZero() && | |
1098 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1099 Label positive_left; | 1091 Label positive_left; |
1100 __ testl(left_reg, left_reg); | 1092 __ testl(left_reg, left_reg); |
1101 __ j(not_sign, &positive_left, Label::kNear); | 1093 __ j(not_sign, &positive_left, Label::kNear); |
1102 __ idivl(right_reg); | 1094 __ idivl(right_reg); |
1103 __ testl(result_reg, result_reg); | 1095 __ testl(result_reg, result_reg); |
1104 DeoptimizeIf(zero, instr->environment()); | 1096 DeoptimizeIf(zero, instr->environment()); |
1105 __ jmp(&done, Label::kNear); | 1097 __ jmp(&done, Label::kNear); |
1106 __ bind(&positive_left); | 1098 __ bind(&positive_left); |
1107 } | 1099 } |
1108 __ idivl(right_reg); | 1100 __ idivl(right_reg); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 int32_t divisor = instr->divisor(); | 1144 int32_t divisor = instr->divisor(); |
1153 ASSERT(ToRegister(instr->result()).is(rdx)); | 1145 ASSERT(ToRegister(instr->result()).is(rdx)); |
1154 | 1146 |
1155 if (divisor == 0) { | 1147 if (divisor == 0) { |
1156 DeoptimizeIf(no_condition, instr->environment()); | 1148 DeoptimizeIf(no_condition, instr->environment()); |
1157 return; | 1149 return; |
1158 } | 1150 } |
1159 | 1151 |
1160 // Check for (0 / -x) that will produce negative zero. | 1152 // Check for (0 / -x) that will produce negative zero. |
1161 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1153 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
1162 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1154 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1163 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
1164 __ testl(dividend, dividend); | 1155 __ testl(dividend, dividend); |
1165 DeoptimizeIf(zero, instr->environment()); | 1156 DeoptimizeIf(zero, instr->environment()); |
1166 } | 1157 } |
1167 | 1158 |
1168 __ FlooringDiv(dividend, divisor); | 1159 __ FlooringDiv(dividend, divisor); |
1169 } | 1160 } |
1170 | 1161 |
1171 | 1162 |
1172 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1163 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
1173 Register dividend = ToRegister(instr->dividend()); | 1164 Register dividend = ToRegister(instr->dividend()); |
1174 int32_t divisor = instr->divisor(); | 1165 int32_t divisor = instr->divisor(); |
1175 Register result = ToRegister(instr->result()); | 1166 Register result = ToRegister(instr->result()); |
1176 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); | 1167 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); |
1177 ASSERT(!result.is(dividend)); | 1168 ASSERT(!result.is(dividend)); |
1178 | 1169 |
1179 // Check for (0 / -x) that will produce negative zero. | 1170 // Check for (0 / -x) that will produce negative zero. |
1180 HDiv* hdiv = instr->hydrogen(); | 1171 HDiv* hdiv = instr->hydrogen(); |
1181 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1172 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1182 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
1183 __ testl(dividend, dividend); | 1173 __ testl(dividend, dividend); |
1184 DeoptimizeIf(zero, instr->environment()); | 1174 DeoptimizeIf(zero, instr->environment()); |
1185 } | 1175 } |
1186 // Check for (kMinInt / -1). | 1176 // Check for (kMinInt / -1). |
1187 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1177 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
1188 hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) { | |
1189 __ cmpl(dividend, Immediate(kMinInt)); | 1178 __ cmpl(dividend, Immediate(kMinInt)); |
1190 DeoptimizeIf(zero, instr->environment()); | 1179 DeoptimizeIf(zero, instr->environment()); |
1191 } | 1180 } |
1192 // Deoptimize if remainder will not be 0. | 1181 // Deoptimize if remainder will not be 0. |
1193 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1182 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
1194 divisor != 1 && divisor != -1) { | 1183 divisor != 1 && divisor != -1) { |
1195 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1184 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1196 __ testl(dividend, Immediate(mask)); | 1185 __ testl(dividend, Immediate(mask)); |
1197 DeoptimizeIf(not_zero, instr->environment()); | 1186 DeoptimizeIf(not_zero, instr->environment()); |
1198 } | 1187 } |
(...skipping 15 matching lines...) Expand all Loading... |
1214 int32_t divisor = instr->divisor(); | 1203 int32_t divisor = instr->divisor(); |
1215 ASSERT(ToRegister(instr->result()).is(rdx)); | 1204 ASSERT(ToRegister(instr->result()).is(rdx)); |
1216 | 1205 |
1217 if (divisor == 0) { | 1206 if (divisor == 0) { |
1218 DeoptimizeIf(no_condition, instr->environment()); | 1207 DeoptimizeIf(no_condition, instr->environment()); |
1219 return; | 1208 return; |
1220 } | 1209 } |
1221 | 1210 |
1222 // Check for (0 / -x) that will produce negative zero. | 1211 // Check for (0 / -x) that will produce negative zero. |
1223 HDiv* hdiv = instr->hydrogen(); | 1212 HDiv* hdiv = instr->hydrogen(); |
1224 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1213 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1225 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
1226 __ testl(dividend, dividend); | 1214 __ testl(dividend, dividend); |
1227 DeoptimizeIf(zero, instr->environment()); | 1215 DeoptimizeIf(zero, instr->environment()); |
1228 } | 1216 } |
1229 | 1217 |
1230 __ FlooringDiv(dividend, Abs(divisor)); | 1218 __ FlooringDiv(dividend, Abs(divisor)); |
1231 __ movl(rax, dividend); | 1219 __ movl(rax, dividend); |
1232 __ shrl(rax, Immediate(31)); | 1220 __ shrl(rax, Immediate(31)); |
1233 __ addl(rdx, rax); | 1221 __ addl(rdx, rax); |
1234 if (divisor < 0) __ neg(rdx); | 1222 if (divisor < 0) __ neg(rdx); |
1235 | 1223 |
1236 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1224 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
1237 __ movl(rax, rdx); | 1225 __ movl(rax, rdx); |
1238 __ imull(rax, rax, Immediate(divisor)); | 1226 __ imull(rax, rax, Immediate(divisor)); |
1239 __ subl(rax, dividend); | 1227 __ subl(rax, dividend); |
1240 DeoptimizeIf(not_equal, instr->environment()); | 1228 DeoptimizeIf(not_equal, instr->environment()); |
1241 } | 1229 } |
1242 } | 1230 } |
1243 | 1231 |
1244 | 1232 |
1245 void LCodeGen::DoDivI(LDivI* instr) { | 1233 void LCodeGen::DoDivI(LDivI* instr) { |
| 1234 HBinaryOperation* hdiv = instr->hydrogen(); |
1246 Register dividend = ToRegister(instr->left()); | 1235 Register dividend = ToRegister(instr->left()); |
1247 Register divisor = ToRegister(instr->right()); | 1236 Register divisor = ToRegister(instr->right()); |
1248 Register remainder = ToRegister(instr->temp()); | 1237 Register remainder = ToRegister(instr->temp()); |
1249 Register result = ToRegister(instr->result()); | 1238 Register result = ToRegister(instr->result()); |
1250 ASSERT(dividend.is(rax)); | 1239 ASSERT(dividend.is(rax)); |
1251 ASSERT(remainder.is(rdx)); | 1240 ASSERT(remainder.is(rdx)); |
1252 ASSERT(result.is(rax)); | 1241 ASSERT(result.is(rax)); |
1253 ASSERT(!divisor.is(rax)); | 1242 ASSERT(!divisor.is(rax)); |
1254 ASSERT(!divisor.is(rdx)); | 1243 ASSERT(!divisor.is(rdx)); |
1255 | 1244 |
1256 // Check for x / 0. | 1245 // Check for x / 0. |
1257 HBinaryOperation* hdiv = instr->hydrogen(); | |
1258 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1246 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1259 __ testl(divisor, divisor); | 1247 __ testl(divisor, divisor); |
1260 DeoptimizeIf(zero, instr->environment()); | 1248 DeoptimizeIf(zero, instr->environment()); |
1261 } | 1249 } |
1262 | 1250 |
1263 // Check for (0 / -x) that will produce negative zero. | 1251 // Check for (0 / -x) that will produce negative zero. |
1264 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1252 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1265 Label dividend_not_zero; | 1253 Label dividend_not_zero; |
1266 __ testl(dividend, dividend); | 1254 __ testl(dividend, dividend); |
1267 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1255 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
1268 __ testl(divisor, divisor); | 1256 __ testl(divisor, divisor); |
1269 DeoptimizeIf(sign, instr->environment()); | 1257 DeoptimizeIf(sign, instr->environment()); |
1270 __ bind(÷nd_not_zero); | 1258 __ bind(÷nd_not_zero); |
1271 } | 1259 } |
1272 | 1260 |
1273 // Check for (kMinInt / -1). | 1261 // Check for (kMinInt / -1). |
1274 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1262 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
1275 Label dividend_not_min_int; | 1263 Label dividend_not_min_int; |
1276 __ cmpl(dividend, Immediate(kMinInt)); | 1264 __ cmpl(dividend, Immediate(kMinInt)); |
1277 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1265 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
1278 __ cmpl(divisor, Immediate(-1)); | 1266 __ cmpl(divisor, Immediate(-1)); |
1279 DeoptimizeIf(zero, instr->environment()); | 1267 DeoptimizeIf(zero, instr->environment()); |
1280 __ bind(÷nd_not_min_int); | 1268 __ bind(÷nd_not_min_int); |
1281 } | 1269 } |
1282 | 1270 |
1283 // Sign extend to rdx (= remainder). | 1271 // Sign extend to rdx (= remainder). |
1284 __ cdq(); | 1272 __ cdq(); |
1285 __ idivl(divisor); | 1273 __ idivl(divisor); |
1286 | 1274 |
1287 if (instr->is_flooring()) { | 1275 if (hdiv->IsMathFloorOfDiv()) { |
1288 Label done; | 1276 Label done; |
1289 __ testl(remainder, remainder); | 1277 __ testl(remainder, remainder); |
1290 __ j(zero, &done, Label::kNear); | 1278 __ j(zero, &done, Label::kNear); |
1291 __ xorl(remainder, divisor); | 1279 __ xorl(remainder, divisor); |
1292 __ sarl(remainder, Immediate(31)); | 1280 __ sarl(remainder, Immediate(31)); |
1293 __ addl(result, remainder); | 1281 __ addl(result, remainder); |
1294 __ bind(&done); | 1282 __ bind(&done); |
1295 } else if (!instr->hydrogen()->CheckFlag( | 1283 } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
1296 HInstruction::kAllUsesTruncatingToInt32)) { | |
1297 // Deoptimize if remainder is not 0. | 1284 // Deoptimize if remainder is not 0. |
1298 __ testl(remainder, remainder); | 1285 __ testl(remainder, remainder); |
1299 DeoptimizeIf(not_zero, instr->environment()); | 1286 DeoptimizeIf(not_zero, instr->environment()); |
1300 } | 1287 } |
1301 } | 1288 } |
1302 | 1289 |
1303 | 1290 |
1304 void LCodeGen::DoMulI(LMulI* instr) { | 1291 void LCodeGen::DoMulI(LMulI* instr) { |
1305 Register left = ToRegister(instr->left()); | 1292 Register left = ToRegister(instr->left()); |
1306 LOperand* right = instr->right(); | 1293 LOperand* right = instr->right(); |
(...skipping 4359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5666 FixedArray::kHeaderSize - kPointerSize)); | 5653 FixedArray::kHeaderSize - kPointerSize)); |
5667 __ bind(&done); | 5654 __ bind(&done); |
5668 } | 5655 } |
5669 | 5656 |
5670 | 5657 |
5671 #undef __ | 5658 #undef __ |
5672 | 5659 |
5673 } } // namespace v8::internal | 5660 } } // namespace v8::internal |
5674 | 5661 |
5675 #endif // V8_TARGET_ARCH_X64 | 5662 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |