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

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

Issue 15769010: Improve code for integral modulus calculation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased. Created 7 years, 6 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/utils.h ('k') | src/x64/lithium-x64.cc » ('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 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 } 1025 }
1026 } 1026 }
1027 1027
1028 1028
1029 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1029 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1030 // Nothing to do. 1030 // Nothing to do.
1031 } 1031 }
1032 1032
1033 1033
1034 void LCodeGen::DoModI(LModI* instr) { 1034 void LCodeGen::DoModI(LModI* instr) {
1035 if (instr->hydrogen()->HasPowerOf2Divisor()) { 1035 HMod* hmod = instr->hydrogen();
1036 Register dividend = ToRegister(instr->left()); 1036 HValue* left = hmod->left();
1037 HValue* right = hmod->right();
1038 if (hmod->HasPowerOf2Divisor()) {
1039 // TODO(svenpanne) We should really do the strength reduction on the
1040 // Hydrogen level.
1041 Register left_reg = ToRegister(instr->left());
1042 ASSERT(left_reg.is(ToRegister(instr->result())));
1037 1043
1038 int32_t divisor = 1044 // Note: The code below even works when right contains kMinInt.
1039 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 1045 int32_t divisor = Abs(right->GetInteger32Constant());
1040 1046
1041 if (divisor < 0) divisor = -divisor; 1047 Label left_is_not_negative, done;
1042 1048 if (left->CanBeNegative()) {
1043 Label positive_dividend, done; 1049 __ testl(left_reg, left_reg);
1044 __ testl(dividend, dividend); 1050 __ j(not_sign, &left_is_not_negative, Label::kNear);
1045 __ j(not_sign, &positive_dividend, Label::kNear); 1051 __ negl(left_reg);
1046 __ negl(dividend); 1052 __ andl(left_reg, Immediate(divisor - 1));
1047 __ andl(dividend, Immediate(divisor - 1)); 1053 __ negl(left_reg);
1048 __ negl(dividend); 1054 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1049 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1055 DeoptimizeIf(zero, instr->environment());
1050 __ j(not_zero, &done, Label::kNear); 1056 }
1051 DeoptimizeIf(no_condition, instr->environment());
1052 } else {
1053 __ jmp(&done, Label::kNear); 1057 __ jmp(&done, Label::kNear);
1054 } 1058 }
1055 __ bind(&positive_dividend); 1059
1056 __ andl(dividend, Immediate(divisor - 1)); 1060 __ bind(&left_is_not_negative);
1061 __ andl(left_reg, Immediate(divisor - 1));
1057 __ bind(&done); 1062 __ bind(&done);
1063
1064 } else if (hmod->has_fixed_right_arg()) {
1065 Register left_reg = ToRegister(instr->left());
1066 ASSERT(left_reg.is(ToRegister(instr->result())));
1067 Register right_reg = ToRegister(instr->right());
1068
1069 int32_t divisor = hmod->fixed_right_arg_value();
1070 ASSERT(IsPowerOf2(divisor));
1071
1072 // Check if our assumption of a fixed right operand still holds.
1073 __ cmpl(right_reg, Immediate(divisor));
1074 DeoptimizeIf(not_equal, instr->environment());
1075
1076 Label left_is_not_negative, done;
1077 if (left->CanBeNegative()) {
1078 __ testl(left_reg, left_reg);
1079 __ j(not_sign, &left_is_not_negative, Label::kNear);
1080 __ negl(left_reg);
1081 __ andl(left_reg, Immediate(divisor - 1));
1082 __ negl(left_reg);
1083 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1084 DeoptimizeIf(zero, instr->environment());
1085 }
1086 __ jmp(&done, Label::kNear);
1087 }
1088
1089 __ bind(&left_is_not_negative);
1090 __ andl(left_reg, Immediate(divisor - 1));
1091 __ bind(&done);
1092
1058 } else { 1093 } else {
1059 Label done, remainder_eq_dividend, slow, both_positive;
1060 Register left_reg = ToRegister(instr->left()); 1094 Register left_reg = ToRegister(instr->left());
1095 ASSERT(left_reg.is(rax));
1061 Register right_reg = ToRegister(instr->right()); 1096 Register right_reg = ToRegister(instr->right());
1062 Register result_reg = ToRegister(instr->result());
1063
1064 ASSERT(left_reg.is(rax));
1065 ASSERT(result_reg.is(rdx));
1066 ASSERT(!right_reg.is(rax)); 1097 ASSERT(!right_reg.is(rax));
1067 ASSERT(!right_reg.is(rdx)); 1098 ASSERT(!right_reg.is(rdx));
1099 Register result_reg = ToRegister(instr->result());
1100 ASSERT(result_reg.is(rdx));
1068 1101
1069 // Check for x % 0. 1102 Label done;
1070 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1103 // Check for x % 0, idiv would signal a divide error. We have to
1104 // deopt in this case because we can't return a NaN.
1105 if (right->CanBeZero()) {
1071 __ testl(right_reg, right_reg); 1106 __ testl(right_reg, right_reg);
1072 DeoptimizeIf(zero, instr->environment()); 1107 DeoptimizeIf(zero, instr->environment());
1073 } 1108 }
1074 1109
1075 __ testl(left_reg, left_reg); 1110 // Check for kMinInt % -1, idiv would signal a divide error. We
1076 __ j(zero, &remainder_eq_dividend, Label::kNear); 1111 // have to deopt if we care about -0, because we can't return that.
1077 __ j(sign, &slow, Label::kNear); 1112 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
1078 1113 Label no_overflow_possible;
1079 __ testl(right_reg, right_reg);
1080 __ j(not_sign, &both_positive, Label::kNear);
1081 // The sign of the divisor doesn't matter.
1082 __ neg(right_reg);
1083
1084 __ bind(&both_positive);
1085 // If the dividend is smaller than the nonnegative
1086 // divisor, the dividend is the result.
1087 __ cmpl(left_reg, right_reg);
1088 __ j(less, &remainder_eq_dividend, Label::kNear);
1089
1090 // Check if the divisor is a PowerOfTwo integer.
1091 Register scratch = ToRegister(instr->temp());
1092 __ movl(scratch, right_reg);
1093 __ subl(scratch, Immediate(1));
1094 __ testl(scratch, right_reg);
1095 __ j(not_zero, &slow, Label::kNear);
1096 __ andl(left_reg, scratch);
1097 __ jmp(&remainder_eq_dividend, Label::kNear);
1098
1099 // Slow case, using idiv instruction.
1100 __ bind(&slow);
1101
1102 // Check for (kMinInt % -1).
1103 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1104 Label left_not_min_int;
1105 __ cmpl(left_reg, Immediate(kMinInt)); 1114 __ cmpl(left_reg, Immediate(kMinInt));
1106 __ j(not_zero, &left_not_min_int, Label::kNear); 1115 __ j(not_zero, &no_overflow_possible, Label::kNear);
1107 __ cmpl(right_reg, Immediate(-1)); 1116 __ cmpl(right_reg, Immediate(-1));
1108 DeoptimizeIf(zero, instr->environment()); 1117 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1109 __ bind(&left_not_min_int); 1118 DeoptimizeIf(equal, instr->environment());
1119 } else {
1120 __ j(not_equal, &no_overflow_possible, Label::kNear);
1121 __ Set(result_reg, 0);
1122 __ jmp(&done, Label::kNear);
1123 }
1124 __ bind(&no_overflow_possible);
1110 } 1125 }
1111 1126
1112 // Sign extend eax to edx. 1127 // Sign extend dividend in eax into edx:eax, since we are using only the low
1113 // (We are using only the low 32 bits of the values.) 1128 // 32 bits of the values.
1114 __ cdq(); 1129 __ cdq();
1115 1130
1116 // Check for (0 % -x) that will produce negative zero. 1131 // If we care about -0, test if the dividend is <0 and the result is 0.
1117 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1132 if (left->CanBeNegative() &&
1133 hmod->CanBeZero() &&
1134 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1118 Label positive_left; 1135 Label positive_left;
1119 Label done;
1120 __ testl(left_reg, left_reg); 1136 __ testl(left_reg, left_reg);
1121 __ j(not_sign, &positive_left, Label::kNear); 1137 __ j(not_sign, &positive_left, Label::kNear);
1122 __ idivl(right_reg); 1138 __ idivl(right_reg);
1123
1124 // Test the remainder for 0, because then the result would be -0.
1125 __ testl(result_reg, result_reg); 1139 __ testl(result_reg, result_reg);
1126 __ j(not_zero, &done, Label::kNear); 1140 DeoptimizeIf(zero, instr->environment());
1127 1141 __ jmp(&done, Label::kNear);
1128 DeoptimizeIf(no_condition, instr->environment());
1129 __ bind(&positive_left); 1142 __ bind(&positive_left);
1130 __ idivl(right_reg);
1131 __ bind(&done);
1132 } else {
1133 __ idivl(right_reg);
1134 } 1143 }
1135 __ jmp(&done, Label::kNear); 1144 __ idivl(right_reg);
1136
1137 __ bind(&remainder_eq_dividend);
1138 __ movl(result_reg, left_reg);
1139
1140 __ bind(&done); 1145 __ bind(&done);
1141 } 1146 }
1142 } 1147 }
1143 1148
1144 1149
1145 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { 1150 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
1146 ASSERT(instr->right()->IsConstantOperand()); 1151 ASSERT(instr->right()->IsConstantOperand());
1147 1152
1148 const Register dividend = ToRegister(instr->left()); 1153 const Register dividend = ToRegister(instr->left());
1149 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); 1154 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
(...skipping 4442 matching lines...) Expand 10 before | Expand all | Expand 10 after
5592 FixedArray::kHeaderSize - kPointerSize)); 5597 FixedArray::kHeaderSize - kPointerSize));
5593 __ bind(&done); 5598 __ bind(&done);
5594 } 5599 }
5595 5600
5596 5601
5597 #undef __ 5602 #undef __
5598 5603
5599 } } // namespace v8::internal 5604 } } // namespace v8::internal
5600 5605
5601 #endif // V8_TARGET_ARCH_X64 5606 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/utils.h ('k') | src/x64/lithium-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698