Я работаю над векторизации циклов, и GCC мне тяжело. Когда я смотрю на код сборки, который он генерирует, я вижу много странных строк, от которых я бы хотел избавиться.GCC генерирует нежелательный код сборки
Например, с векторизации, я узнал, что вы можете избежать множества дополнительных сборочных линий, предоставив дополнительную информацию GCC о выравнивании массива. http://locklessinc.com/articles/vectorize/
Вот мой эксперимент.
#define SIZE 1024
void itwillwork (const uint16_t * a, const uint16_t * b, uint16_t * comp) {
int i = 0;
comp[i]=a[i]|b[i];
}
Формирует простой монтаж:
.globl _ZN8Test_LUT7performEv
23 _ZN8Test_LUT7performEv:
24 .LFB664:
25 .cfi_startproc
26 0020 488B4710 movq 16(%rdi), %rax
27 0024 488B4F08 movq 8(%rdi), %rcx
28 0028 488B5720 movq 32(%rdi), %rdx
29 002c 0FB700 movzwl (%rax), %eax
30 002f 660B01 orw (%rcx), %ax
31 0032 668902 movw %ax, (%rdx)
32 0035 C3 ret
33 .cfi_endproc
Но, даже если я ожидал несколько дополнительных линий, я очень удивлен тем, что я получил после добавления петли:
#define SIZE 1024
void itwillwork (const uint16_t * a, const uint16_t * b, uint16_t * comp) {
int i = 0;
for(i=0;i<SIZE;i++)
comp[i]=a[i]|b[i];
}
Генерирует эту сборку с гораздо большим количеством линий:
233 _Z10itwillworkPKtS0_Pt:
234 .LFB663:
235 .cfi_startproc
236 0250 488D4210 leaq 16(%rdx), %rax
237 0254 488D4E10 leaq 16(%rsi), %rcx
238 0258 4839F0 cmpq %rsi, %rax
239 025b 410F96C0 setbe %r8b
240 025f 4839CA cmpq %rcx, %rdx
241 0262 0F93C1 setnb %cl
242 0265 4108C8 orb %cl, %r8b
243 0268 743E je .L55
244 026a 4839F8 cmpq %rdi, %rax
245 026d 488D4710 leaq 16(%rdi), %rax
246 0271 0F96C1 setbe %cl
247 0274 4839C2 cmpq %rax, %rdx
248 0277 0F93C0 setnb %al
249 027a 08C1 orb %al, %cl
250 027c 742A je .L55
251 027e 31C0 xorl %eax, %eax
252 .p2align 4,,10
253 .p2align 3
254 .L57:
255 0280 F30F6F0C movdqu (%rsi,%rax), %xmm1
255 06
256 0285 F30F6F04 movdqu (%rdi,%rax), %xmm0
256 07
257 028a 660FEBC1 por %xmm1, %xmm0
258 028e F30F7F04 movdqu %xmm0, (%rdx,%rax)
258 02
259 0293 4883C010 addq $16, %rax
260 0297 483D0008 cmpq $2048, %rax
260 0000
261 029d 75E1 jne .L57
262 029f F3C3 rep ret
263 .p2align 4,,10
264 02a1 0F1F8000 .p2align 3
264 000000
265 .L55:
266 02a8 31C0 xorl %eax, %eax
267 02aa 660F1F44 .p2align 4,,10
267 0000
268 .p2align 3
269 .L58:
270 02b0 0FB70C06 movzwl (%rsi,%rax), %ecx
271 02b4 660B0C07 orw (%rdi,%rax), %cx
272 02b8 66890C02 movw %cx, (%rdx,%rax)
273 02bc 4883C002 addq $2, %rax
274 02c0 483D0008 cmpq $2048, %rax
274 0000
275 02c6 75E8 jne .L58
276 02c8 F3C3 rep ret
277 .cfi_endproc
Оба были скомпилированы с gcc 4.8.4 в режиме освобождения, -O2 -ftree-vectorize -msse2.
Может ли кто-нибудь помочь мне избавиться от этих линий? Или, если это невозможно, можете ли вы сказать мне, почему они там?
Update:
Я пробовал трюки там http://locklessinc.com/articles/vectorize/, но я получаю еще один вопрос:
#define SIZE 1024
void itwillwork (const uint16_t * a, const uint16_t * b, uint16_t * comp) {
int i = 0;
for(i=0;i<SIZE;i++)
comp[i]=a[i]|b[i];
}
несколько сборочных линий генерируются для этой функции, я получаю это. Но когда я называю эту функцию из другого места:
itwillwork(a,b,c);
Там нет инструкции вызова: длинный список инструкций «itwillwork» (то же самое, что и выше) используются непосредственно. Я что-то упустил? («Лишние линии» является проблемой, а не встроенный вызов)
Приятная идея - вставить код сборки в свой вопрос, вместо того, чтобы перейти на сайт pastebin.Я не понимаю, почему вы ставите код высокого уровня в свой вопрос, но не сборку. –
Почему вы думаете, что у вас так много других строк - это плохо? Если оптимизированный код работает быстро, вам небезразличен размер кода? Но также, ЧТО вы пробовали с 'ограничить' (вывести эту версию кода на C++). Код asm выглядит так, как будто компилятор не знает о указателях ограничений (особенно 'comp') и был бы более эффективным, если бы это было так. – JSF
Я попытался вставить здесь код сборки, но он вообще не читался (по какой-то причине нет строки). – Utundu