Lite_stream
@Lite_stream

Почему Clang (с -O3) не векторизует данный цикл?

В первом примере компилятор успешно векторизовал цикл:

struct Word
{
    int a;
    int b;
    int c;
    int d;
};

size_t N = 1'000'000'000;

Word * words = new Word[N];

for (size_t i = 0; i < N; ++i)
{
        words[i].a = value + 1;
        words[i].b = value + 2;
        words[i].c = value + 3;
        words[i].d = value + 4;
}


Тело цикла:
=> 0x0000000000404c40 <+96>:	movdqu %xmm0,-0x70(%rdi)
   0x0000000000404c45 <+101>:	movdqu %xmm0,-0x60(%rdi)
   0x0000000000404c4a <+106>:	movdqu %xmm0,-0x50(%rdi)
   0x0000000000404c4f <+111>:	movdqu %xmm0,-0x40(%rdi)
   0x0000000000404c54 <+116>:	movdqu %xmm0,-0x30(%rdi)
   0x0000000000404c59 <+121>:	movdqu %xmm0,-0x20(%rdi)
   0x0000000000404c5e <+126>:	movdqu %xmm0,-0x10(%rdi)
   0x0000000000404c63 <+131>:	movdqu %xmm0,(%rdi)
   0x0000000000404c67 <+135>:	add    $0x8,%rsi
   0x0000000000404c6b <+139>:	sub    $0xffffffffffffff80,%rdi
   0x0000000000404c6f <+143>:	cmp    %rsi,%rdx
   0x0000000000404c72 <+146>:	jne    0x404c40 <run()+96>


А вот во втором, где происходит то же самое, но Word разделилась на 2 части и теперь 2 массива - нет:

struct Word
{
    int a;
    int b;
};

struct Half
{
    int c;
    int d;
};

size_t N = 1'000'000'000;

Word * words = new Word[N];
Half * halfs = new Half[N];

for (size_t i = 0; i < N; ++i)
{
        words[i].a = value + 1;
        words[i].b = value + 2;
        halfs[i].c = value + 3;
        halfs[i].d = value + 4;
}


Тело цикла:
=> 0x0000000000404c50 <+96>:	mov    %r9d,(%rsi,%rdx,8)
   0x0000000000404c54 <+100>:	mov    %edi,0x4(%rsi,%rdx,8)
   0x0000000000404c58 <+104>:	mov    %ebx,(%rcx,%rdx,8)
   0x0000000000404c5b <+107>:	mov    %eax,0x4(%rcx,%rdx,8)
   0x0000000000404c5f <+111>:	mov    %r9d,0x8(%rsi,%rdx,8)
   0x0000000000404c64 <+116>:	mov    %edi,0xc(%rsi,%rdx,8)
   0x0000000000404c68 <+120>:	mov    %ebx,0x8(%rcx,%rdx,8)
   0x0000000000404c6c <+124>:	mov    %eax,0xc(%rcx,%rdx,8)
   0x0000000000404c70 <+128>:	add    $0x2,%rdx
   0x0000000000404c74 <+132>:	cmp    %rdx,%r10
   0x0000000000404c77 <+135>:	jne    0x404c50 <run()+96>
  • Вопрос задан
  • 111 просмотров
Решения вопроса 1
mayton2019
@mayton2019
Bigdata Engineer
В первом варианте был массив четверок int или массив 128 битных элементов.
Во втором случае - два независимых массивка 64х битных элементов которые в памяти
расположены достаточно далеко и для них скорее всего не нашлось такой векторной
команды которая-бы адресовалась к паре 64 + 64.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы