[PATCH][LoopVectorizer] Restrict the unroll factor of reductions in loops

James Molloy james at jamesmolloy.co.uk
Mon Aug 11 09:17:49 PDT 2014


Hi Arnold, Gerolf, Hal,

Good idea about a tuning option. Attached is a patch that implements that
tuning option. Is it OK to commit?

Gerolf, did you want me to add "|| isCyclone()" to
AArch64TargetTransformInfo?

Cheers,

James


On 11 August 2014 04:31, Gerolf Hoflehner <ghoflehner at apple.com> wrote:

> On Typhoon the gain for libquantum is almost 2%, and about one percent on
> hmmer. No regression on CINT2006. This is O3 LTO, ref input.
>
> -Gerolf
>
> On Aug 8, 2014, at 4:57 PM, Gerolf Hoflehner <ghoflehner at apple.com> wrote:
>
> > I second a tuning option at least in the short term. It is usually hard
> to get it right, though. So longer term this is a case for dynamic
> versioning that invokes different versions of the code at run-time
> depending on the trip count.
> >
> > -Gerolf
> >
> > On Aug 8, 2014, at 12:30 PM, Hal Finkel <hfinkel at anl.gov> wrote:
> >
> >> ----- Original Message -----
> >>> From: "James Molloy" <james.molloy at arm.com>
> >>> To: "Arnold Schwaighofer" <aschwaighofer at apple.com>
> >>> Cc: "llvm-commits" <llvm-commits at cs.uiuc.edu>
> >>> Sent: Friday, August 8, 2014 9:37:38 AM
> >>> Subject: [PATCH][LoopVectorizer] Restrict the unroll factor of
> reductions in        loops
> >>>
> >>>
> >>>
> >>>
> >>>
> >>> Hi Arnold,
> >>>
> >>>
> >>>
> >>> Attached are two patches. The first ups the maximum unroll factor on
> >>> AArch64 from 2 to 4, for C-A57 only at the moment as that’s all I’ve
> >>> got data for. This gives us significant wins – ~14% on
> >>> 462.libquantum at least.
> >>>
> >>>
> >>>
> >>> However it also causes some regressions. The second patch makes the
> >>> loop vectorizer a bit more conservative with its unroll factor. The
> >>> problem is purely for reductions within loops. The regressions I’ve
> >>> seen are small (but runtime-known) trip count loops within a loop
> >>> nest. A loop unroll factor of 2 is fine, but above 2 the reduction
> >>> variable fixup logic after the loop increases the critical path
> >>> length and resource usage. For most loops this isn’t a problem, but
> >>> small loops in a larger loop nest will execute this fixup code many
> >>> times.
> >>
> >> Can you please add a flag for this? I anticipate needing to tune it.
> >>
> >> Also, it seems to me that this is exactly the kind of thing that would
> benefit from profiling information (so we can determine if the inner loop
> is likely to have a large trip count). Can the current infrastructure do
> this? Also, maybe in cases where the inner loop count is not a function of
> the outer loop, we might 'unswitch' it so that we get the unrolled inner
> loop only when actually profitable.
> >>
> >> Thanks again,
> >> Hal
> >>
> >>>
> >>>
> >>>
> >>> The heuristic is: if this is a (scalar) reduction, and the loop is
> >>> nested, clamp the UF to a maximum of 2. With 2, we still get wins
> >>> but we only add one fadd/fmul to the critical path.
> >>>
> >>>
> >>>
> >>> Please take a look.
> >>>
> >>>
> >>>
> >>> Cheers,
> >>>
> >>>
> >>>
> >>> James
> >>> _______________________________________________
> >>> llvm-commits mailing list
> >>> llvm-commits at cs.uiuc.edu
> >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> >>>
> >>
> >> --
> >> Hal Finkel
> >> Assistant Computational Scientist
> >> Leadership Computing Facility
> >> Argonne National Laboratory
> >>
> >> _______________________________________________
> >> llvm-commits mailing list
> >> llvm-commits at cs.uiuc.edu
> >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> >
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140811/41d077b1/attachment.html>
-------------- next part --------------
Index: lib/Transforms/Vectorize/LoopVectorize.cpp
===================================================================
--- lib/Transforms/Vectorize/LoopVectorize.cpp	(revision 215117)
+++ lib/Transforms/Vectorize/LoopVectorize.cpp	(working copy)
@@ -204,6 +204,11 @@
     "enable-cond-stores-vec", cl::init(false), cl::Hidden,
     cl::desc("Enable if predication of stores during vectorization."));
 
+static cl::opt<unsigned> MaxNestedScalarReductionUF(
+    "max-nested-scalar-reduction-unroll", cl::init(2), cl::Hidden,
+    cl::desc("The maximum unroll factor to use when unrolling a scalar "
+             "reduction in a nested loop."));
+
 namespace {
 
 // Forward declarations.
@@ -5545,6 +5550,18 @@
     unsigned StoresUF = UF / (Legal->NumStores ? Legal->NumStores : 1);
     unsigned LoadsUF = UF /  (Legal->NumLoads ? Legal->NumLoads : 1);
 
+    // If we have a scalar reduction (vector reductions are already dealt with
+    // by this point), we can increase the critical path length if the loop
+    // we're unrolling is inside another loop. Limit, by default to 2, so the
+    // critical path only gets increased by one reduction operation.
+    if (Legal->getReductionVars()->size() &&
+        TheLoop->getLoopDepth() > 1) {
+      unsigned F = static_cast<unsigned>(MaxNestedScalarReductionUF);
+      SmallUF = std::min(SmallUF, F);
+      StoresUF = std::min(StoresUF, F);
+      LoadsUF = std::min(LoadsUF, F);
+    }
+
     if (EnableLoadStoreRuntimeUnroll && std::max(StoresUF, LoadsUF) > SmallUF) {
       DEBUG(dbgs() << "LV: Unrolling to saturate store or load ports.\n");
       return std::max(StoresUF, LoadsUF);
-------------- next part --------------
Index: lib/Target/AArch64/AArch64TargetTransformInfo.cpp
===================================================================
--- lib/Target/AArch64/AArch64TargetTransformInfo.cpp	(revision 215117)
+++ lib/Target/AArch64/AArch64TargetTransformInfo.cpp	(working copy)
@@ -104,7 +104,7 @@
     return 64;
   }
 
-  unsigned getMaximumUnrollFactor() const override { return 2; }
+  unsigned getMaximumUnrollFactor() const override;
 
   unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const
       override;
@@ -513,3 +513,9 @@
   }
   return Cost;
 }
+
+unsigned AArch64TTI::getMaximumUnrollFactor() const {
+  if (ST->isCortexA57())
+    return 4;
+  return 2;
+}


More information about the llvm-commits mailing list