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

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. ia32/x64/ARM done, MIPS restructured. 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
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 1027 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 } 1038 }
1039 } 1039 }
1040 1040
1041 1041
1042 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1042 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1043 // Nothing to do. 1043 // Nothing to do.
1044 } 1044 }
1045 1045
1046 1046
1047 void LCodeGen::DoModI(LModI* instr) { 1047 void LCodeGen::DoModI(LModI* instr) {
1048 if (instr->hydrogen()->HasPowerOf2Divisor()) { 1048 HMod* hmod = instr->hydrogen();
1049 Register dividend = ToRegister(instr->left()); 1049 HValue* left = hmod->left();
1050 HValue* right = hmod->right();
1051 if (hmod->HasPowerOf2Divisor()) {
1052 // TODO(svenpanne) We should really do the strength reduction on the
1053 // Hydrogen level.
1054 Register left_reg = ToRegister(instr->left());
1055 ASSERT(left_reg.is(ToRegister(instr->result())));
1050 1056
1051 int32_t divisor = 1057 int32_t divisor = Abs(right->GetInteger32Constant());
1052 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
1053 1058
1054 if (divisor < 0) divisor = -divisor; 1059 Label left_is_not_negative, done;
1055 1060 if (left->CanBeNegative()) {
1056 Label positive_dividend, done; 1061 __ testl(left_reg, left_reg);
1057 __ testl(dividend, dividend); 1062 __ j(not_sign, &left_is_not_negative, Label::kNear);
1058 __ j(not_sign, &positive_dividend, Label::kNear); 1063 __ negl(left_reg);
1059 __ negl(dividend); 1064 __ andl(left_reg, Immediate(divisor - 1));
1060 __ andl(dividend, Immediate(divisor - 1)); 1065 __ negl(left_reg);
1061 __ negl(dividend); 1066 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1062 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1067 DeoptimizeIf(zero, instr->environment());
1063 __ j(not_zero, &done, Label::kNear); 1068 }
1064 DeoptimizeIf(no_condition, instr->environment());
1065 } else {
1066 __ jmp(&done, Label::kNear); 1069 __ jmp(&done, Label::kNear);
1067 } 1070 }
1068 __ bind(&positive_dividend); 1071
1069 __ andl(dividend, Immediate(divisor - 1)); 1072 __ bind(&left_is_not_negative);
1073 __ andl(left_reg, Immediate(divisor - 1));
1070 __ bind(&done); 1074 __ bind(&done);
1075
1076 } else if (hmod->has_fixed_right_arg()) {
1077 Register left_reg = ToRegister(instr->left());
1078 ASSERT(left_reg.is(ToRegister(instr->result())));
1079 Register right_reg = ToRegister(instr->right());
1080
1081 int32_t divisor = hmod->fixed_right_arg_value();
1082 ASSERT(IsPowerOf2(divisor));
1083
1084 // Check if our assumption of a fixed right operand still holds.
1085 __ cmpl(right_reg, Immediate(divisor));
1086 DeoptimizeIf(not_equal, instr->environment());
1087
1088 Label left_is_not_negative, done;
1089 if (left->CanBeNegative()) {
1090 __ testl(left_reg, left_reg);
1091 __ j(not_sign, &left_is_not_negative, Label::kNear);
1092 __ negl(left_reg);
1093 __ andl(left_reg, Immediate(divisor - 1));
1094 __ negl(left_reg);
1095 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1096 DeoptimizeIf(zero, instr->environment());
1097 }
1098 __ jmp(&done, Label::kNear);
1099 }
1100
1101 __ bind(&left_is_not_negative);
1102 __ andl(left_reg, Immediate(divisor - 1));
1103 __ bind(&done);
1104
1071 } else { 1105 } else {
1072 Label done, remainder_eq_dividend, slow, both_positive;
1073 Register left_reg = ToRegister(instr->left()); 1106 Register left_reg = ToRegister(instr->left());
1107 ASSERT(left_reg.is(rax));
1074 Register right_reg = ToRegister(instr->right()); 1108 Register right_reg = ToRegister(instr->right());
1075 Register result_reg = ToRegister(instr->result());
1076
1077 ASSERT(left_reg.is(rax));
1078 ASSERT(result_reg.is(rdx));
1079 ASSERT(!right_reg.is(rax)); 1109 ASSERT(!right_reg.is(rax));
1080 ASSERT(!right_reg.is(rdx)); 1110 ASSERT(!right_reg.is(rdx));
1111 Register result_reg = ToRegister(instr->result());
1112 ASSERT(result_reg.is(rdx));
1081 1113
1082 // Check for x % 0. 1114 Label done;
1083 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1115 // Check for x % 0, idiv would signal a divide error. We have to
1116 // deopt in this case because we can't return a NaN.
1117 if (right->CanBeZero()) {
1084 __ testl(right_reg, right_reg); 1118 __ testl(right_reg, right_reg);
1085 DeoptimizeIf(zero, instr->environment()); 1119 DeoptimizeIf(zero, instr->environment());
1086 } 1120 }
1087 1121
1088 __ testl(left_reg, left_reg); 1122 // Check for kMinInt % -1, idiv would signal a divide error. We
1089 __ j(zero, &remainder_eq_dividend, Label::kNear); 1123 // have to deopt if we care about -0, because we can't return that.
1090 __ j(sign, &slow, Label::kNear); 1124 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
1091 1125 Label no_overflow_possible;
1092 __ testl(right_reg, right_reg);
1093 __ j(not_sign, &both_positive, Label::kNear);
1094 // The sign of the divisor doesn't matter.
1095 __ neg(right_reg);
1096
1097 __ bind(&both_positive);
1098 // If the dividend is smaller than the nonnegative
1099 // divisor, the dividend is the result.
1100 __ cmpl(left_reg, right_reg);
1101 __ j(less, &remainder_eq_dividend, Label::kNear);
1102
1103 // Check if the divisor is a PowerOfTwo integer.
1104 Register scratch = ToRegister(instr->temp());
1105 __ movl(scratch, right_reg);
1106 __ subl(scratch, Immediate(1));
1107 __ testl(scratch, right_reg);
1108 __ j(not_zero, &slow, Label::kNear);
1109 __ andl(left_reg, scratch);
1110 __ jmp(&remainder_eq_dividend, Label::kNear);
1111
1112 // Slow case, using idiv instruction.
1113 __ bind(&slow);
1114
1115 // Check for (kMinInt % -1).
1116 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1117 Label left_not_min_int;
1118 __ cmpl(left_reg, Immediate(kMinInt)); 1126 __ cmpl(left_reg, Immediate(kMinInt));
1119 __ j(not_zero, &left_not_min_int, Label::kNear); 1127 __ j(not_zero, &no_overflow_possible, Label::kNear);
1120 __ cmpl(right_reg, Immediate(-1)); 1128 __ cmpl(right_reg, Immediate(-1));
1121 DeoptimizeIf(zero, instr->environment()); 1129 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1122 __ bind(&left_not_min_int); 1130 DeoptimizeIf(equal, instr->environment());
1131 } else {
1132 __ j(not_equal, &no_overflow_possible, Label::kNear);
1133 __ Set(result_reg, 0);
1134 __ jmp(&done, Label::kNear);
1135 }
1136 __ bind(&no_overflow_possible);
1123 } 1137 }
1124 1138
1125 // Sign extend eax to edx. 1139 // Sign extend dividend in eax into edx:eax, since we are using only the low
1126 // (We are using only the low 32 bits of the values.) 1140 // 32 bits of the values.
1127 __ cdq(); 1141 __ cdq();
1128 1142
1129 // Check for (0 % -x) that will produce negative zero. 1143 // If we care about -0, test if the dividend is <0 and the result is 0.
1130 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1144 if (left->CanBeNegative() &&
1145 hmod->CanBeZero() &&
1146 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1131 Label positive_left; 1147 Label positive_left;
1132 Label done;
1133 __ testl(left_reg, left_reg); 1148 __ testl(left_reg, left_reg);
1134 __ j(not_sign, &positive_left, Label::kNear); 1149 __ j(not_sign, &positive_left, Label::kNear);
1135 __ idivl(right_reg); 1150 __ idivl(right_reg);
1136
1137 // Test the remainder for 0, because then the result would be -0.
1138 __ testl(result_reg, result_reg); 1151 __ testl(result_reg, result_reg);
1139 __ j(not_zero, &done, Label::kNear); 1152 DeoptimizeIf(zero, instr->environment());
1140 1153 __ jmp(&done, Label::kNear);
1141 DeoptimizeIf(no_condition, instr->environment());
1142 __ bind(&positive_left); 1154 __ bind(&positive_left);
1143 __ idivl(right_reg);
1144 __ bind(&done);
1145 } else {
1146 __ idivl(right_reg);
1147 } 1155 }
1148 __ jmp(&done, Label::kNear); 1156 __ idivl(right_reg);
1149
1150 __ bind(&remainder_eq_dividend);
1151 __ movl(result_reg, left_reg);
1152
1153 __ bind(&done); 1157 __ bind(&done);
1154 } 1158 }
1155 } 1159 }
1156 1160
1157 1161
1158 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { 1162 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
1159 ASSERT(instr->right()->IsConstantOperand()); 1163 ASSERT(instr->right()->IsConstantOperand());
1160 1164
1161 const Register dividend = ToRegister(instr->left()); 1165 const Register dividend = ToRegister(instr->left());
1162 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); 1166 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
(...skipping 4449 matching lines...) Expand 10 before | Expand all | Expand 10 after
5612 FixedArray::kHeaderSize - kPointerSize)); 5616 FixedArray::kHeaderSize - kPointerSize));
5613 __ bind(&done); 5617 __ bind(&done);
5614 } 5618 }
5615 5619
5616 5620
5617 #undef __ 5621 #undef __
5618 5622
5619 } } // namespace v8::internal 5623 } } // namespace v8::internal
5620 5624
5621 #endif // V8_TARGET_ARCH_X64 5625 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/ia32/lithium-codegen-ia32.cc ('K') | « src/utils.h ('k') | src/x64/lithium-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698