我有一个看起来像这样的Java循环:

public void testMethod() {
    int[] nums = new int[10];
    for (int i = 0; i < nums.length; i++) {
        nums[i] = 0x42;
    }
}

我得到的程序集是这样的:
0x00000001296ac845: cmp    %r10d,%ebp
0x00000001296ac848: jae    0x00000001296ac8b4
0x00000001296ac84a: movl   $0x42,0x10(%rbx,%rbp,4)
0x00000001296ac852: inc    %ebp
0x00000001296ac854: cmp    %r11d,%ebp
0x00000001296ac857: jl     0x00000001296ac845

0x00000001296ac859: mov    %r10d,%r8d
0x00000001296ac85c: add    $0xfffffffd,%r8d
0x00000001296ac860: mov    $0x80000000,%r9d
0x00000001296ac866: cmp    %r8d,%r10d
0x00000001296ac869: cmovl  %r9d,%r8d
0x00000001296ac86d: cmp    %r8d,%ebp
0x00000001296ac870: jge    0x00000001296ac88e
0x00000001296ac872: vmovq  -0xda(%rip),%xmm0
0x00000001296ac87a: vpunpcklqdq %xmm0,%xmm0,%xmm0
0x00000001296ac87e: xchg   %ax,%ax

0x00000001296ac880: vmovdqu %xmm0,0x10(%rbx,%rbp,4)
0x00000001296ac886: add    $0x4,%ebp
0x00000001296ac889: cmp    %r8d,%ebp
0x00000001296ac88c: jl     0x00000001296ac880

如果我的理解是正确的,则汇编的第一块是nums[i] = 0x42;。在第三块中,有一个vmovdqu
vmovdqu指令将值从整数向量移动到未对齐的内存位置。

但是,我仍然不完全了解我的循环上下文中的vmovdqu在做什么。

汇编代码的第三部分到底在做什么?

完整的代码可以在这里找到:https://pastebin.com/cT5cJcMS

最佳答案

优化器已选择对您的循环进行矢量化处理,每个“迭代”设置4个值。 (vmovdqu之前的指令相当不透明,但是大概是将0x42放入XMM0的所有通道中。)“unaligned”变体是必需的,因为不能保证数组在内存中是SIMD对齐的(毕竟,它存储int32 s ,而不是int32x4)。

08-16 10:28