winMips64运行MIPS汇编乘方代码出现大量RAW错误该如何优化?
问题原因
你遇到的RAW(写后读)报错本质是流水线处理器中,后续指令需要读取前序指令还未完成写回的寄存器值,导致流水线被迫停顿。你的代码里核心有三处强数据依赖触发了大量RAW:
- 初始化阶段
DADDI R2, R0, 1后立刻读R2执行MTC1 R2,F11,整数指令结果还未写回就被读取 MTC1 R2,F11后立刻读F11执行CVT.L.D F2,F11,浮点寄存器写入后无间隔就被读取- 循环内
MUL.D F2, F2, F0每次都直接依赖上一次乘法的结果F2,双精度浮点乘法本身周期长,连续依赖下几乎每次都会触发RAW停顿
优化方案
1. 调整初始化阶段指令顺序
将无依赖的加载指令插入到有数据依赖的指令之间,打散相邻依赖,无需修改功能就能消除初始化阶段的所有RAW:
DADDI R2, R0, 1 ; 先计算R2 LD R1,n(R0) ; 插入无关的Load指令,隔开R2的写和读 MTC1 R2,F11 ; 此时R2已经完成写回,无RAW L.D F0,x(R0) ; 插入无关的浮点Load指令,隔开F11的写和读 CVT.L.D F2,F11 ; 此时F11已经完成写回,无RAW
2. 循环指令调度+循环展开
调整循环内指令顺序,同时将循环展开,把整数操作插入到两次浮点乘法的间隙,填充浮点乘法的等待周期,避免连续依赖F2。这里以你的用例n=8(2的倍数)为例,展开2次循环:
loop: MUL.D F2, F2, F0 ; 第一次乘法 DADDI R1, R1, -2 ; 插入整数操作,隔开两次乘法的F2依赖 MUL.D F2, F2, F0 ; 第二次乘法,此时第一次乘法的F2结果已经写回 BNEZ R1, loop ; 循环判断
如果要兼容任意正整数n,额外加边界判断处理奇数情况即可。
3. (可选)改用快速幂算法
如果允许修改计算逻辑,x的n次乘方可通过快速幂将乘法次数从n次降到log₂n次,从根本上减少依赖次数。比如你的用例x^8只需要3次乘法,几乎不会出现连续RAW。
完整优化后代码(兼容通用n,无额外功能改动)
.data n: .word 8 x: .double 0.5 .text DADDI R2, R0, 1 ; R2 = 1 LD R1,n(R0) ; 加载n MTC1 R2,F11 ; F11 = 1 L.D F0,x(R0) ; 加载x CVT.L.D F2,F11 ; F2 = 1 loop: MUL.D F2, F2, F0 ; F2 = F2*F0 DADDI R1, R1, -1 ; decrement R1 by 1 BNEZ R1, loop ; if R1 != 0 continue HALT
内容的提问来源于stack exchange,提问作者mikeyMike
相关产品推荐
相关产品推荐

