<font face="Default Sans Serif,Verdana,Arial,Helvetica,sans-serif" size="2"><br><br><font color="#990099">-----Forwarded by Olivier H Sallenave/Watson/IBM on 02/09/2015 03:33PM -----</font><div style="padding-left:5px;"><div style="padding-right:0px;padding-left:5px;border-left:solid black 2px;">To: Olivier H Sallenave/Watson/IBM@IBMUS, hfinkel@anl.gov<br>From: Olivier H Sallenave/Watson/IBM@IBMUS<br>Date: 02/09/2015 01:45PM<br>Subject: [PATCH] Break dependencies in large loops containing reductions (LoopVectorize)<br><br><i>(See attached file: D7514.19597.patch)</i><br><br><div><font face="Courier New,Courier,monospace" size="3">Hi hfinkel,<br><br>For the code below, the loop vectorizer is expected to unroll the loop and break loop-carried dependencies by using more registers (see <a href="http://reviews.llvm.org/D7128">http://reviews.llvm.org/D7128</a>).<br><br>```<br>for(int i=0; i<n; i++) {<br>  for(int i_c=0; i_c<3; i_c++) {<br>    _Complex __attribute__ ((aligned (8))) at = a[i][i_c];<br>    sum += ((__real__(at))*(__real__(at)) + (__imag__(at))*(__imag__(at)));<br>  }<br>}<br>```<br><br>Here, the inner loop is first unrolled by the regular loop unroller, which doesn't break dependencies. The loop vectorizer should then unroll the outer loop and break dependencies. But this doesn't happen, since the heuristics consider that only small loops are worth to unroll. This patch fixes the heuristics.<br><br>For the example above on POWER8, there is a 2.5x speedup. To handle all targets appropriately, I propose the following cost function to compute the unroll factor (not in this patch yet):<br><br>UF = UF * CriticalPathLength / LoopLength<br><br>UF is the unroll factor already computed up to this point, which takes into account register pressure and is bounded with the TTI max interleave factor. CriticalPathLength and LoopLength only take into account interesting operations (FP?). The cost function approximates reduces UF while ensuring that ILP opportunities are met. It works well for the example above on P8. Please tell me what you think.<br><br>Thanks,<br>Olivier<br><br><a href="http://reviews.llvm.org/D7514">http://reviews.llvm.org/D7514</a><br><br>Files:<br>  lib/Transforms/Vectorize/LoopVectorize.cpp<br>  test/Transforms/LoopVectorize/PowerPC/unrolled-rdx.ll<br><br>Index: lib/Transforms/Vectorize/LoopVectorize.cpp<br>===================================================================<br>--- lib/Transforms/Vectorize/LoopVectorize.cpp<br>+++ lib/Transforms/Vectorize/LoopVectorize.cpp<br>@@ -4647,6 +4647,14 @@<br>     return SmallUF;<br>   }<br><br>+  // Unroll if this is a large loop (small loops are already dealt with by this<br>+  // point) and there is a scalar reduction that could benefit from unrolling.<br>+  if (!UnrollingRequiresRuntimePointerCheck &&<br>+      Legal->getReductionVars()->size()) {<br>+    DEBUG(dbgs() << "LV: Unrolling because of reductions.\n");<br>+    return UF;<br>+  }<br>+<br>   DEBUG(dbgs() << "LV: Not Unrolling.\n");<br>   return 1;<br> }<br>Index: test/Transforms/LoopVectorize/PowerPC/unrolled-rdx.ll<br>===================================================================<br>--- test/Transforms/LoopVectorize/PowerPC/unrolled-rdx.ll<br>+++ test/Transforms/LoopVectorize/PowerPC/unrolled-rdx.ll<br>@@ -0,0 +1,64 @@<br>+; RUN: opt < %s -loop-vectorize -S -debug < %s 2>&1 | FileCheck %s<br>+<br>+; CHECK: LV: Unrolling because of reductions.<br>+<br>+target datalayout = "e-m:e-i64:64-n32:64"<br>+target triple = "powerpc64le-ibm-linux-gnu"<br>+<br>+define void @QLA_F3_r_veq_norm2_V(float* noalias nocapture %r, [3 x { float, float }]* noalias nocapture readonly %a, i32 signext %n) #0 {<br>+entry:<br>+  %cmp24 = icmp sgt i32 %n, 0<br>+  br i1 %cmp24, label %for.cond1.preheader.lr.ph, label %for.end13<br>+<br>+for.cond1.preheader.lr.ph:                        ; preds = %entry<br>+  %0 = add i32 %n, -1<br>+  br label %for.cond1.preheader<br>+<br>+for.cond1.preheader:                              ; preds = %for.cond1.preheader.lr.ph, %for.body3<br>+  %indvars.iv = phi i64 [ 0, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next, %for.body3 ]<br>+  %sum.026 = phi double [ 0.000000e+00, %for.cond1.preheader.lr.ph ], [ %add10.2, %for.body3 ]<br>+  br label %for.body3<br>+<br>+for.body3:                                        ; preds = %for.cond1.preheader<br>+  %arrayidx5.realp = getelementptr inbounds [3 x { float, float }]* %a, i64 %indvars.iv, i64 0, i32 0<br>+  %arrayidx5.real = load float* %arrayidx5.realp, align 8<br>+  %arrayidx5.imagp = getelementptr inbounds [3 x { float, float }]* %a, i64 %indvars.iv, i64 0, i32 1<br>+  %arrayidx5.imag = load float* %arrayidx5.imagp, align 8<br>+  %mul = fmul fast float %arrayidx5.real, %arrayidx5.real<br>+  %mul9 = fmul fast float %arrayidx5.imag, %arrayidx5.imag<br>+  %add = fadd fast float %mul9, %mul<br>+  %conv = fpext float %add to double<br>+  %add10 = fadd fast double %conv, %sum.026<br>+  %arrayidx5.realp.1 = getelementptr inbounds [3 x { float, float }]* %a, i64 %indvars.iv, i64 1, i32 0<br>+  %arrayidx5.real.1 = load float* %arrayidx5.realp.1, align 8<br>+  %arrayidx5.imagp.1 = getelementptr inbounds [3 x { float, float }]* %a, i64 %indvars.iv, i64 1, i32 1<br>+  %arrayidx5.imag.1 = load float* %arrayidx5.imagp.1, align 8<br>+  %mul.1 = fmul fast float %arrayidx5.real.1, %arrayidx5.real.1<br>+  %mul9.1 = fmul fast float %arrayidx5.imag.1, %arrayidx5.imag.1<br>+  %add.1 = fadd fast float %mul9.1, %mul.1<br>+  %conv.1 = fpext float %add.1 to double<br>+  %add10.1 = fadd fast double %conv.1, %add10<br>+  %arrayidx5.realp.2 = getelementptr inbounds [3 x { float, float }]* %a, i64 %indvars.iv, i64 2, i32 0<br>+  %arrayidx5.real.2 = load float* %arrayidx5.realp.2, align 8<br>+  %arrayidx5.imagp.2 = getelementptr inbounds [3 x { float, float }]* %a, i64 %indvars.iv, i64 2, i32 1<br>+  %arrayidx5.imag.2 = load float* %arrayidx5.imagp.2, align 8<br>+  %mul.2 = fmul fast float %arrayidx5.real.2, %arrayidx5.real.2<br>+  %mul9.2 = fmul fast float %arrayidx5.imag.2, %arrayidx5.imag.2<br>+  %add.2 = fadd fast float %mul9.2, %mul.2<br>+  %conv.2 = fpext float %add.2 to double<br>+  %add10.2 = fadd fast double %conv.2, %add10.1<br>+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1<br>+  %lftr.wideiv = trunc i64 %indvars.iv to i32<br>+  %exitcond = icmp ne i32 %lftr.wideiv, %0<br>+  br i1 %exitcond, label %for.cond1.preheader, label %for.cond.for.end13_crit_edge<br>+<br>+for.cond.for.end13_crit_edge:                     ; preds = %for.body3<br>+  %add10.lcssa.lcssa = phi double [ %add10.2, %for.body3 ]<br>+  %phitmp = fptrunc double %add10.lcssa.lcssa to float<br>+  br label %for.end13<br>+<br>+for.end13:                                        ; preds = %for.cond.for.end13_crit_edge, %entry<br>+  %sum.0.lcssa = phi float [ %phitmp, %for.cond.for.end13_crit_edge ], [ 0.000000e+00, %entry ]<br>+  store float %sum.0.lcssa, float* %r, align 4<br>+  ret void<br>+}<br><br>EMAIL PREFERENCES<br>  <a href="http://reviews.llvm.org/settings/panel/emailpreferences/">http://reviews.llvm.org/settings/panel/emailpreferences/</a><br></font></div></div></div></font>