| 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));
|
| }
|
|
|