为什么将变量声明为volatile会加速代码执行?

时间:2011-09-28 23:52:17

标签: volatile

有什么想法吗?我正在为PPC750使用GCC交叉编译器。在循环中对两个浮点数进行简单的乘法运算并对其进行计时。我声明变量是易变的,以确保没有重要的东西被优化,代码加快了!

我已经检查了两种情况的汇编指令,当然,编译器生成了更多指令,以便在非易失性情况下执行相同的基本工作。 10,000,000次迭代的执行时间从800ms降至300ms!

易失性案件的组装:

0x10eeec  stwu  r1,-32(r1)
0x10eef0  lis   r9,0x1d # 29
0x10eef4  lis   r11,0x4080 # 16512
0x10eef8  lfs   fr0,-18944(r9)
0x10eefc  li    r0,0x0 # 0
0x10ef00  lis   r9,0x98 # 152
0x10ef04  stfs  fr0,8(r1)
0x10ef08  mtspr CTR,r9
0x10ef0c  stw   r11,12(r1)
0x10ef10  stw   r0,16(r1)
0x10ef14  ori   r9,r9,0x9680
0x10ef18  mtspr CTR,r9
0x10ef1c  lfs   fr0,8(r1)
0x10ef20  lfs   fr13,12(r1)
0x10ef24  fmuls fr0,fr0,fr13
0x10ef28  stfs  fr0,16(r1)
0x10ef2c  bc    0x10,0, 0x10ef1c # 0x0010ef1c
0x10ef30  addi  r1,r1,0x20 # 32

非易失性案件的组合:

0x10ef04  stwu        r1,-48(r1)
0x10ef08  stw         r31,44(r1)
0x10ef0c  or          r31,r1,r1
0x10ef10  lis         r9,0x1d # 29
0x10ef14  lfs         fr0,-18832(r9)
0x10ef18  stfs        fr0,12(r31)
0x10ef1c  lis         r0,0x4080 # 16512
0x10ef20  stw         r0,16(r31)
0x10ef24  li          r0,0x0 # 0
0x10ef28  stw         r0,20(r31)
0x10ef2c  li          r0,0x0 # 0
0x10ef30  stw         r0,8(r31)
0x10ef34  lwz         r0,8(r31)
0x10ef38  lis         r9,0x98 # 152
0x10ef3c  ori         r9,r9,0x967f
0x10ef40  cmpl        crf0,0,r0,r9
0x10ef44  bc          0x4,1, 0x10ef4c # 0x0010ef4c
0x10ef48  b           0x10ef6c # 0x0010ef6c
0x10ef4c  lfs         fr0,12(r31)
0x10ef50  lfs         fr13,16(r31)
0x10ef54  fmuls       fr0,fr0,fr13
0x10ef58  stfs        fr0,20(r31)
0x10ef5c  lwz         r9,8(r31)
0x10ef60  addi        r0,r9,0x1 # 1
0x10ef64  stw         r0,8(r31)
0x10ef68  b           0x10ef34 # 0x0010ef34
0x10ef6c  lwz         r11,0(r1)
0x10ef70  lwz         r31,-4(r11)
0x10ef74  or          r1,r11,r11
0x10ef78  blr

如果我正确读取它,它会在每次迭代中加载内存中的值,但它似乎在非易失性情况下生成了更多指令。< / p>

这是来源:

void floatTest()
{
    unsigned long i;
    volatile double d1 = 500.234, d2 = 4.000001, d3=0;
    for(i=0; i<10000000; i++)
        d3 = d1*d2;
}

1 个答案:

答案 0 :(得分:2)

您确定没有更改优化设置吗?

原作看起来未经优化 - 这是循环部分:

0x10ef34  lwz         r0,8(r31)       //Put 'i' in r0.
0x10ef38  lis         r9,0x98 # 152   //Put MSB of 10000000 in r9
0x10ef3c  ori         r9,r9,0x967f    //Put LSB of 10000000 in r9
0x10ef40  cmpl        crf0,0,r0,r9    //compare r0 to r9

0x10ef44  bc          0x4,1, 0x10ef4c //branch to loop if r0<r9
0x10ef48  b           0x10ef6c        //else branch to end

0x10ef4c  lfs         fr0,12(r31)     //load d1
0x10ef50  lfs         fr13,16(r31)    //load d2
0x10ef54  fmuls       fr0,fr0,fr13    //multiply
0x10ef58  stfs        fr0,20(r31)     //save d3

0x10ef5c  lwz         r9,8(r31)       //load i into r9
0x10ef60  addi        r0,r9,0x1       //add 1
0x10ef64  stw         r0,8(r31)       //save i

0x10ef68  b           0x10ef34        //go back to top, must reload r9

易失性版本看起来非常优化 - 它重新排列指令,并使用专用计数器寄存器而不是将i存储在堆栈中:

0x10ef00  lis   r9,0x98 # 152      //MSB of 10M
//.. 4 initialization instructions here ..
0x10ef14  ori   r9,r9,0x9680       //LSB of 10,000000
0x10ef18  mtspr CTR,r9             // store r9 in Special Purpose CTR register
0x10ef1c  lfs   fr0,8(r1)          // load d1
0x10ef20  lfs   fr13,12(r1)        // load d2
0x10ef24  fmuls fr0,fr0,fr13       // multiply
0x10ef28  stfs  fr0,16(r1)         // store result
0x10ef2c  bc    0x10,0, 0x10ef1c   // decrement counter and branch if not 0.

点击率优化将循环减少到5条指令,而不是原始代码中的14条指令。我认为没有任何理由“挥发”本身就能实现优化。