GCC ARM乘法优化

时间:2018-12-18 08:31:31

标签: assembly compiler-construction arm compiler-optimization

我正在阅读有关ALU设计和Booth's algorithm的信息,它们用于优化二进制乘法。令我好奇的是,像gcc这样的编译器将如何优化乘法,因为乘法运算的速度不如ARM 32bit这样的移位快。这是尝试将变量乘以0xaaa(这是Booth算法的最坏情况)时获得的ASM:

    mov     r2, r3      // r3 is an arbitrary variable
    lsl     r2, r2, #1
    add     r2, r2, r3
    lsl     r3, r2, #3
    sub     r3, r3, r2
    lsl     r2, r3, #6
    add     r3, r3, r2
    lsl     r3, r3, #1

我似乎无法掌握产生以下输出的任何模式或规则。我想看一下gcc的源代码,但我不知道在哪里查找。有人可以阐明什么是算法,以及如何将其推广到任何乘数?

2 个答案:

答案 0 :(得分:3)

您发布的程序集不是广义乘数-编译器已离线执行了一些算法,并对固定f(X) = X * 0xaaa计算所需的常数和算术运算进行了硬编码。

mov     r2, r3      // r2 = X, r3 = X
lsl     r2, r2, #1  // r2 = 2 * X
add     r2, r2, r3  // r2 = 2X + X = 3X
lsl     r3, r2, #3  // r3 = 8 * 3X = 24X
sub     r3, r3, r2  // r3 = 24X - 3X = 21X
lsl     r2, r3, #6  // r2 = 64 * 21X = 1344X
add     r3, r3, r2  // r3 = 21X + 1344X = 1365X
lsl     r3, r3, #1  // r3 = 2 * 1365 = 2730X = 0xAAA * X

在这种情况下,编译器不需要使用通用的乘法算法,例如Booth的算法。它知道它要达到的目标值,因此它只是预先确定通过0xAAA使用移位,加法和减法来生成恒定缩放的最佳方法。

一般的问题是“单常数乘法”问题-在线有论文(针对任意位数的最佳解决方案是“硬”问题,因此有很多研究论文)。

答案 1 :(得分:1)

基本乘法,并非您发现的所有内容都将使用某人将其名字放在上面的算法。

十进制

33 * 12

  33
* 12
=====
  66  ((33*2)<<0)
+33   ((33*1)<<1)
========

base 2具有第二个操作数可以包含零或一的特征

0b110 * 0b101

    110
*   101
=========   
    110     ((110*1)<<0)
   000      ((110*0)<<1)
+ 110       ((110*1)<<2)
===========

重要的是非零位。所以乘以五就是

x * 5 =(x * 4)+(x * 1)=(x << 2)+ x =((x + x)<< 1)+ x =((x << 1)<< 1)+ x

x * 10只是再左移一次。 x * 10 =(x * 8)+(x * 2)=((x + x)<< 1)+ x)<< 1

依此类推,您可以玩游戏,但是您希望针对目标架构进行优化。

0xAAA =(0x5 << 9)+(0x5 << 5)+(0x5 << 1)或(1 << 11)+(1 << 9)+(1 << 7)+(1 < <5)+(1 << 3)+(1 << 1)

从那里进行优化的各种方法。