ASM - 优化`for`循环

时间:2015-09-27 12:57:59

标签: c optimization assembly dlx

在作业中,我收到了将C代码更改为简化DLX的ASM的任务:

multi

我的解决方案:

假设:

  • a = 0; for (i = 1; i < 14; i++) a = a + c; A[0] = a; 的值在寄存器R1
  • a的值在寄存器R2
  • c的值在寄存器R3
  • i的地址值(表示A)在寄存器R4

然后:

&A

他们的解决方案:

假设:

  • addi R1 R0 0 // init a = 0 addi R3 R0 1 // init i = 1 slti R5 R3 14 // test (i < 14) ; R5 = 1 if i < 14 beqz R5 3 // branch 3 lines of R5 == 0 add R1 R1 R2 // a = a + c addi R3 R3 1 // i++ beqz R0 -5 // return up to the condition of the for loop sw R1 R4 0 // A[0] = 0 的值在寄存器R1
  • a的值在寄存器R2 中(请注意此处的更改)
  • i的值在寄存器R3 中(注意此处的更改)
  • c的地址值(表示A)在寄存器R4

然后:

&A

差:

他们的解决方案显然更好,因为命令少了一个 - 我的代码有一个额外的条件分支。他们的代码正是我想要做的第一个,但后来我回忆起addi R1 R0 0 // a = 0 addi R2 R0 1 // i = 1 add R1 R1 R3 // a = a+c addi R2 R2 1 // i++ slti R5 R2 14 // R5=1 iff i<14 bnez R5 -4 // jump 4 lines up from the next line if // R5!=0, that is if i<14 sw R1 R4 0 // store the new value of A[0]=a (R1) 循环算法:

  1. 初始化变量
  2. 检查条件是否为for 如果True:在循环中应用命令,
    否则:退出循环。
  3. 增量变量
  4. 返回#2
  5. 所以他们的代码与for循环算法不同,因为它在初始化(#1)后没有检查条件(#2)...
    我心想 - 这是优化的结果吗? 这是什么级别的优化? (IIRC有4个级别:O0,O1,O2,O3)
    在解释C代码时,是否应该默认优化代码?

1 个答案:

答案 0 :(得分:2)

激活优化后,编译器会检查其汇编代码,以查看是否有任何需要改进的地方,特别是避免无用的指令或检查。

例如,在您的代码中,for循环是初始化,然后是经典的while循环。经典优化是检查第一个条目的while条件是否为false,如果不是,则在do while循环中对其进行转换。
这正是你的情况。如果您在指令i < 14之后检查它,则i = 1不能为假。所以运行得更快:

a = 0;
i = 1;
do
{
    a = a + c;
    i++;
} while (i < 14);
A[0] = a;

是的,这是一种优化形式。但是当你直接用汇编语言编写代码时,通常需要你做这种技巧,因为汇编编程的目标(主要是学习它)是尽可能快地使你的代码,使用任何减少指令调用的可能性。

这是GCC上O1级别优化的结果。