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

发布于 2022-09-18 22:34:26 字数 7844 浏览 30 评论 0

这段c代码

  1. int test_int_mod()
  2. {
  3.   unsigned int mode_u;
  4.   int mode_i;
  5.   
  6.   int x;
  7.   unsigned int y;
  8.   x=99;
  9.   y=77;
  10.   x=(x+1)%64;
  11.   y=(y+1)%64;
  12.   
  13.   x=(x+1)%32;
  14.   y=(y+1)%32;
  15.   mode_u=32;
  16.   mode_i=32;
  17.   x=(x+1)%mode_i;
  18.   y=(y+1)%mode_u;
  19.   mode_u=11;
  20.   mode_i=12;
  21.   x=(x+1)%mode_i;
  22.   y=(y+1)%mode_u;
  23.   
  24.   return(x);
  25. }

复制代码

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

  1. ?test_int_mod@@YAHXZ PROC NEAR                                ; test_int_mod
  2.         push        ebp
  3.         mov        ebp, esp
  4.         sub        esp, 16                                        ; 00000010H
  5.         mov        DWORD PTR _x$[ebp], 99                        ; 00000063H
  6.         mov        DWORD PTR _y$[ebp], 77                        ; 0000004dH
  7.         mov        eax, DWORD PTR _x$[ebp]
  8.         add        eax, 1
  9.         and        eax, -2147483585                        ; 8000003fH
  10.         jns        SHORT $L69607
  11.         dec        eax
  12.         or        eax, -64                                ; ffffffc0H
  13.         inc        eax
  14.         mov        DWORD PTR _x$[ebp], eax
  15.         mov        eax, DWORD PTR _y$[ebp]
  16.         add        eax, 1
  17.         xor        edx, edx
  18.         mov        ecx, 64                                        ; 00000040H
  19.         div        ecx
  20.         mov        DWORD PTR _y$[ebp], edx
  21.         mov        edx, DWORD PTR _x$[ebp]
  22.         add        edx, 1
  23.         and        edx, -2147483617                        ; 8000001fH
  24.         jns        SHORT $L69608
  25.         dec        edx
  26.         or        edx, -32                                ; ffffffe0H
  27.         inc        edx
  28.         mov        DWORD PTR _x$[ebp], edx
  29.         mov        eax, DWORD PTR _y$[ebp]
  30.         add        eax, 1
  31.         xor        edx, edx
  32.         mov        ecx, 32                                        ; 00000020H
  33.         div        ecx
  34.         mov        DWORD PTR _y$[ebp], edx
  35.         mov        DWORD PTR _mode_u$[ebp], 32                ; 00000020H
  36.         mov        DWORD PTR _mode_i$[ebp], 32                ; 00000020H
  37.         mov        eax, DWORD PTR _x$[ebp]
  38.         add        eax, 1
  39.         cdq
  40.         idiv        DWORD PTR _mode_i$[ebp]
  41.         mov        DWORD PTR _x$[ebp], edx
  42.         mov        eax, DWORD PTR _y$[ebp]
  43.         add        eax, 1
  44.         xor        edx, edx
  45.         div        DWORD PTR _mode_u$[ebp]
  46.         mov        DWORD PTR _y$[ebp], edx
  47.         mov        DWORD PTR _mode_u$[ebp], 11                ; 0000000bH
  48.         mov        DWORD PTR _mode_i$[ebp], 12                ; 0000000cH
  49.         mov        eax, DWORD PTR _x$[ebp]
  50.         add        eax, 1
  51.         cdq
  52.         idiv        DWORD PTR _mode_i$[ebp]
  53.         mov        DWORD PTR _x$[ebp], edx
  54.         mov        eax, DWORD PTR _y$[ebp]
  55.         add        eax, 1
  56.         xor        edx, edx
  57.         div        DWORD PTR _mode_u$[ebp]
  58.         mov        DWORD PTR _y$[ebp], edx
  59.         mov        eax, DWORD PTR _x$[ebp]
  60.         mov        esp, ebp
  61.         pop        ebp
  62.         ret        0
  63. ?test_int_mod@@YAHXZ ENDP                                ; test_int_mod

复制代码

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

神回复 2022-09-25 22:34:26

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

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

意中人 2022-09-25 22:34:26


你认为以下代码:

  1. #include <stdio.h>
  2. int main()
  3. {
  4.       int i,j;
  5.       for(i=0,j=0;i<10000;i++)
  6.              j+=i;
  7.       return 0;
  8. }

复制代码
应该被优化为以下吗?

  1. .globl main
  2. main:
  3.         xorl    %eax, %eax
  4.         ret

复制代码

冰雪之触 2022-09-25 22:34:26

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

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

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

ぃ弥猫深巷。 2022-09-25 22:34:26

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

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

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

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

肥爪爪 2022-09-25 22:34:26

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

怪异←思 2022-09-25 22:34:26

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

宛菡 2022-09-25 22:34:26

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


nt i, t1, t2;
i = 0;  // or  i=input();

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

地狱即天堂 2022-09-25 22:34:26

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

这个观点同意

无戏配角 2022-09-25 22:34:26

原帖由 system888net 于 2008-5-7 00:48 发表


nt i, t1, t2;
i = 0;  // or  i=input();

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文