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

Unified Diff: src/arm/lithium-codegen-arm.cc

Issue 6756033: ARM: Add optimization for constant RHS in DoMulI (try 2) (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/arm/macro-assembler-arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm/lithium-codegen-arm.cc
===================================================================
--- src/arm/lithium-codegen-arm.cc (revision 7433)
+++ src/arm/lithium-codegen-arm.cc (working copy)
@@ -1042,40 +1042,130 @@
void LCodeGen::DoMulI(LMulI* instr) {
+ LOperand* left_op = instr->InputAt(0);
+ LOperand* right_op = instr->InputAt(1);
+
Register scratch = scratch0();
- Register left = ToRegister(instr->InputAt(0));
- Register right = EmitLoadRegister(instr->InputAt(1), scratch);
+ Register left = ToRegister(left_op);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
- !instr->InputAt(1)->IsConstantOperand()) {
- __ orr(ToRegister(instr->TempAt(0)), left, right);
- }
+ ASSERT(left_op->Equals(instr->result()));
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
- // scratch:left = left * right.
- __ smull(left, scratch, left, right);
- __ mov(ip, Operand(left, ASR, 31));
- __ cmp(ip, Operand(scratch));
- DeoptimizeIf(ne, instr->environment());
+ bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+ bool bailout_on_minus_zero =
+ instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
+
+ if (right_op->IsConstantOperand()) {
+ // Use optimized code for specific constants.
+ int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
+ Condition overflow_deopt_cond = kNoCondition;
+
+ switch (constant) {
+ case -1:
+ overflow_deopt_cond = can_overflow ? vs : kNoCondition;
+ __ rsb(left,
+ left,
+ Operand(0),
+ can_overflow ? SetCC : LeaveCC);
+ break;
+ case 0:
+ if (bailout_on_minus_zero) {
+ // If left is strictly negative and the constant is null, the
+ // result is -0. Deoptimize if required, otherwise return 0.
+ __ cmp(left, Operand(0));
+ DeoptimizeIf(mi, instr->environment());
+ }
+ __ mov(left, Operand(0));
+ break;
+ case 1:
+ // Do nothing.
+ break;
+ default:
+ // Multiplying by powers of two and powers of two plus or minus
+ // one can be done faster with shifted operands.
+ // For other constants we emit standard code.
+ int32_t mask = constant >> 31;
+ uint32_t constant_abs = (constant + mask) ^ mask;
+
+ if (IsPowerOf2(constant_abs)) {
+ if (!can_overflow) {
+ int32_t shift = WhichPowerOf2(constant_abs);
+ __ mov(left, Operand(left, LSL, shift));
+ if (constant < 0) __ rsb(left, left, Operand(0));
+ } else {
+ // scratch:left = left * constant.
+ __ mov(ip, Operand(constant));
+ __ smull(left, scratch, left, ip);
+ __ cmp(scratch, Operand(left, ASR, 31));
+ overflow_deopt_cond = ne;
+ }
+ } else if (IsPowerOf2(constant_abs - 1)) {
+ int32_t shift = WhichPowerOf2(constant_abs - 1);
+ __ add(left,
+ left,
+ Operand(left, LSL, shift),
+ can_overflow ? SetCC : LeaveCC);
+ overflow_deopt_cond = can_overflow ? vs : kNoCondition;
+ if (constant < 0) __ rsb(left, left, Operand(0));
+ } else if (IsPowerOf2(constant_abs + 1)) {
+ int32_t shift = WhichPowerOf2(constant_abs + 1);
+ __ rsb(left,
+ left,
+ Operand(left, LSL, shift),
+ can_overflow ? SetCC : LeaveCC);
+ overflow_deopt_cond = can_overflow ? vs : kNoCondition;
+ if (constant < 0) __ rsb(left, left, Operand(0));
+ } else {
+ if (!can_overflow) {
+ __ mov(ip, Operand(constant));
+ __ mul(left, left, ip);
+ } else {
+ // scratch:left = left * constant.
+ __ mov(ip, Operand(constant));
+ __ smull(left, scratch, left, ip);
+ __ cmp(scratch, Operand(left, ASR, 31));
+ overflow_deopt_cond = ne;
+ }
+ }
+ break;
+ }
+
+
+ if (can_overflow && (constant != 0) && (constant != 1)) {
+ ASSERT(overflow_deopt_cond != kNoCondition);
+ DeoptimizeIf(overflow_deopt_cond, instr->environment());
+ }
+
+ if (bailout_on_minus_zero && (constant < 0)) {
+ // The case of a null constant was handled separately.
+ // If constant is negative and left is null, the result should be -0.
+ __ cmp(left, Operand(0));
+ DeoptimizeIf(eq, instr->environment());
+ }
+
} else {
- __ mul(left, left, right);
- }
+ Register right = EmitLoadRegister(right_op, scratch);
+ if (bailout_on_minus_zero) {
+ __ orr(ToRegister(instr->TempAt(0)), left, right);
+ }
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- // Bail out if the result is supposed to be negative zero.
- Label done;
- __ cmp(left, Operand(0));
- __ b(ne, &done);
- if (instr->InputAt(1)->IsConstantOperand()) {
- if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
- DeoptimizeIf(al, instr->environment());
- }
+ if (can_overflow) {
+ // scratch:left = left * right.
+ __ smull(left, scratch, left, right);
+ __ cmp(scratch, Operand(left, ASR, 31));
+ DeoptimizeIf(ne, instr->environment());
} else {
- // Test the non-zero operand for negative sign.
+ __ mul(left, left, right);
+ }
+
+ if (bailout_on_minus_zero) {
+ // Bail out if the result is supposed to be negative zero.
+ Label done;
+ __ cmp(left, Operand(0));
+ __ b(ne, &done);
__ cmp(ToRegister(instr->TempAt(0)), Operand(0));
DeoptimizeIf(mi, instr->environment());
+ __ bind(&done);
}
- __ bind(&done);
}
}
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/arm/macro-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698