ARM架构中LDR(无符号偏移)与LDUR(无缩放)指令差异及性能问询
ARM LDR(无符号偏移)与LDUR(无缩放)指令解析
假设x1寄存器的值为0x10001000,以下两条指令功能完全相同,均会将0x10001004-0x10001007地址范围内的4字节数据加载到w6寄存器中:
ldr w6, [x1, #4] // "无符号偏移"(立即数) ldur w6, [x1, #4] // "无缩放"加载
指令特性总结
- 32位LDR(立即数)指令仅支持4的正整数倍作为预增量偏移;64位LDR(立即数)则仅支持8的正整数倍作为预增量偏移,因此以下两条指令属于非法指令:
ldr w6, [x1, #1] // 非法 ldr w6, [x1, #-4] // 非法
- 若需要使用负偏移或非对齐地址传输数据,必须使用LDUR指令:
ldur w6, [x1, #1] // 加载地址0x10001001-0x10001004的字节数据 ldur w6, [x1, #-4] // 加载地址0x10000ffc-0x10001000的字节数据
问题与解答
问题1:为何区分LDR(无符号偏移)与LDUR(无缩放)指令?
最初推测LDUR的延迟远高于LDR(立即数),ARM是为了让开发者明确感知到潜在性能损耗才分开实现。后续经提醒得知:LDR指令因限制偏移为4/8的整数倍,能支持更大范围的立即数偏移,这是两者拆分的核心原因。
问题2:Neoverse架构下三种实现方式的性能对比
已知SVE向量指令集更适合批量数据加载场景,此处仅为加深对LDUR的理解。在最新Neoverse架构上,对比以下三种批量加载实现的性能优劣(无法通过QEMU模拟测试):
#1 #2 #3 (后增量修改x1寄存器) ldur x2, [x1, # -4] sub x1, x1, 4 ldr x2, [x1], #-4 ldur x3, [x1, # -8] ldr x2, [x1] ldr x3, [x1], #-4 ldur x4, [x1, #-12] sub x1, x1, 4 ldr x4, [x1], #-4 ldur x5, [x1, #-16] ldr x3, [x1] ldr x5, [x1], #-4 ldur x6, [x1, #-20] sub x1, x1, 4 ldr x6, [x1], #-4 ldur x7, [x1, #-24] ldr x4, [x1] ldr x7, [x1], #-4 ldur x8, [x1, #-28] sub x1, x1, 4 ldr x8, [x1], #-4 ldur x9, [x1, #-32] ldr x5, [x1] ldr x9, [x1], #-4 sub x1, x1, 4 ldr x6, [x1] sub x1, x1, 4 ldr x7, [x1] sub x1, x1, 4 ldr x8, [x1] sub x1, x1, 4 ldr x9, [x1]
经指引参考ARM《软件优化指南》,此类批量操作的推荐方式是通过循环展开最大化指令并行性。
内容的提问来源于stack exchange,提问作者Lance E.T. Compte
相关产品推荐
相关产品推荐

