我正在尝试以正确的方式优化此代码。我的意思是正确的......我想有一种执行这些优化的通用方法,这样如果其他人查看代码,他们就可以删除优化。
可读性的C代码示例......
int a = 1; // mapped to %l0
int b = 5; // mapped to %l1
int c = 0; // mapped to %l2
int d; // mapped to %l3
while( a < b ) {
c += a * b;
++a;
}
d = c * b;
SPARC程序集版本......
mov %g0, %l2
cmp %l0, %l1
bge END_LOOP
nop
LOOP:
mov %l0, %o0
call .mul
mov %l1, %o1 ! Fill delay slot with second argument
add %l2, %o0, %l2
inc %l0
cmp %l0, %l1
bl LOOP
nop
END_LOOP:
mov %l2, %o0
call .mul ! Fill delay sot with second argument
mov %l1, %o1
mov %o0, %l3
我可以优化第一部分(不确定是否正确),但我不确定如何优化第二部分。
mov %g0, %l2
cmp %l0, %l1
bge,a END_LOOP ! Annul branch to execute if branch is taken
mov %l2, %o0 ! Instruction at target
LOOP:
mov %l0, %o0
call .mul
mov %l1, %o1 ! Fill delay slot with second argument
add %l2, %o0, %l2
inc %l0
cmp %l0, %l1
bl LOOP
nop
mov %l2, %o0 ! Move the instruction to above the target
END_LOOP:
call .mul ! Fill delay sot with second argument
mov %l1, %o1
mov %o0, %l3
非常感谢任何有关如何执行这些优化的帮助。
答案 0 :(得分:3)
一般来说,您的方法是正确的。假设您没有紧跟目标的数据依赖或控制指令转移,通常可以遵循以下约定。
你做到了这一点,可能没有意识到:
转到分支的目标,将指令复制到延迟槽并取消分支。如您所述,您取消分支以防止在未执行分支时执行指令。然后在标签上方的目标处移动指令。
在您的代码中,按照上述步骤操作,您将执行以下操作:
我删除了你的评论,因此你可以明确地看到我改变了什么。
mov %g0, %l2
cmp %l0, %l1
bge,a END_LOOP
mov %l2, %o0
mov %l0, %o0 ! 3. Move the instruction formerly after the loop
! above the label
LOOP:
[ mov %l0, %o0 ] ! Instruction was here
call .mul
mov %l1, %o1
add %l2, %o0, %l2
inc %l0
cmp %l0, %l1
bl,a LOOP ! 1. Go to the target and copy that instruction into
! they delay slot.
! 2. Annul the branch
mov %l0, %o0 ! Instruction formerly after LOOP:
mov %l2, %o0
END_LOOP:
call .mul
mov %l1, %o1
mov %o0, %l3
如果仔细检查代码,您将看到逻辑仍然存在,并且有一种系统的方法可以解除优化。
无论您是否进入循环,您的代码仍将正确执行循环后的代码。
这是优化代码的一般方法,与编译器的工作方式类似。关键是始终确保不存在数据依赖。