<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="">Agreed, it looks like this result is the result of a loop variable optimization which made the resulting code more complex. So what’s the best way to track this down?<div class=""><br class=""></div><div class="">Thanks,</div><div class="">Wenzel<br class=""><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 09 Jun 2016, at 12:00, mats petersson <<a href="mailto:mats@planetcatfish.com" class="">mats@planetcatfish.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div dir="ltr" class=""><div class="">Being technical on the "lack of optimisation" here, it is not that LLVM doesn't identify the common loop variable, but the fact that it (probably misguidedly) removes the loop variable and uses multiple pointers instead.<br class=""><br class=""></div><div class="">You WOULD want:<br class=""><br class=""></div><div class="">    for(i = 0; i < size; i++)<br class="">    {<br class=""></div><div class="">       s[i] = t[i];<br class="">    }<br class=""><br class=""></div><div class="">to be converted to:<br class=""><br class=""></div><div class="">    stmp = s;<br class=""></div><div class="">    ttemp = t;<br class=""></div><div class="">    send = s+size;<br class=""></div><div class="">    while(stmp < send)<br class="">    {<br class=""></div><div class="">       s++ = t++;<br class="">    }<br class=""><br class=""></div><div class="">right? So the compiler should recognise these cases, and do the conversion, but only when it's actually "better".<br class=""></div><div class=""><br class="">--<br class=""></div>Mats<br class=""></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On 9 June 2016 at 10:02, Wenzel Jakob via cfe-dev <span dir="ltr" class=""><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" 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 class=""><blockquote type="cite" class=""><span class=""><div class="">On 09 Jun 2016, at 09:15, Wenzel Jakob <<a href="mailto:wenzel.jakob@epfl.ch" target="_blank" class="">wenzel.jakob@epfl.ch</a>> wrote:</div><br class=""></span><div class="">
<div style="word-wrap:break-word" class=""><span 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></span><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=""><div class="h5"><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 style="white-space:pre-wrap" class="">   </span>vmovups<span style="white-space:pre-wrap" class="">      </span>(%rdx), %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class=""> </span>vaddps<span style="white-space:pre-wrap" class="">       </span>(%rcx), %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">  </span>vmovups<span style="white-space:pre-wrap" class="">      </span>(%r8), %ymm1</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">  </span>vaddps<span style="white-space:pre-wrap" class="">       </span>(%r9), %ymm1, %ymm1</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">   </span>vaddps<span style="white-space:pre-wrap" class="">       </span>%ymm1, %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">   </span>vmovups<span style="white-space:pre-wrap" class="">      </span>(%rax), %ymm1</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class=""> </span>vaddps<span style="white-space:pre-wrap" class="">       </span>(%r10), %ymm1, %ymm1</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">  </span>vaddps<span style="white-space:pre-wrap" class="">       </span>%ymm1, %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">   </span>vmovups<span style="white-space:pre-wrap" class="">      </span>%ymm0, (%rsi)</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class=""> </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %rdx</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %rcx</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %r8</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">      </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %r9</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">      </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %rax</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %r10</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %rsi</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>decq<span style="white-space:pre-wrap" class=""> </span>%rdi</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">  </span>jne<span style="white-space:pre-wrap" class="">  </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 style="white-space:pre-wrap" class="">       </span>vmovaps<span style="white-space:pre-wrap" class="">      </span>(%r9,%rax), %ymm1</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>vmovaps<span style="white-space:pre-wrap" class="">      </span>(%rcx,%rax), %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">    </span>vaddps<span style="white-space:pre-wrap" class="">       </span>(%r8,%rax), %ymm1, %ymm2</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">      </span>vaddps<span style="white-space:pre-wrap" class="">       </span>(%rdx,%rax), %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>vaddps<span style="white-space:pre-wrap" class="">       </span>%ymm0, %ymm2, %ymm1</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">   </span>vmovaps<span style="white-space:pre-wrap" class="">      </span>(%r11,%rax), %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">    </span>vaddps<span style="white-space:pre-wrap" class="">       </span>(%rbx,%rax), %ymm0, %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>vaddps<span style="white-space:pre-wrap" class="">       </span>%ymm0, %ymm1, %ymm0</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">   </span>vmovaps<span style="white-space:pre-wrap" class="">      </span>%ymm0, (%rsi,%rax)</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">    </span>addq<span style="white-space:pre-wrap" class=""> </span>$32, %rax</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">     </span>cmpq<span style="white-space:pre-wrap" class=""> </span>%rax, %r10</font></div><div class=""><font face="Courier" class=""><span style="white-space:pre-wrap" class="">    </span>jne<span style="white-space:pre-wrap" class="">  </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 %.<a href="http://lr.ph/" target="_blank" class="">lr.ph</a></font></div><div class=""><font face="Courier" class=""><br class=""></font></div><div class=""><font face="Courier" class="">._crit_edge:                                      ; preds = %.<a href="http://lr.ph/" target="_blank" class="">lr.ph</a>, %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="">.<a href="http://lr.ph/" target="_blank" class="">lr.ph</a>:                                           ; preds = %0, %.<a href="http://lr.ph/" target="_blank" class="">lr.ph</a></font></div><div class=""><font face="Courier" class="">  %i.01 = phi i64 [ %20, %.<a href="http://lr.ph/" target="_blank" class="">lr.ph</a> ], [ 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 %.<a href="http://lr.ph/" target="_blank" class="">lr.ph</a></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></div></div></blockquote></div><br class=""></div></div><br class="">_______________________________________________<br class="">
cfe-dev mailing list<br class="">
<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br class="">
<br class=""></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></div></div></body></html>