为什么GCC针对常量的不同值生成不同的乘法操作码?

14

我在gcc.godbolt.org上尝试使用GCC反汇编器,注意到从4.6版本开始,GCC对乘法的编译方式有所不同。以下是我的两个函数:

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

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

m126 编译后的结果是:

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

m131 编译成:

imul eax, edi, 131
ret

为什么会有差异?GCC 4.5在两种情况下生成相同的操作码。

这是 GCC Explorer 上实际示例的链接


1
因为如果数字超过有符号字节的最大值,它会生成不同的代码。 - tckmn
@Doorknob:这是一个有趣的假设,为什么需要这样做呢? - NPE
@Doorknob:没错,我没有注意到。我只是考虑跨越8位边界。这样做更有效率或更紧凑吗? - detunized
它肯定不更紧凑(我已经检查了机器代码)。我也不明白为什么它会更有效率。 - NPE
mov edx,126 不只使用“一个字节的常量”吗?如果是这样,那么与 imul eax, edi, 126 的 32 位常量相比,它可能会短一个字节。 - Mats Petersson
gcc 4.7.2 (-O3) 对于两个函数使用相同的指令序列:imull $126, 4(%esp), %eaximull $131, 4(%esp), %eax - ouah
1个回答

10

gcc/config/i386/i386.md中发现了这个(请参见顶部的注释):

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

似乎与指令解码有关(抱歉我不是专家)


这似乎与此相关。但我并不真正理解这段代码如何解释差异。 - detunized
经过一段时间的学习,它开始变得有意义了。当定义了TARGET_SLOW_IMUL_IMM8并且satisfies_constraint_K为真(在constrains.md中定义,表示常量在[-128, 127]范围内),它将用三个指令组合替换三操作数的imul。看起来,在某些CPU上,带有imm8imul可能会很慢。 - detunized
i386.c 中有一段代码,其中写着:/* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD machines. */ m_CORE2I7 | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC64。现在它有点意义了。谢谢。 - detunized

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接