<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Apologies, there was a typo in my last message.<div class=""><br class=""></div><div class="">"The following output was generated by LLVM” in the third paragraph should have read "The following output was generated by GCC 5.3.0”.</div><div class=""><br class=""></div><div class="">-Wenzel</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 09 Jun 2016, at 09:15, Wenzel Jakob <<a href="mailto:wenzel.jakob@epfl.ch" class="">wenzel.jakob@epfl.ch</a>> wrote:</div><br class="Apple-interchange-newline"><div class="">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi,</div><div class=""><br class=""></div><div class="">I’m having trouble getting LLVM/Clang to generate high quality code for a tight loop involving AVX intrinsics.</div><div class="">Consider the following simple function, which computes a sum of a bunch of buffers.</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">#include <immintrin.h></font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">void sum(size_t n, </font></div><div class=""><font face="Courier" class=""> __m256* __restrict__ a, __m256* __restrict__ b,</font></div><div class=""><font face="Courier" class=""> __m256* __restrict__ c, __m256* __restrict__ d,</font></div><div class=""><font face="Courier" class=""> __m256* __restrict__ e, __m256* __restrict__ f,</font></div><div class=""><font face="Courier" class=""> __m256* __restrict__ g) {</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class=""> for (size_t i = 0; i < n; ++i)</font></div><div class=""><font face="Courier" class=""> a[i] = _mm256_add_ps(</font></div><div class=""><font face="Courier" class=""> _mm256_add_ps(_mm256_add_ps(b[i], c[i]),</font></div><div class=""><font face="Courier" class=""> _mm256_add_ps(d[i], e[i])),</font></div><div class=""><font face="Courier" class=""> _mm256_add_ps(f[i], g[i]));</font></div><div class=""><font face="Courier" class="">}</font></div><div class=""><br class=""></div><div class="">This is the main loop body resulting from the above expression (compiled with -mavx2 -O3 -fomit-frame-pointer -fno-unroll-loops). Note the large number of “addq” instructions!</div><div class="">The compiler also seems to assume that the __m256 entries are unaligned, but that is another issue.</div><div class=""><br class=""></div><div class=""><font face="Courier" class="">LBB0_2:</font></div><div class=""><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovups<span class="Apple-tab-span" style="white-space:pre"> </span>(%rdx), %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>(%rcx), %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovups<span class="Apple-tab-span" style="white-space:pre"> </span>(%r8), %ymm1</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>(%r9), %ymm1, %ymm1</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>%ymm1, %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovups<span class="Apple-tab-span" style="white-space:pre"> </span>(%rax), %ymm1</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>(%r10), %ymm1, %ymm1</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>%ymm1, %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovups<span class="Apple-tab-span" style="white-space:pre"> </span>%ymm0, (%rsi)</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %rdx</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %rcx</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %r8</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %r9</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %rax</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %r10</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %rsi</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>decq<span class="Apple-tab-span" style="white-space:pre"> </span>%rdi</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>jne<span class="Apple-tab-span" style="white-space:pre"> </span>LBB0_2</font></div></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">The following output was generated by LLVM. It identifies the common counter variable and just stores the buffer offsets in registers.</div><div class=""><br class=""></div><div class=""><div class=""><font face="Courier" class="">L5:</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovaps<span class="Apple-tab-span" style="white-space:pre"> </span>(%r9,%rax), %ymm1</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovaps<span class="Apple-tab-span" style="white-space:pre"> </span>(%rcx,%rax), %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>(%r8,%rax), %ymm1, %ymm2</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>(%rdx,%rax), %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>%ymm0, %ymm2, %ymm1</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovaps<span class="Apple-tab-span" style="white-space:pre"> </span>(%r11,%rax), %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>(%rbx,%rax), %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vaddps<span class="Apple-tab-span" style="white-space:pre"> </span>%ymm0, %ymm1, %ymm0</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>vmovaps<span class="Apple-tab-span" style="white-space:pre"> </span>%ymm0, (%rsi,%rax)</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>addq<span class="Apple-tab-span" style="white-space:pre"> </span>$32, %rax</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>cmpq<span class="Apple-tab-span" style="white-space:pre"> </span>%rax, %r10</font></div><div class=""><font face="Courier" class=""><span class="Apple-tab-span" style="white-space:pre"> </span>jne<span class="Apple-tab-span" style="white-space:pre"> </span>L5</font></div></div><div class=""><br class=""></div><div class="">Is there something that could be done to LLVM to generate better code in such cases?</div><div class=""><br class=""></div><div class=""><div class="">For reference, this is the associated LLVM IR:</div><div class=""><font face="Courier" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Courier" class="">; Function Attrs: nounwind ssp uwtable</font></div><div class=""><font face="Courier" class="">define void @_Z3summPDv8_fS0_S0_S0_S0_S0_S0_(i64 %n, <8 x float>* noalias nocapture %a, <8 x float>* noalias nocapture readonly %b, <8 x float>* noalias nocapture readonly %c, <8 x float>* noalias nocapture readonly %d, <8 x float>* noalias nocapture readonly %e, <8 x float>* noalias nocapture readonly %f, <8 x float>* noalias nocapture readonly %g) #0 {</font></div><div class=""><font face="Courier" class=""> %1 = icmp eq i64 %n, 0</font></div><div class=""><font face="Courier" class=""> br i1 %1, label %._crit_edge, label %.lr.ph</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">._crit_edge: ; preds = %.lr.ph, %0</font></div><div class=""><font face="Courier" class=""> ret void</font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">.lr.ph: ; preds = %0, %.lr.ph</font></div><div class=""><font face="Courier" class=""> %i.01 = phi i64 [ %20, %.lr.ph ], [ 0, %0 ]</font></div><div class=""><font face="Courier" class=""> %2 = getelementptr inbounds <8 x float>, <8 x float>* %b, i64 %i.01</font></div><div class=""><font face="Courier" class=""> %3 = load <8 x float>, <8 x float>* %2, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %4 = getelementptr inbounds <8 x float>, <8 x float>* %c, i64 %i.01</font></div><div class=""><font face="Courier" class=""> %5 = load <8 x float>, <8 x float>* %4, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %6 = fadd <8 x float> %3, %5</font></div><div class=""><font face="Courier" class=""> %7 = getelementptr inbounds <8 x float>, <8 x float>* %d, i64 %i.01</font></div><div class=""><font face="Courier" class=""> %8 = load <8 x float>, <8 x float>* %7, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %9 = getelementptr inbounds <8 x float>, <8 x float>* %e, i64 %i.01</font></div><div class=""><font face="Courier" class=""> %10 = load <8 x float>, <8 x float>* %9, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %11 = fadd <8 x float> %8, %10</font></div><div class=""><font face="Courier" class=""> %12 = fadd <8 x float> %6, %11</font></div><div class=""><font face="Courier" class=""> %13 = getelementptr inbounds <8 x float>, <8 x float>* %f, i64 %i.01</font></div><div class=""><font face="Courier" class=""> %14 = load <8 x float>, <8 x float>* %13, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %15 = getelementptr inbounds <8 x float>, <8 x float>* %g, i64 %i.01</font></div><div class=""><font face="Courier" class=""> %16 = load <8 x float>, <8 x float>* %15, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %17 = fadd <8 x float> %14, %16</font></div><div class=""><font face="Courier" class=""> %18 = fadd <8 x float> %12, %17</font></div><div class=""><font face="Courier" class=""> %19 = getelementptr inbounds <8 x float>, <8 x float>* %a, i64 %i.01</font></div><div class=""><font face="Courier" class=""> store <8 x float> %18, <8 x float>* %19, align 16, !tbaa !2</font></div><div class=""><font face="Courier" class=""> %20 = add nuw i64 %i.01, 1</font></div><div class=""><font face="Courier" class=""> %exitcond = icmp eq i64 %20, %n</font></div><div class=""><font face="Courier" class=""> br i1 %exitcond, label %._crit_edge, label %.lr.ph</font></div><div class=""><font face="Courier" class="">}</font></div></div><div class=""><br class=""></div><div class="">Thank you and best regards,</div><div class="">Wenzel</div></div></div></blockquote></div><br class=""></div></body></html>