Index: src/ia32/lithium-codegen-ia32.cc |
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc |
index 28f4679a41cf5e7c37fc7545a0283bdceac37271..fceadd6fc761e775e25b0e989ac7581765fdf06a 100644 |
--- a/src/ia32/lithium-codegen-ia32.cc |
+++ b/src/ia32/lithium-codegen-ia32.cc |
@@ -875,7 +875,49 @@ void LCodeGen::DoMulI(LMulI* instr) { |
} |
if (right->IsConstantOperand()) { |
- __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); |
+ // Try strength reductions on the multiplication. |
+ // All replacement instructions are at most as long as the imul |
+ // and have better latency. |
+ int constant = ToInteger32(LConstantOperand::cast(right)); |
+ if (constant == -1) { |
+ __ neg(left); |
+ } else if (constant == 0) { |
+ __ xor_(left, Operand(left)); |
+ } else if (constant == 2) { |
+ __ add(left, Operand(left)); |
+ } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
+ // If we know that the multiplication can't overflow, it's safe to |
+ // use instructions that don't set the overflow flag for the |
+ // multiplication. |
+ switch (constant) { |
+ case 1: |
+ // Do nothing. |
+ break; |
+ case 3: |
+ __ lea(left, Operand(left, left, times_2, 0)); |
+ break; |
+ case 4: |
+ __ shl(left, 2); |
+ break; |
+ case 5: |
+ __ lea(left, Operand(left, left, times_4, 0)); |
+ break; |
+ case 8: |
+ __ shl(left, 3); |
+ break; |
+ case 9: |
+ __ lea(left, Operand(left, left, times_8, 0)); |
+ break; |
+ case 16: |
+ __ shl(left, 4); |
+ break; |
+ default: |
+ __ imul(left, left, constant); |
+ break; |
+ } |
+ } else { |
+ __ imul(left, left, constant); |
+ } |
} else { |
__ imul(left, ToOperand(right)); |
} |