system888net 发表于 2008-05-06 21:00

编译器可以考虑的一个小小可能性

这段c代码

int test_int_mod()
{
unsigned int mode_u;
int mode_i;

int x;
unsigned int y;

x=99;
y=77;

x=(x+1)%64;
y=(y+1)%64;

x=(x+1)%32;
y=(y+1)%32;

mode_u=32;
mode_i=32;
x=(x+1)%mode_i;
y=(y+1)%mode_u;

mode_u=11;
mode_i=12;
x=(x+1)%mode_i;
y=(y+1)%mode_u;

return(x);
}


在VC6.0下被编译成了如下:

?test_int_mod@@YAHXZ PROC NEAR                                ; test_int_mod
        push        ebp
        mov        ebp, esp
        sub        esp, 16                                        ; 00000010H
        mov        DWORD PTR _x$, 99                        ; 00000063H
        mov        DWORD PTR _y$, 77                        ; 0000004dH
        mov        eax, DWORD PTR _x$
        add        eax, 1
        and        eax, -2147483585                        ; 8000003fH
        jns        SHORT $L69607
        dec        eax
        or        eax, -64                                ; ffffffc0H
        inc        eax
        mov        DWORD PTR _x$, eax
        mov        eax, DWORD PTR _y$
        add        eax, 1
        xor        edx, edx
        mov        ecx, 64                                        ; 00000040H
        div        ecx
        mov        DWORD PTR _y$, edx
        mov        edx, DWORD PTR _x$
        add        edx, 1
        and        edx, -2147483617                        ; 8000001fH
        jns        SHORT $L69608
        dec        edx
        or        edx, -32                                ; ffffffe0H
        inc        edx
        mov        DWORD PTR _x$, edx
        mov        eax, DWORD PTR _y$
        add        eax, 1
        xor        edx, edx
        mov        ecx, 32                                        ; 00000020H
        div        ecx
        mov        DWORD PTR _y$, edx
        mov        DWORD PTR _mode_u$, 32                ; 00000020H
        mov        DWORD PTR _mode_i$, 32                ; 00000020H
        mov        eax, DWORD PTR _x$
        add        eax, 1
        cdq
        idiv        DWORD PTR _mode_i$
        mov        DWORD PTR _x$, edx
        mov        eax, DWORD PTR _y$
        add        eax, 1
        xor        edx, edx
        div        DWORD PTR _mode_u$
        mov        DWORD PTR _y$, edx
        mov        DWORD PTR _mode_u$, 11                ; 0000000bH
        mov        DWORD PTR _mode_i$, 12                ; 0000000cH
        mov        eax, DWORD PTR _x$
        add        eax, 1
        cdq
        idiv        DWORD PTR _mode_i$
        mov        DWORD PTR _x$, edx
        mov        eax, DWORD PTR _y$
        add        eax, 1
        xor        edx, edx
        div        DWORD PTR _mode_u$
        mov        DWORD PTR _y$, edx
        mov        eax, DWORD PTR _x$
        mov        esp, ebp
        pop        ebp
        ret        0
?test_int_mod@@YAHXZ ENDP                                ; test_int_mod


其中不能针对mode_u变量的值做优化(gcc也类似问题),但对大家自己的特定编译器或虚拟机解释器在编译时则可考虑加入判断mode_u是不是2的次幂来做不同的处理的代码.
但对于边解释边运行的机制来说:这样一来判断能力mode_u是不是2的次幂 又要多出代码耗时了.
因此只能考虑编译型或伪编译性执行采用这样的建议.

Wind-Son 发表于 2008-05-06 22:31

不用细看,基于数值特征的优化基本上是费力不讨好。把这些交给程序员在他们真正需要优化的地方自己去解决更好。比如用移位和位逻辑运算代替乘除和求余。

下面这样的代码你认为应该被优化掉吗
int i, t1, t2;
i = 0;
t1 = i*3;
t2 = t1 * 4;

cjaizss 发表于 2008-05-06 22:51

:)
你认为以下代码:

#include <stdio.h>
int main()
{
      int i,j;
      for(i=0,j=0;i<10000;i++)
             j+=i;
      return 0;
}

应该被优化为以下吗?

.globl main
main:
      xorl    %eax, %eax
      ret

system888net 发表于 2008-05-06 23:51

2,3楼的观点是正确的!

我表述的有问题.
意思不是优化掉代码,而是根据输入值分支到相对合适的模块.

[ 本帖最后由 system888net 于 2008-5-6 23:57 编辑 ]

system888net 发表于 2008-05-07 00:01

原帖由 Wind-Son 于 2008-5-6 22:31 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
不用细看,基于数值特征的优化基本上是费力不讨好。把这些交给程序员在他们真正需要优化的地方自己去解决更好。比如用移位和位逻辑运算代替乘除和求余。

下面这样的代码你认为应该被优化掉吗
int i, t1, t2 ...


:smile:

可以优化为:
nt i, t1, t2;
i = 0;// ori=input();

if(i==0)
{
t1=0;
t2=0;
}
else
{
   t1 = i*3;
   t2 = t1 * 4;
}
对于虚拟机是有意义的

cjaizss 发表于 2008-05-07 00:37

我倒,为了一个乘法,居然加了个条件分支.........
有这么做的编译器?除了bt,我想不出来别的词语形容。
你说直接优化为
int i=0,t1=0,t2=0;
我还信。

cjaizss 发表于 2008-05-07 00:47

另外,X86上对于这种乘特殊数(一般比较小的数),可能会采取用寻址来实现乘法。
比如:
leal    (%eax,%eax,2), %eax
其实就是为了实现乘3
当然,这种类型优化体系结构相关

system888net 发表于 2008-05-07 00:48

原帖由 cjaizss 于 2008-5-7 00:37 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
我倒,为了一个乘法,居然加了个条件分支.........
有这么做的编译器?除了bt,我想不出来别的词语形容。
你说直接优化为
int i=0,t1=0,t2=0;
我还信。
:-)
nt i, t1, t2;
i = 0;// ori=input();

if(i==0)//对于用户i=input(); 多次输入的时候,i=0的特例虚拟机的确可以快速出结果.
{
t1=0;
t2=0;
}
else
{
   //假如这里有多次的运算..., 对于i=0用户的感觉虚拟机太苯了
   t1 = i*3;
   t2 = t1 * 4;
}

system888net 发表于 2008-05-07 00:49

原帖由 cjaizss 于 2008-5-7 00:47 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
另外,X86上对于这种乘特殊数(一般比较小的数),可能会采取用寻址来实现乘法。
比如:
leal    (%eax,%eax,2), %eax
其实就是为了实现乘3
当然,这种类型优化体系结构相关

这个观点同意

hzcgz 发表于 2008-05-07 08:09

原帖由 system888net 于 2008-5-7 00:48 发表 http://linux.chinaunix.net/bbs/images/common/back.gif

:-)
nt i, t1, t2;
i = 0;// ori=input();

if(i==0)//对于用户i=input(); 多次输入的时候,i=0的特例虚拟机的确可以快速出结果.
{
t1=0;
t2=0;
}
else
{
   //假如这里有多次的运算... ...
:shock: :shock: :shock:
页: [1] 2
查看完整版本: 编译器可以考虑的一个小小可能性