Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index 9cd0c1c51ec4a4cd5423758558d81a6a03489a42..1f6192f0a51129017e53fd3af4c815362121a1f1 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -864,16 +864,56 @@ void LCodeGen::DoMulI(LMulI* instr) { |
__ movl(kScratchRegister, left); |
} |
+ bool can_overflow = |
+ instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
if (right->IsConstantOperand()) { |
int right_value = ToInteger32(LConstantOperand::cast(right)); |
- __ imull(left, left, Immediate(right_value)); |
+ if (right_value == -1) { |
+ __ negl(left); |
+ } else if (right_value == 0) { |
William Hesse
2011/03/17 12:55:06
If BailoutOnMinusZero is true, we always bail out
Lasse Reichstein
2011/03/17 18:11:55
Yes, I noticed too that we bail out even if we don
|
+ __ xorl(left, left); |
+ } else if (right_value == 2) { |
+ __ addl(left, left); |
+ } else if (!can_overflow) { |
+ // If the multiplication is known to not overflow, we |
+ // can use operations that don't set the overflow flag |
+ // correctly. |
+ switch (right_value) { |
+ case 1: |
+ // Do nothing. |
+ break; |
+ case 3: |
+ __ leal(left, Operand(left, left, times_2, 0)); |
+ break; |
+ case 4: |
+ __ shll(left, Immediate(2)); |
+ break; |
+ case 5: |
+ __ leal(left, Operand(left, left, times_4, 0)); |
+ break; |
+ case 8: |
+ __ shll(left, Immediate(3)); |
+ break; |
+ case 9: |
+ __ leal(left, Operand(left, left, times_8, 0)); |
+ break; |
+ case 16: |
+ __ shll(left, Immediate(4)); |
+ break; |
+ default: |
+ __ imull(left, left, Immediate(right_value)); |
+ break; |
+ } |
+ } else { |
+ __ imull(left, left, Immediate(right_value)); |
+ } |
} else if (right->IsStackSlot()) { |
__ imull(left, ToOperand(right)); |
} else { |
__ imull(left, ToRegister(right)); |
} |
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
+ if (can_overflow) { |
DeoptimizeIf(overflow, instr->environment()); |
} |