Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does GCC generate different opcodes for multiplication based on a value of the constant?

I was playing around with GCC disassembler on gcc.godbolt.org and I noticed that GCC starting version 4.6 compiles multiplication differently. I have the following two functions:

unsigned m126(unsigned i)
{
    return i * 126;
}

unsigned m131(unsigned i)
{
    return i * 131;
}

m126 compiles into:

mov eax, edi
mov edx, 126
imul eax, edx
ret

And m131 compiles into:

imul eax, edi, 131
ret

Why is the difference? GCC 4.5 generates the same opcode in both cases.

A link to the actual example on GCC Explorer.

like image 562
detunized Avatar asked Dec 20 '12 16:12

detunized


People also ask

Is multiplication or division faster Python?

Multiplication is usually faster - certainly never slower. However, if it is not speed critical, write whichever is clearest. Save this answer.

How slow is multiplication vs division?

And the results (see the comments) are similar to that of Intel: division is about 3-6 times slower than multiplication.

Is division slower than multiplication Java?

It used to be that both multiplication and division were slow operations. Nowadays multiplication is a bit faster (but slightly slower than addition/subtraction), but division still is slower than the others. I believe Newton-Raphson is still used internally by most for reciprocating a number. – J. M.

What branch of science which multiplication is the same thing as division?

Biology is the only science in which multiplication is the same thing as division.


1 Answers

Found this in gcc/config/i386/i386.md (see the comment on the top):

;; imul $8/16bit_imm, regmem, reg is vector decoded.
;; Convert it into imul reg, reg
;; It would be better to force assembler to encode instruction using long
;; immediate, but there is apparently no way to do so.
(define_peephole2
  [(parallel [(set (match_operand:SWI248 0 "register_operand")
           (mult:SWI248
            (match_operand:SWI248 1 "nonimmediate_operand")
            (match_operand:SWI248 2 "const_int_operand")))
          (clobber (reg:CC FLAGS_REG))])
   (match_scratch:SWI248 3 "r")]
  "TARGET_SLOW_IMUL_IMM8 && optimize_insn_for_speed_p ()
   && satisfies_constraint_K (operands[2])"
  [(set (match_dup 3) (match_dup 2))
   (parallel [(set (match_dup 0) (mult:SWI248 (match_dup 0) (match_dup 3)))
          (clobber (reg:CC FLAGS_REG))])]
{
  if (!rtx_equal_p (operands[0], operands[1]))
    emit_move_insn (operands[0], operands[1]);
})

Seems like it has something to do with instruction decoding (sorry I'm not an expert)

like image 98
szx Avatar answered Sep 20 '22 11:09

szx