展开 y86 循环
Posted
技术标签:
【中文标题】展开 y86 循环【英文标题】:Unrolling y86 loop 【发布时间】:2016-10-26 01:37:24 【问题描述】:我正在尝试在 y86 代码中展开循环,但是当我尝试运行测试程序时,我得到了 2 个不同的值。注册。代码是:
xorq %rax,%rax # count = 0;
andq %rdx,%rdx # len <= 0?
jle Done # if so, goto Done:
Loop:
mrmovq (%rdi), %r10 # read val from src...
rmmovq %r10, (%rsi) # ...and store it to dst
andq %r10, %r10 # val <= 0?
jle Npos # if so, goto Npos:
#irmovq $1, %r10
#addq %r10, %rax
iaddq $1, %rax # count++
Npos:
irmovq $1, %r10
subq %r10, %rdx # len--
#irmovq $8, %r10
#addq %r10, %rdi
#addq %r10, %rsi
iaddq $8, %rdi # src++
iaddq $8, %rsi # dst++
andq %rdx,%rdx # len > 0?
jg Loop # if so, goto Loop:
Done:
ret
我制作的展开版是:
xorq %rax,%rax # count = 0;
andq %rdx,%rdx # len <= 0?
jle Done # if so, goto Done:
Loop:
mrmovq (%rdi), %r10 # read val from src…
mrmovq 8(%rdi), %r11 # <- from class get second value
rmmovq %r10, (%rsi) # ...and store it to dst
rmmovq %r11, 8(%rsi) # store second val to dst
andq %r10, %r10 # val <= 0?
jle Npos # if so, goto Npos:
iaddq $1, %rax
Npos:
andq %r11, %r11 # check if src[1] <= 0
jle Npos2 # if it is, don’t increase count
iaddq $1, %rax
Npos2:
irmvoq %2, %r10
iaddq $16, %rdi # increase stack or base pointer to get next 2 vals
iaddq $16, %rsi # increase stack or base pointer to store next 2 vals
subq %r10, %rdx # decrease length by 2
jge Loop # go back into loop if length >= 2
len_cleanup:
iaddq $2, %rdx
cleanup:
irmovq $1, %r10
subq %r10, %rdx
jl Done # if length < 0, jmp to Done, no cleanup needed
mrmovq (%rdi), %r10 # get next val
rmmovq %r10, (%rsi) # move val onto stack
andq %r10, %r10 # check if val <= 0
jle Done # skip count if val < 0
iaddq $1, %rax # same as iaddq $1, %rax
Done:
ret
我应该得到的结果是 2,但从展开的结果返回的结果是 3。我知道有一个额外的 iaddq
正在执行,但我不确定在哪里。我展开循环两次,以便改为检查 2 个值。
【问题讨论】:
【参考方案1】:我刚刚修好了。我想在开始循环之前减少 %rdx 以正确展开函数。
当您不知道迭代次数是展开因子的倍数时,您需要将 do while(--i >= 0);
展开为类似--i; do while(i-=2 >= 0);
的内容,以确保不会过冲。
【讨论】:
以上是关于展开 y86 循环的主要内容,如果未能解决你的问题,请参考以下文章