[llvm] r348944 - [Unroll/UnrollAndJam/Vectorizer/Distribute] Add followup loop attributes.

Jordan Rupprecht via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 13 15:12:26 PST 2018


It seems the bitcode is identical (just removing -Werror and ignoring the
warning), so it's just that the error is firing more often than before --
not sure if it's a false positive, or if it's something that should have
been firing before. Still looking...

On Thu, Dec 13, 2018 at 2:01 PM Jordan Rupprecht <rupprecht at google.com>
wrote:

> The code in question is actually using #pragma unroll, not unroll_and_jam.
> Here's a reduced test case (creduce may have gone too far, but this might
> be enough to figure out what's going on...):
> $ cat reduced.cc
> char c;
> class f {
>  public:
>   template <typename b>
>   void g(int, b i) {
> #pragma unroll
>     for (int e = 0;;) i(e, &c);
>   }
> };
> class j {
>  public:
>   j(bool);
>   bool k() {
>     (*this)({});
>     return true;
>   }
>   void operator()(int) {
>     auto d = [](int, char *) {};
>     h.g(0, d);
>   }
>   f h;
> };
> void l() {
>   j a(false);
>   a.k();
> }
> $ /path/to/clang++ -Werror -O1 -c reduced.cc
> reduced.cc:5:8: error: loop not unrolled: the optimizer was unable to
> perform the requested transformation; the transformation might be disabled
> or specified as part of an unsupported transformation ordering
>       [-Werror,-Wpass-failed=transform-warning]
>   void g(int, b i) {
>
>
> On Thu, Dec 13, 2018 at 8:21 AM Michael Kruse <llvm at meinersbur.de> wrote:
>
>> Yes, additional warnings are expected. For instance, #pragma
>> unroll_and_jam should trigger such a warning since the
>> LoopUnrollAndJam pass is not in the default pipeline. However,
>> LoopUnroll should always be present and may indeed not have unrolled
>> the loop (although atm I cannot think of a reason why it should). A
>> reduced test case would be useful.
>>
>> Michael
>>
>> Am Do., 13. Dez. 2018 um 09:58 Uhr schrieb Jordan Rupprecht
>> <rupprecht at google.com>:
>> >
>> > I'm seeing a new error in some internal code (loop not unrolled: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering [-Werror,-Wpass-failed=transform-warning]). Is it
>> expected that this patch can trigger warnings in more cases? I couldn't
>> figure that out from the patch description. I think we're using the new
>> pass manager, fwiw.
>> >
>> > I'll see if I can reduce the internal test case to something that I can
>> report back on this list in a bit.
>> >
>> > On Wed, Dec 12, 2018 at 9:36 AM Michael Kruse via llvm-commits <
>> llvm-commits at lists.llvm.org> wrote:
>> >>
>> >> Author: meinersbur
>> >> Date: Wed Dec 12 09:32:52 2018
>> >> New Revision: 348944
>> >>
>> >> URL: http://llvm.org/viewvc/llvm-project?rev=348944&view=rev
>> >> Log:
>> >> [Unroll/UnrollAndJam/Vectorizer/Distribute] Add followup loop
>> attributes.
>> >>
>> >> When multiple loop transformation are defined in a loop's metadata,
>> their order of execution is defined by the order of their respective passes
>> in the pass pipeline. For instance, e.g.
>> >>
>> >>     #pragma clang loop unroll_and_jam(enable)
>> >>     #pragma clang loop distribute(enable)
>> >>
>> >> is the same as
>> >>
>> >>     #pragma clang loop distribute(enable)
>> >>     #pragma clang loop unroll_and_jam(enable)
>> >>
>> >> and will try to loop-distribute before Unroll-And-Jam because the
>> LoopDistribute pass is scheduled after UnrollAndJam pass. UnrollAndJamPass
>> only supports one inner loop, i.e. it will necessarily fail after loop
>> distribution. It is not possible to specify another execution order. Also,t
>> the order of passes in the pipeline is subject to change between versions
>> of LLVM, optimization options and which pass manager is used.
>> >>
>> >> This patch adds 'followup' attributes to various loop transformation
>> passes. These attributes define which attributes the resulting loop of a
>> transformation should have. For instance,
>> >>
>> >>     !0 = !{!0, !1, !2}
>> >>     !1 = !{!"llvm.loop.unroll_and_jam.enable"}
>> >>     !2 = !{!"llvm.loop.unroll_and_jam.followup_inner", !3}
>> >>     !3 = !{!"llvm.loop.distribute.enable"}
>> >>
>> >> defines a loop ID (!0) to be unrolled-and-jammed (!1) and then the
>> attribute !3 to be added to the jammed inner loop, which contains the
>> instruction to distribute the inner loop.
>> >>
>> >> Currently, in both pass managers, pass execution is in a fixed order
>> and UnrollAndJamPass will not execute again after LoopDistribute. We hope
>> to fix this in the future by allowing pass managers to run passes until a
>> fixpoint is reached, use Polly to perform these transformations, or add a
>> loop transformation pass which takes the order issue into account.
>> >>
>> >> For mandatory/forced transformations (e.g. by having been declared by
>> #pragma omp simd), the user must be notified when a transformation could
>> not be performed. It is not possible that the responsible pass emits such a
>> warning because the transformation might be 'hidden' in a followup
>> attribute when it is executed, or it is not present in the pipeline at all.
>> For this reason, this patche introduces a WarnMissedTransformations pass,
>> to warn about orphaned transformations.
>> >>
>> >> Since this changes the user-visible diagnostic message when a
>> transformation is applied, two test cases in the clang repository need to
>> be updated.
>> >>
>> >> To ensure that no other transformation is executed before the intended
>> one, the attribute `llvm.loop.disable_nonforced` can be added which should
>> disable transformation heuristics before the intended transformation is
>> applied. E.g. it would be surprising if a loop is distributed before a
>> #pragma unroll_and_jam is applied.
>> >>
>> >> With more supported code transformations (loop fusion, interchange,
>> stripmining, offloading, etc.), transformations can be used as building
>> blocks for more complex transformations (e.g.
>> stripmining+stripmining+interchange -> tiling).
>> >>
>> >> Reviewed By: hfinkel, dmgreen
>> >>
>> >> Differential Revision: https://reviews.llvm.org/D49281
>> >> Differential Revision: https://reviews.llvm.org/D55288
>> >>
>> >> Added:
>> >>     llvm/trunk/docs/TransformMetadata.rst
>> >>     llvm/trunk/include/llvm/Transforms/Scalar/WarnMissedTransforms.h
>> >>     llvm/trunk/lib/Transforms/Scalar/WarnMissedTransforms.cpp
>> >>     llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced_enable.ll
>> >>     llvm/trunk/test/Transforms/LoopDistribute/followup.ll
>> >>     llvm/trunk/test/Transforms/LoopTransformWarning/
>> >>
>>  llvm/trunk/test/Transforms/LoopTransformWarning/distribution-remarks-missed.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopTransformWarning/unrollandjam-remarks-missed.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopTransformWarning/unrolling-remarks-missed.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopTransformWarning/vectorization-remarks-missed.ll
>> >>     llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced.ll
>> >>     llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_count.ll
>> >>     llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_enable.ll
>> >>     llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_full.ll
>> >>     llvm/trunk/test/Transforms/LoopUnroll/followup.ll
>> >>     llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_count.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_enable.ll
>> >>     llvm/trunk/test/Transforms/LoopUnrollAndJam/followup.ll
>> >>     llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced_enable.ll
>> >>     llvm/trunk/test/Transforms/LoopVectorize/followup.ll
>> >> Modified:
>> >>     llvm/trunk/docs/LangRef.rst
>> >>     llvm/trunk/docs/Passes.rst
>> >>     llvm/trunk/docs/index.rst
>> >>     llvm/trunk/include/llvm/InitializePasses.h
>> >>     llvm/trunk/include/llvm/LinkAllPasses.h
>> >>     llvm/trunk/include/llvm/Transforms/Scalar.h
>> >>     llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
>> >>     llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
>> >>
>>  llvm/trunk/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
>> >>     llvm/trunk/lib/Analysis/LoopInfo.cpp
>> >>     llvm/trunk/lib/Passes/PassBuilder.cpp
>> >>     llvm/trunk/lib/Passes/PassRegistry.def
>> >>     llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
>> >>     llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt
>> >>     llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp
>> >>     llvm/trunk/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp
>> >>     llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
>> >>     llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp
>> >>     llvm/trunk/lib/Transforms/Scalar/Scalar.cpp
>> >>     llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
>> >>     llvm/trunk/lib/Transforms/Utils/LoopUnrollAndJam.cpp
>> >>     llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp
>> >>     llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
>> >>     llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>> >>     llvm/trunk/test/Other/new-pm-defaults.ll
>> >>     llvm/trunk/test/Other/new-pm-thinlto-defaults.ll
>> >>     llvm/trunk/test/Other/opt-O2-pipeline.ll
>> >>     llvm/trunk/test/Other/opt-O3-pipeline.ll
>> >>     llvm/trunk/test/Other/opt-Os-pipeline.ll
>> >>     llvm/trunk/test/Other/opt-hot-cold-split.ll
>> >>     llvm/trunk/test/Transforms/LoopUnrollAndJam/pragma.ll
>> >>
>>  llvm/trunk/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll
>> >>     llvm/trunk/test/Transforms/LoopVectorize/no_array_bounds.ll
>> >>     llvm/trunk/test/Transforms/LoopVectorize/no_switch.ll
>> >>
>> >> Modified: llvm/trunk/docs/LangRef.rst
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/docs/LangRef.rst (original)
>> >> +++ llvm/trunk/docs/LangRef.rst Wed Dec 12 09:32:52 2018
>> >> @@ -5076,6 +5076,8 @@ optimizations related to compare and bra
>> >>  is treated as a boolean value; if it exists, it signals that the
>> branch
>> >>  or switch that it is attached to is completely unpredictable.
>> >>
>> >> +.. _llvm.loop:
>> >> +
>> >>  '``llvm.loop``'
>> >>  ^^^^^^^^^^^^^^^
>> >>
>> >> @@ -5109,6 +5111,26 @@ suggests an unroll factor to the loop un
>> >>      !0 = !{!0, !1}
>> >>      !1 = !{!"llvm.loop.unroll.count", i32 4}
>> >>
>> >> +'``llvm.loop.disable_nonforced``'
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata disables all optional loop transformations unless
>> >> +explicitly instructed using other transformation metdata such as
>> >> +``llvm.loop.unroll.enable''. That is, no heuristic will try to
>> determine
>> >> +whether a transformation is profitable. The purpose is to avoid that
>> the
>> >> +loop is transformed to a different loop before an explicitly requested
>> >> +(forced) transformation is applied. For instance, loop fusion can make
>> >> +other transformations impossible. Mandatory loop canonicalizations
>> such
>> >> +as loop rotation are still applied.
>> >> +
>> >> +It is recommended to use this metadata in addition to any llvm.loop.*
>> >> +transformation directive. Also, any loop should have at most one
>> >> +directive applied to it (and a sequence of transformations built using
>> >> +followup-attributes). Otherwise, which transformation will be applied
>> >> +depends on implementation details such as the pass pipeline order.
>> >> +
>> >> +See :ref:`transformation-metadata` for details.
>> >> +
>> >>  '``llvm.loop.vectorize``' and '``llvm.loop.interleave``'
>> >>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >>
>> >> @@ -5167,6 +5189,29 @@ vectorization of the loop. If ``llvm.loo
>> >>  0 or if the loop does not have this metadata the width will be
>> >>  determined automatically.
>> >>
>> >> +'``llvm.loop.vectorize.followup_vectorized``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which loop attributes the vectorized loop will
>> >> +have. See :ref:`transformation-metadata` for details.
>> >> +
>> >> +'``llvm.loop.vectorize.followup_epilogue``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which loop attributes the epilogue will have.
>> The
>> >> +epilogue is not vectorized and is executed when either the vectorized
>> >> +loop is not known to preserve semantics (because e.g., it processes
>> two
>> >> +arrays that are found to alias by a runtime check) or for the last
>> >> +iterations that do not fill a complete set of vector lanes. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >> +'``llvm.loop.vectorize.followup_all``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +Attributes in the metadata will be added to both the vectorized and
>> >> +epilogue loop.
>> >> +See :ref:`Transformation Metadata <transformation-metadata>` for
>> details.
>> >> +
>> >>  '``llvm.loop.unroll``'
>> >>  ^^^^^^^^^^^^^^^^^^^^^^
>> >>
>> >> @@ -5235,6 +5280,19 @@ For example:
>> >>
>> >>     !0 = !{!"llvm.loop.unroll.full"}
>> >>
>> >> +'``llvm.loop.unroll.followup``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which loop attributes the unrolled loop will
>> have.
>> >> +See :ref:`Transformation Metadata <transformation-metadata>` for
>> details.
>> >> +
>> >> +'``llvm.loop.unroll.followup_remainder``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which loop attributes the remainder loop after
>> >> +partial/runtime unrolling will have. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >>  '``llvm.loop.unroll_and_jam``'
>> >>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >>
>> >> @@ -5288,6 +5346,43 @@ string ``llvm.loop.unroll_and_jam.enable
>> >>
>> >>     !0 = !{!"llvm.loop.unroll_and_jam.enable"}
>> >>
>> >> +'``llvm.loop.unroll_and_jam.followup_outer``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which loop attributes the outer unrolled loop
>> will
>> >> +have. See :ref:`Transformation Metadata <transformation-metadata>` for
>> >> +details.
>> >> +
>> >> +'``llvm.loop.unroll_and_jam.followup_inner``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which loop attributes the inner jammed loop will
>> >> +have. See :ref:`Transformation Metadata <transformation-metadata>` for
>> >> +details.
>> >> +
>> >> +'``llvm.loop.unroll_and_jam.followup_remainder_outer``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which attributes the epilogue of the outer loop
>> >> +will have. This loop is usually unrolled, meaning there is no such
>> >> +loop. This attribute will be ignored in this case. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >> +'``llvm.loop.unroll_and_jam.followup_remainder_inner``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which attributes the inner loop of the epilogue
>> >> +will have. The outer epilogue will usually be unrolled, meaning there
>> >> +can be multiple inner remainder loops. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >> +'``llvm.loop.unroll_and_jam.followup_all``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +Attributes specified in the metadata is added to all
>> >> +``llvm.loop.unroll_and_jam.*`` loops. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >>  '``llvm.loop.licm_versioning.disable``' Metadata
>> >>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >>
>> >> @@ -5320,6 +5415,34 @@ enabled. A value of 0 disables distribut
>> >>  This metadata should be used in conjunction with ``llvm.loop`` loop
>> >>  identification metadata.
>> >>
>> >> +'``llvm.loop.distribute.followup_coincident``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which attributes extracted loops with no cyclic
>> >> +dependencies will have (i.e. can be vectorized). See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >> +'``llvm.loop.distribute.followup_sequential``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +This metadata defines which attributes the isolated loops with unsafe
>> >> +memory dependencies will have. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >> +'``llvm.loop.distribute.followup_fallback``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +If loop versioning is necessary, this metadata defined the attributes
>> >> +the non-distributed fallback version will have. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >> +'``llvm.loop.distribute.followup_all``' Metadata
>> >> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >> +
>> >> +Thes attributes in this metdata is added to all followup loops of the
>> >> +loop distribution pass. See
>> >> +:ref:`Transformation Metadata <transformation-metadata>` for details.
>> >> +
>> >>  '``llvm.mem``'
>> >>  ^^^^^^^^^^^^^^^
>> >>
>> >>
>> >> Modified: llvm/trunk/docs/Passes.rst
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Passes.rst?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/docs/Passes.rst (original)
>> >> +++ llvm/trunk/docs/Passes.rst Wed Dec 12 09:32:52 2018
>> >> @@ -1224,3 +1224,8 @@ Displays the post dominator tree using t
>> >>  Displays the post dominator tree using the GraphViz tool, but
>> omitting function
>> >>  bodies.
>> >>
>> >> +``-transform-warning``: Report missed forced transformations
>> >> +------------------------------------------------------------
>> >> +
>> >> +Emits warnings about not yet applied forced transformations (e.g. from
>> >> +``#pragma omp simd``).
>> >>
>> >> Added: llvm/trunk/docs/TransformMetadata.rst
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TransformMetadata.rst?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/docs/TransformMetadata.rst (added)
>> >> +++ llvm/trunk/docs/TransformMetadata.rst Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,441 @@
>> >> +.. _transformation-metadata:
>> >> +
>> >> +============================
>> >> +Code Transformation Metadata
>> >> +============================
>> >> +
>> >> +.. contents::
>> >> +   :local:
>> >> +
>> >> +Overview
>> >> +========
>> >> +
>> >> +LLVM transformation passes can be controlled by attaching metadata to
>> >> +the code to transform. By default, transformation passes use
>> heuristics
>> >> +to determine whether or not to perform transformations, and when doing
>> >> +so, other details of how the transformations are applied (e.g., which
>> >> +vectorization factor to select).
>> >> +Unless the optimizer is otherwise directed, transformations are
>> applied
>> >> +conservatively. This conservatism generally allows the optimizer to
>> >> +avoid unprofitable transformations, but in practice, this results in
>> the
>> >> +optimizer not applying transformations that would be highly
>> profitable.
>> >> +
>> >> +Frontends can give additional hints to LLVM passes on which
>> >> +transformations they should apply. This can be additional knowledge
>> that
>> >> +cannot be derived from the emitted IR, or directives passed from the
>> >> +user/programmer. OpenMP pragmas are an example of the latter.
>> >> +
>> >> +If any such metadata is dropped from the program, the code's semantics
>> >> +must not change.
>> >> +
>> >> +Metadata on Loops
>> >> +=================
>> >> +
>> >> +Attributes can be attached to loops as described in :ref:`llvm.loop`.
>> >> +Attributes can describe properties of the loop, disable
>> transformations,
>> >> +force specific transformations and set transformation options.
>> >> +
>> >> +Because metadata nodes are immutable (with the exception of
>> >> +``MDNode::replaceOperandWith`` which is dangerous to use on uniqued
>> >> +metadata), in order to add or remove a loop attributes, a new
>> ``MDNode``
>> >> +must be created and assigned as the new ``llvm.loop`` metadata. Any
>> >> +connection between the old ``MDNode`` and the loop is lost. The
>> >> +``llvm.loop`` node is also used as LoopID (``Loop::getLoopID()``),
>> i.e.
>> >> +the loop effectively gets a new identifier. For instance,
>> >> +``llvm.mem.parallel_loop_access`` references the LoopID. Therefore, if
>> >> +the parallel access property is to be preserved after adding/removing
>> >> +loop attributes, any ``llvm.mem.parallel_loop_access`` reference must
>> be
>> >> +updated to the new LoopID.
>> >> +
>> >> +Transformation Metadata Structure
>> >> +=================================
>> >> +
>> >> +Some attributes describe code transformations (unrolling, vectorizing,
>> >> +loop distribution, etc.). They can either be a hint to the optimizer
>> >> +that a transformation might be beneficial, instruction to use a
>> specific
>> >> +option, , or convey a specific request from the user (such as
>> >> +``#pragma clang loop`` or ``#pragma omp simd``).
>> >> +
>> >> +If a transformation is forced but cannot be carried-out for any
>> reason,
>> >> +an optimization-missed warning must be emitted. Semantic information
>> >> +such as a transformation being safe (e.g.
>> >> +``llvm.mem.parallel_loop_access``) can be unused by the optimizer
>> >> +without generating a warning.
>> >> +
>> >> +Unless explicitly disabled, any optimization pass may heuristically
>> >> +determine whether a transformation is beneficial and apply it. If
>> >> +metadata for another transformation was specified, applying a
>> different
>> >> +transformation before it might be inadvertent due to being applied on
>> a
>> >> +different loop or the loop not existing anymore. To avoid having to
>> >> +explicitly disable an unknown number of passes, the attribute
>> >> +``llvm.loop.disable_nonforced`` disables all optional, high-level,
>> >> +restructuring transformations.
>> >> +
>> >> +The following example avoids the loop being altered before being
>> >> +vectorized, for instance being unrolled.
>> >> +
>> >> +.. code-block:: llvm
>> >> +
>> >> +      br i1 %exitcond, label %for.exit, label %for.header, !llvm.loop
>> !0
>> >> +    ...
>> >> +    !0 = distinct !{!0, !1, !2}
>> >> +    !1 = !{!"llvm.loop.vectorize.enable", i1 true}
>> >> +    !2 = !{!"llvm.loop.disable_nonforced"}
>> >> +
>> >> +After a transformation is applied, follow-up attributes are set on the
>> >> +transformed and/or new loop(s). This allows additional attributes
>> >> +including followup-transformations to be specified. Specifying
>> multiple
>> >> +transformations in the same metadata node is possible for
>> compatibility
>> >> +reasons, but their execution order is undefined. For instance, when
>> >> +``llvm.loop.vectorize.enable`` and ``llvm.loop.unroll.enable`` are
>> >> +specified at the same time, unrolling may occur either before or after
>> >> +vectorization.
>> >> +
>> >> +As an example, the following instructs a loop to be vectorized and
>> only
>> >> +then unrolled.
>> >> +
>> >> +.. code-block:: llvm
>> >> +
>> >> +    !0 = distinct !{!0, !1, !2, !3}
>> >> +    !1 = !{!"llvm.loop.vectorize.enable", i1 true}
>> >> +    !2 = !{!"llvm.loop.disable_nonforced"}
>> >> +    !3 = !{!"llvm.loop.vectorize.followup_vectorized",
>> !{"llvm.loop.unroll.enable"}}
>> >> +
>> >> +If, and only if, no followup is specified, the pass may add
>> attributes itself.
>> >> +For instance, the vectorizer adds a ``llvm.loop.isvectorized``
>> attribute and
>> >> +all attributes from the original loop excluding its loop vectorizer
>> >> +attributes. To avoid this, an empty followup attribute can be used,
>> e.g.
>> >> +
>> >> +.. code-block:: llvm
>> >> +
>> >> +    !3 = !{!"llvm.loop.vectorize.followup_vectorized"}
>> >> +
>> >> +The followup attributes of a transformation that cannot be applied
>> will
>> >> +never be added to a loop and are therefore effectively ignored. This
>> means
>> >> +that any followup-transformation in such attributes requires that its
>> >> +prior transformations are applied before the followup-transformation.
>> >> +The user should receive a warning about the first transformation in
>> the
>> >> +transformation chain that could not be applied if it a forced
>> >> +transformation. All following transformations are skipped.
>> >> +
>> >> +Pass-Specific Transformation Metadata
>> >> +=====================================
>> >> +
>> >> +Transformation options are specific to each transformation. In the
>> >> +following, we present the model for each LLVM loop optimization pass
>> and
>> >> +the metadata to influence them.
>> >> +
>> >> +Loop Vectorization and Interleaving
>> >> +-----------------------------------
>> >> +
>> >> +Loop vectorization and interleaving is interpreted as a single
>> >> +transformation. It is interpreted as forced if
>> >> +``!{"llvm.loop.vectorize.enable", i1 true}`` is set.
>> >> +
>> >> +Assuming the pre-vectorization loop is
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    for (int i = 0; i < n; i+=1) // original loop
>> >> +      Stmt(i);
>> >> +
>> >> +then the code after vectorization will be approximately (assuming an
>> >> +SIMD width of 4):
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    int i = 0;
>> >> +    if (rtc) {
>> >> +      for (; i + 3 < n; i+=4) // vectorized/interleaved loop
>> >> +        Stmt(i:i+3);
>> >> +    }
>> >> +    for (; i < n; i+=1) // epilogue loop
>> >> +      Stmt(i);
>> >> +
>> >> +where ``rtc`` is a generated runtime check.
>> >> +
>> >> +``llvm.loop.vectorize.followup_vectorized`` will set the attributes
>> for
>> >> +the vectorized loop. If not specified, ``llvm.loop.isvectorized`` is
>> >> +combined with the original loop's attributes to avoid it being
>> >> +vectorized multiple times.
>> >> +
>> >> +``llvm.loop.vectorize.followup_epilogue`` will set the attributes for
>> >> +the remainder loop. If not specified, it will have the original loop's
>> >> +attributes combined with ``llvm.loop.isvectorized`` and
>> >> +``llvm.loop.unroll.runtime.disable`` (unless the original loop already
>> >> +has unroll metadata).
>> >> +
>> >> +The attributes specified by ``llvm.loop.vectorize.followup_all`` are
>> >> +added to both loops.
>> >> +
>> >> +When using a follow-up attribute, it replaces any automatically
>> deduced
>> >> +attributes for the generated loop in question. Therefore it is
>> >> +recommended to add ``llvm.loop.isvectorized`` to
>> >> +``llvm.loop.vectorize.followup_all`` which avoids that the loop
>> >> +vectorizer tries to optimize the loops again.
>> >> +
>> >> +Loop Unrolling
>> >> +--------------
>> >> +
>> >> +Unrolling is interpreted as forced any
>> ``!{!"llvm.loop.unroll.enable"}``
>> >> +metadata or option (``llvm.loop.unroll.count``,
>> ``llvm.loop.unroll.full``)
>> >> +is present. Unrolling can be full unrolling, partial unrolling of a
>> loop
>> >> +with constant trip count or runtime unrolling of a loop with a trip
>> >> +count unknown at compile-time.
>> >> +
>> >> +If the loop has been unrolled fully, there is no followup-loop. For
>> >> +partial/runtime unrolling, the original loop of
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    for (int i = 0; i < n; i+=1) // original loop
>> >> +      Stmt(i);
>> >> +
>> >> +is transformed into (using an unroll factor of 4):
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    int i = 0;
>> >> +    for (; i + 3 < n; i+=4) // unrolled loop
>> >> +      Stmt(i);
>> >> +      Stmt(i+1);
>> >> +      Stmt(i+2);
>> >> +      Stmt(i+3);
>> >> +    }
>> >> +    for (; i < n; i+=1) // remainder loop
>> >> +      Stmt(i);
>> >> +
>> >> +``llvm.loop.unroll.followup_unrolled`` will set the loop attributes of
>> >> +the unrolled loop. If not specified, the attributes of the original
>> loop
>> >> +without the ``llvm.loop.unroll.*`` attributes are copied and
>> >> +``llvm.loop.unroll.disable`` added to it.
>> >> +
>> >> +``llvm.loop.unroll.followup_remainder`` defines the attributes of the
>> >> +remainder loop. If not specified the remainder loop will have no
>> >> +attributes. The remainder loop might not be present due to being fully
>> >> +unrolled in which case this attribute has no effect.
>> >> +
>> >> +Attributes defined in ``llvm.loop.unroll.followup_all`` are added to
>> the
>> >> +unrolled and remainder loops.
>> >> +
>> >> +To avoid that the partially unrolled loop is unrolled again, it is
>> >> +recommended to add ``llvm.loop.unroll.disable`` to
>> >> +``llvm.loop.unroll.followup_all``. If no follow-up attribute specified
>> >> +for a generated loop, it is added automatically.
>> >> +
>> >> +Unroll-And-Jam
>> >> +--------------
>> >> +
>> >> +Unroll-and-jam uses the following transformation model (here with an
>> >> +unroll factor if 2). Currently, it does not support a fallback version
>> >> +when the transformation is unsafe.
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    for (int i = 0; i < n; i+=1) { // original outer loop
>> >> +      Fore(i);
>> >> +      for (int j = 0; j < m; j+=1) // original inner loop
>> >> +        SubLoop(i, j);
>> >> +      Aft(i);
>> >> +    }
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    int i = 0;
>> >> +    for (; i + 1 < n; i+=2) { // unrolled outer loop
>> >> +      Fore(i);
>> >> +      Fore(i+1);
>> >> +      for (int j = 0; j < m; j+=1) { // unrolled inner loop
>> >> +        SubLoop(i, j);
>> >> +        SubLoop(i+1, j);
>> >> +      }
>> >> +      Aft(i);
>> >> +      Aft(i+1);
>> >> +    }
>> >> +    for (; i < n; i+=1) { // remainder outer loop
>> >> +      Fore(i);
>> >> +      for (int j = 0; j < m; j+=1) // remainder inner loop
>> >> +        SubLoop(i, j);
>> >> +      Aft(i);
>> >> +    }
>> >> +
>> >> +``llvm.loop.unroll_and_jam.followup_outer`` will set the loop
>> attributes
>> >> +of the unrolled outer loop. If not specified, the attributes of the
>> >> +original outer loop without the ``llvm.loop.unroll.*`` attributes are
>> >> +copied and ``llvm.loop.unroll.disable`` added to it.
>> >> +
>> >> +``llvm.loop.unroll_and_jam.followup_inner`` will set the loop
>> attributes
>> >> +of the unrolled inner loop. If not specified, the attributes of the
>> >> +original inner loop are used unchanged.
>> >> +
>> >> +``llvm.loop.unroll_and_jam.followup_remainder_outer`` sets the loop
>> >> +attributes of the outer remainder loop. If not specified it will not
>> >> +have any attributes. The remainder loop might not be present due to
>> >> +being fully unrolled.
>> >> +
>> >> +``llvm.loop.unroll_and_jam.followup_remainder_inner`` sets the loop
>> >> +attributes of the inner remainder loop. If not specified it will have
>> >> +the attributes of the original inner loop. It the outer remainder loop
>> >> +is unrolled, the inner remainder loop might be present multiple times.
>> >> +
>> >> +Attributes defined in ``llvm.loop.unroll_and_jam.followup_all`` are
>> >> +added to all of the aforementioned output loops.
>> >> +
>> >> +To avoid that the unrolled loop is unrolled again, it is
>> >> +recommended to add ``llvm.loop.unroll.disable`` to
>> >> +``llvm.loop.unroll_and_jam.followup_all``. It suppresses
>> unroll-and-jam
>> >> +as well as an additional inner loop unrolling. If no follow-up
>> >> +attribute specified for a generated loop, it is added automatically.
>> >> +
>> >> +Loop Distribution
>> >> +-----------------
>> >> +
>> >> +The LoopDistribution pass tries to separate vectorizable parts of a
>> loop
>> >> +from the non-vectorizable part (which otherwise would make the entire
>> >> +loop non-vectorizable). Conceptually, it transforms a loop such as
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    for (int i = 1; i < n; i+=1) { // original loop
>> >> +      A[i] = i;
>> >> +      B[i] = 2 + B[i];
>> >> +      C[i] = 3 + C[i - 1];
>> >> +    }
>> >> +
>> >> +into the following code:
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    if (rtc) {
>> >> +      for (int i = 1; i < n; i+=1) // coincident loop
>> >> +        A[i] = i;
>> >> +      for (int i = 1; i < n; i+=1) // coincident loop
>> >> +        B[i] = 2 + B[i];
>> >> +      for (int i = 1; i < n; i+=1) // sequential loop
>> >> +        C[i] = 3 + C[i - 1];
>> >> +    } else {
>> >> +      for (int i = 1; i < n; i+=1) { // fallback loop
>> >> +        A[i] = i;
>> >> +        B[i] = 2 + B[i];
>> >> +        C[i] = 3 + C[i - 1];
>> >> +      }
>> >> +    }
>> >> +
>> >> +where ``rtc`` is a generated runtime check.
>> >> +
>> >> +``llvm.loop.distribute.followup_coincident`` sets the loop attributes
>> of
>> >> +all loops without loop-carried dependencies (i.e. vectorizable loops).
>> >> +There might be more than one such loops. If not defined, the loops
>> will
>> >> +inherit the original loop's attributes.
>> >> +
>> >> +``llvm.loop.distribute.followup_sequential`` sets the loop attributes
>> of the
>> >> +loop with potentially unsafe dependencies. There should be at most one
>> >> +such loop. If not defined, the loop will inherit the original loop's
>> >> +attributes.
>> >> +
>> >> +``llvm.loop.distribute.followup_fallback`` defines the loop attributes
>> >> +for the fallback loop, which is a copy of the original loop for when
>> >> +loop versioning is required. If undefined, the fallback loop inherits
>> >> +all attributes from the original loop.
>> >> +
>> >> +Attributes defined in ``llvm.loop.distribute.followup_all`` are added
>> to
>> >> +all of the aforementioned output loops.
>> >> +
>> >> +It is recommended to add ``llvm.loop.disable_nonforced`` to
>> >> +``llvm.loop.distribute.followup_fallback``. This avoids that the
>> >> +fallback version (which is likely never executed) is further optimzed
>> >> +which would increase the code size.
>> >> +
>> >> +Versioning LICM
>> >> +---------------
>> >> +
>> >> +The pass hoists code out of loops that are only loop-invariant when
>> >> +dynamic conditions apply. For instance, it transforms the loop
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    for (int i = 0; i < n; i+=1) // original loop
>> >> +      A[i] = B[0];
>> >> +
>> >> +into:
>> >> +
>> >> +.. code-block:: c
>> >> +
>> >> +    if (rtc) {
>> >> +      auto b = B[0];
>> >> +      for (int i = 0; i < n; i+=1) // versioned loop
>> >> +        A[i] = b;
>> >> +    } else {
>> >> +      for (int i = 0; i < n; i+=1) // unversioned loop
>> >> +        A[i] = B[0];
>> >> +    }
>> >> +
>> >> +The runtime condition (``rtc``) checks that the array ``A`` and the
>> >> +element `B[0]` do not alias.
>> >> +
>> >> +Currently, this transformation does not support followup-attributes.
>> >> +
>> >> +Loop Interchange
>> >> +----------------
>> >> +
>> >> +Currently, the ``LoopInterchange`` pass does not use any metadata.
>> >> +
>> >> +Ambiguous Transformation Order
>> >> +==============================
>> >> +
>> >> +If there multiple transformations defined, the order in which they are
>> >> +executed depends on the order in LLVM's pass pipeline, which is
>> subject
>> >> +to change. The default optimization pipeline (anything higher than
>> >> +``-O0``) has the following order.
>> >> +
>> >> +When using the legacy pass manager:
>> >> +
>> >> + - LoopInterchange (if enabled)
>> >> + - SimpleLoopUnroll/LoopFullUnroll (only performs full unrolling)
>> >> + - VersioningLICM (if enabled)
>> >> + - LoopDistribute
>> >> + - LoopVectorizer
>> >> + - LoopUnrollAndJam (if enabled)
>> >> + - LoopUnroll (partial and runtime unrolling)
>> >> +
>> >> +When using the legacy pass manager with LTO:
>> >> +
>> >> + - LoopInterchange (if enabled)
>> >> + - SimpleLoopUnroll/LoopFullUnroll (only performs full unrolling)
>> >> + - LoopVectorizer
>> >> + - LoopUnroll (partial and runtime unrolling)
>> >> +
>> >> +When using the new pass manager:
>> >> +
>> >> + - SimpleLoopUnroll/LoopFullUnroll (only performs full unrolling)
>> >> + - LoopDistribute
>> >> + - LoopVectorizer
>> >> + - LoopUnrollAndJam (if enabled)
>> >> + - LoopUnroll (partial and runtime unrolling)
>> >> +
>> >> +Leftover Transformations
>> >> +========================
>> >> +
>> >> +Forced transformations that have not been applied after the last
>> >> +transformation pass should be reported to the user. The transformation
>> >> +passes themselves cannot be responsible for this reporting because
>> they
>> >> +might not be in the pipeline, there might be multiple passes able to
>> >> +apply a transformation (e.g. ``LoopInterchange`` and Polly) or a
>> >> +transformation attribute may be 'hidden' inside another passes'
>> followup
>> >> +attribute.
>> >> +
>> >> +The pass ``-transform-warning`` (``WarnMissedTransformationsPass``)
>> >> +emits such warnings. It should be placed after the last transformation
>> >> +pass.
>> >> +
>> >> +The current pass pipeline has a fixed order in which transformations
>> >> +passes are executed. A transformation can be in the followup of a pass
>> >> +that is executed later and thus leftover. For instance, a loop nest
>> >> +cannot be distributed and then interchanged with the current pass
>> >> +pipeline. The loop distribution will execute, but there is no loop
>> >> +interchange pass following such that any loop interchange metadata
>> will
>> >> +be ignored. The ``-transform-warning`` should emit a warning in this
>> >> +case.
>> >> +
>> >> +Future versions of LLVM may fix this by executing transformations
>> using
>> >> +a dynamic ordering.
>> >>
>> >> Modified: llvm/trunk/docs/index.rst
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/index.rst?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/docs/index.rst (original)
>> >> +++ llvm/trunk/docs/index.rst Wed Dec 12 09:32:52 2018
>> >> @@ -292,6 +292,7 @@ For API clients and LLVM developers.
>> >>     Statepoints
>> >>     MergeFunctions
>> >>     TypeMetadata
>> >> +   TransformMetadata
>> >>     FaultMaps
>> >>     MIRLangRef
>> >>     Coroutines
>> >>
>> >> Modified: llvm/trunk/include/llvm/InitializePasses.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/InitializePasses.h (original)
>> >> +++ llvm/trunk/include/llvm/InitializePasses.h Wed Dec 12 09:32:52 2018
>> >> @@ -400,6 +400,7 @@ void initializeUnreachableMachineBlockEl
>> >>  void initializeVerifierLegacyPassPass(PassRegistry&);
>> >>  void initializeVirtRegMapPass(PassRegistry&);
>> >>  void initializeVirtRegRewriterPass(PassRegistry&);
>> >> +void initializeWarnMissedTransformationsLegacyPass(PassRegistry &);
>> >>  void initializeWasmEHPreparePass(PassRegistry&);
>> >>  void initializeWholeProgramDevirtPass(PassRegistry&);
>> >>  void initializeWinEHPreparePass(PassRegistry&);
>> >>
>> >> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
>> >> +++ llvm/trunk/include/llvm/LinkAllPasses.h Wed Dec 12 09:32:52 2018
>> >> @@ -220,6 +220,7 @@ namespace {
>> >>        (void) llvm::createFloat2IntPass();
>> >>        (void) llvm::createEliminateAvailableExternallyPass();
>> >>        (void) llvm::createScalarizeMaskedMemIntrinPass();
>> >> +      (void) llvm::createWarnMissedTransformationsPass();
>> >>
>> >>        (void)new llvm::IntervalPartition();
>> >>        (void)new llvm::ScalarEvolutionWrapperPass();
>> >>
>> >> Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
>> >> +++ llvm/trunk/include/llvm/Transforms/Scalar.h Wed Dec 12 09:32:52
>> 2018
>> >> @@ -484,6 +484,13 @@ FunctionPass *createLibCallsShrinkWrapPa
>> >>  // primarily to help other loop passes.
>> >>  //
>> >>  Pass *createLoopSimplifyCFGPass();
>> >> +
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +//
>> >> +// WarnMissedTransformations - This pass emits warnings for leftover
>> forced
>> >> +// transformations.
>> >> +//
>> >> +Pass *createWarnMissedTransformationsPass();
>> >>  } // End llvm namespace
>> >>
>> >>  #endif
>> >>
>> >> Added: llvm/trunk/include/llvm/Transforms/Scalar/WarnMissedTransforms.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/WarnMissedTransforms.h?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/Transforms/Scalar/WarnMissedTransforms.h
>> (added)
>> >> +++ llvm/trunk/include/llvm/Transforms/Scalar/WarnMissedTransforms.h
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,38 @@
>> >> +//===- WarnMissedTransforms.h -----------------------------------*-
>> C++ -*-===//
>> >> +//
>> >> +//                     The LLVM Compiler Infrastructure
>> >> +//
>> >> +// This file is distributed under the University of Illinois Open
>> Source
>> >> +// License. See LICENSE.TXT for details.
>> >> +//
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +//
>> >> +// Emit warnings if forced code transformations have not been
>> performed.
>> >> +//
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +
>> >> +#ifndef LLVM_TRANSFORMS_SCALAR_WARNMISSEDTRANSFORMS_H
>> >> +#define LLVM_TRANSFORMS_SCALAR_WARNMISSEDTRANSFORMS_H
>> >> +
>> >> +#include "llvm/IR/PassManager.h"
>> >> +
>> >> +namespace llvm {
>> >> +class Function;
>> >> +class Loop;
>> >> +class LPMUpdater;
>> >> +
>> >> +// New pass manager boilerplate.
>> >> +class WarnMissedTransformationsPass
>> >> +    : public PassInfoMixin<WarnMissedTransformationsPass> {
>> >> +public:
>> >> +  explicit WarnMissedTransformationsPass() {}
>> >> +
>> >> +  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
>> >> +};
>> >> +
>> >> +// Legacy pass manager boilerplate.
>> >> +Pass *createWarnMissedTransformationsPass();
>> >> +void initializeWarnMissedTransformationsLegacyPass(PassRegistry &);
>> >> +} // end namespace llvm
>> >> +
>> >> +#endif // LLVM_TRANSFORMS_SCALAR_WARNMISSEDTRANSFORMS_H
>> >>
>> >> Modified: llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h (original)
>> >> +++ llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h Wed Dec 12
>> 09:32:52 2018
>> >> @@ -171,6 +171,77 @@ SmallVector<Instruction *, 8> findDefsUs
>> >>  Optional<const MDOperand *> findStringMetadataForLoop(Loop *TheLoop,
>> >>                                                        StringRef Name);
>> >>
>> >> +/// Find named metadata for a loop with an integer value.
>> >> +llvm::Optional<int> getOptionalIntLoopAttribute(Loop *TheLoop,
>> StringRef Name);
>> >> +
>> >> +/// Create a new loop identifier for a loop created from a loop
>> transformation.
>> >> +///
>> >> +/// @param OrigLoopID The loop ID of the loop before the
>> transformation.
>> >> +/// @param FollowupAttrs List of attribute names that contain
>> attributes to be
>> >> +///                      added to the new loop ID.
>> >> +/// @param InheritAttrsExceptPrefix Selects which attributes should
>> be inherited
>> >> +///                                 from the original loop. The
>> following values
>> >> +///                                 are considered:
>> >> +///        nullptr   : Inherit all attributes from @p OrigLoopID.
>> >> +///        ""        : Do not inherit any attribute from @p
>> OrigLoopID; only use
>> >> +///                    those specified by a followup attribute.
>> >> +///        "<prefix>": Inherit all attributes except those which
>> start with
>> >> +///                    <prefix>; commonly used to remove metadata for
>> the
>> >> +///                    applied transformation.
>> >> +/// @param AlwaysNew If true, do not try to reuse OrigLoopID and
>> never return
>> >> +///                  None.
>> >> +///
>> >> +/// @return The loop ID for the after-transformation loop. The
>> following values
>> >> +///         can be returned:
>> >> +///         None         : No followup attribute was found; it is up
>> to the
>> >> +///                        transformation to choose attributes that
>> make sense.
>> >> +///         @p OrigLoopID: The original identifier can be reused.
>> >> +///         nullptr      : The new loop has no attributes.
>> >> +///         MDNode*      : A new unique loop identifier.
>> >> +Optional<MDNode *>
>> >> +makeFollowupLoopID(MDNode *OrigLoopID, ArrayRef<StringRef>
>> FollowupAttrs,
>> >> +                   const char *InheritOptionsAttrsPrefix = "",
>> >> +                   bool AlwaysNew = false);
>> >> +
>> >> +/// Look for the loop attribute that disables all transformation
>> heuristic.
>> >> +bool hasDisableAllTransformsHint(const Loop *L);
>> >> +
>> >> +/// The mode sets how eager a transformation should be applied.
>> >> +enum TransformationMode {
>> >> +  /// The pass can use heuristics to determine whether a
>> transformation should
>> >> +  /// be applied.
>> >> +  TM_Unspecified,
>> >> +
>> >> +  /// The transformation should be applied without considering a cost
>> model.
>> >> +  TM_Enable,
>> >> +
>> >> +  /// The transformation should not be applied.
>> >> +  TM_Disable,
>> >> +
>> >> +  /// Force is a flag and should not be used alone.
>> >> +  TM_Force = 0x04,
>> >> +
>> >> +  /// The transformation was directed by the user, e.g. by a #pragma
>> in
>> >> +  /// the source code. If the transformation could not be applied, a
>> >> +  /// warning should be emitted.
>> >> +  TM_ForcedByUser = TM_Enable | TM_Force,
>> >> +
>> >> +  /// The transformation must not be applied. For instance, `#pragma
>> clang loop
>> >> +  /// unroll(disable)` explicitly forbids any unrolling to take
>> place. Unlike
>> >> +  /// general loop metadata, it must not be dropped. Most passes
>> should not
>> >> +  /// behave differently under TM_Disable and TM_SuppressedByUser.
>> >> +  TM_SuppressedByUser = TM_Disable | TM_Force
>> >> +};
>> >> +
>> >> +/// @{
>> >> +/// Get the mode for LLVM's supported loop transformations.
>> >> +TransformationMode hasUnrollTransformation(Loop *L);
>> >> +TransformationMode hasUnrollAndJamTransformation(Loop *L);
>> >> +TransformationMode hasVectorizeTransformation(Loop *L);
>> >> +TransformationMode hasDistributeTransformation(Loop *L);
>> >> +TransformationMode hasLICMVersioningTransformation(Loop *L);
>> >> +/// @}
>> >> +
>> >>  /// Set input string into loop metadata by keeping other values
>> intact.
>> >>  void addStringMetadataToLoop(Loop *TheLoop, const char *MDString,
>> >>                               unsigned V = 0);
>> >>
>> >> Modified: llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h (original)
>> >> +++ llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h Wed Dec 12
>> 09:32:52 2018
>> >> @@ -35,6 +35,15 @@ class ScalarEvolution;
>> >>
>> >>  using NewLoopsMap = SmallDenseMap<const Loop *, Loop *, 4>;
>> >>
>> >> +/// @{
>> >> +/// Metadata attribute names
>> >> +const char *const LLVMLoopUnrollFollowupAll =
>> "llvm.loop.unroll.followup_all";
>> >> +const char *const LLVMLoopUnrollFollowupUnrolled =
>> >> +    "llvm.loop.unroll.followup_unrolled";
>> >> +const char *const LLVMLoopUnrollFollowupRemainder =
>> >> +    "llvm.loop.unroll.followup_remainder";
>> >> +/// @}
>> >> +
>> >>  const Loop* addClonedBlockToLoopInfo(BasicBlock *OriginalBB,
>> >>                                       BasicBlock *ClonedBB, LoopInfo
>> *LI,
>> >>                                       NewLoopsMap &NewLoops);
>> >> @@ -61,15 +70,16 @@ LoopUnrollResult UnrollLoop(Loop *L, uns
>> >>                              unsigned PeelCount, bool UnrollRemainder,
>> >>                              LoopInfo *LI, ScalarEvolution *SE,
>> >>                              DominatorTree *DT, AssumptionCache *AC,
>> >> -                            OptimizationRemarkEmitter *ORE, bool
>> PreserveLCSSA);
>> >> +                            OptimizationRemarkEmitter *ORE, bool
>> PreserveLCSSA,
>> >> +                            Loop **RemainderLoop = nullptr);
>> >>
>> >>  bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
>> >>                                  bool AllowExpensiveTripCount,
>> >>                                  bool UseEpilogRemainder, bool
>> UnrollRemainder,
>> >> -                                LoopInfo *LI,
>> >> -                                ScalarEvolution *SE, DominatorTree
>> *DT,
>> >> -                                AssumptionCache *AC,
>> >> -                                bool PreserveLCSSA);
>> >> +                                LoopInfo *LI, ScalarEvolution *SE,
>> >> +                                DominatorTree *DT, AssumptionCache
>> *AC,
>> >> +                                bool PreserveLCSSA,
>> >> +                                Loop **ResultLoop = nullptr);
>> >>
>> >>  void computePeelCount(Loop *L, unsigned LoopSize,
>> >>                        TargetTransformInfo::UnrollingPreferences &UP,
>> >> @@ -84,7 +94,8 @@ LoopUnrollResult UnrollAndJamLoop(Loop *
>> >>                                    unsigned TripMultiple, bool
>> UnrollRemainder,
>> >>                                    LoopInfo *LI, ScalarEvolution *SE,
>> >>                                    DominatorTree *DT, AssumptionCache
>> *AC,
>> >> -                                  OptimizationRemarkEmitter *ORE);
>> >> +                                  OptimizationRemarkEmitter *ORE,
>> >> +                                  Loop **EpilogueLoop = nullptr);
>> >>
>> >>  bool isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree
>> &DT,
>> >>                            DependenceInfo &DI);
>> >>
>> >> Modified:
>> llvm/trunk/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
>> (original)
>> >> +++
>> llvm/trunk/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h
>> Wed Dec 12 09:32:52 2018
>> >> @@ -113,7 +113,11 @@ public:
>> >>    unsigned getWidth() const { return Width.Value; }
>> >>    unsigned getInterleave() const { return Interleave.Value; }
>> >>    unsigned getIsVectorized() const { return IsVectorized.Value; }
>> >> -  enum ForceKind getForce() const { return (ForceKind)Force.Value; }
>> >> +  enum ForceKind getForce() const {
>> >> +    if (Force.Value == FK_Undefined &&
>> hasDisableAllTransformsHint(TheLoop))
>> >> +      return FK_Disabled;
>> >> +    return (ForceKind)Force.Value;
>> >> +  }
>> >>
>> >>    /// If hints are provided that force vectorization, use the
>> AlwaysPrint
>> >>    /// pass name to force the frontend to print the diagnostic.
>> >>
>> >> Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopInfo.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
>> >> +++ llvm/trunk/lib/Analysis/LoopInfo.cpp Wed Dec 12 09:32:52 2018
>> >> @@ -237,23 +237,19 @@ MDNode *Loop::getLoopID() const {
>> >>  }
>> >>
>> >>  void Loop::setLoopID(MDNode *LoopID) const {
>> >> -  assert(LoopID && "Loop ID should not be null");
>> >> -  assert(LoopID->getNumOperands() > 0 && "Loop ID needs at least one
>> operand");
>> >> -  assert(LoopID->getOperand(0) == LoopID && "Loop ID should refer to
>> itself");
>> >> +  assert((!LoopID || LoopID->getNumOperands() > 0) &&
>> >> +         "Loop ID needs at least one operand");
>> >> +  assert((!LoopID || LoopID->getOperand(0) == LoopID) &&
>> >> +         "Loop ID should refer to itself");
>> >>
>> >> -  if (BasicBlock *Latch = getLoopLatch()) {
>> >> -    Latch->getTerminator()->setMetadata(LLVMContext::MD_loop, LoopID);
>> >> -    return;
>> >> -  }
>> >> -
>> >> -  assert(!getLoopLatch() &&
>> >> -         "The loop should have no single latch at this point");
>> >>    BasicBlock *H = getHeader();
>> >>    for (BasicBlock *BB : this->blocks()) {
>> >>      Instruction *TI = BB->getTerminator();
>> >>      for (BasicBlock *Successor : successors(TI)) {
>> >> -      if (Successor == H)
>> >> +      if (Successor == H) {
>> >>          TI->setMetadata(LLVMContext::MD_loop, LoopID);
>> >> +        break;
>> >> +      }
>> >>      }
>> >>    }
>> >>  }
>> >>
>> >> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
>> >> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Wed Dec 12 09:32:52 2018
>> >> @@ -148,6 +148,7 @@
>> >>  #include "llvm/Transforms/Scalar/SpeculateAroundPHIs.h"
>> >>  #include "llvm/Transforms/Scalar/SpeculativeExecution.h"
>> >>  #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
>> >> +#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
>> >>  #include "llvm/Transforms/Utils/AddDiscriminators.h"
>> >>  #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
>> >>  #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
>> >> @@ -835,6 +836,7 @@ PassBuilder::buildModuleOptimizationPipe
>> >>          createFunctionToLoopPassAdaptor(LoopUnrollAndJamPass(Level)));
>> >>    }
>> >>    OptimizePM.addPass(LoopUnrollPass(LoopUnrollOptions(Level)));
>> >> +  OptimizePM.addPass(WarnMissedTransformationsPass());
>> >>    OptimizePM.addPass(InstCombinePass());
>> >>
>> OptimizePM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis,
>> Function>());
>> >>    OptimizePM.addPass(createFunctionToLoopPassAdaptor(LICMPass(),
>> DebugLogging));
>> >>
>> >> Modified: llvm/trunk/lib/Passes/PassRegistry.def
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Passes/PassRegistry.def (original)
>> >> +++ llvm/trunk/lib/Passes/PassRegistry.def Wed Dec 12 09:32:52 2018
>> >> @@ -230,6 +230,7 @@ FUNCTION_PASS("verify<memoryssa>", Memor
>> >>  FUNCTION_PASS("verify<regions>", RegionInfoVerifierPass())
>> >>  FUNCTION_PASS("view-cfg", CFGViewerPass())
>> >>  FUNCTION_PASS("view-cfg-only", CFGOnlyViewerPass())
>> >> +FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
>> >>  #undef FUNCTION_PASS
>> >>
>> >>  #ifndef LOOP_ANALYSIS
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -702,6 +702,8 @@ void PassManagerBuilder::populateModuleP
>> >>      MPM.add(createLICMPass());
>> >>   }
>> >>
>> >> +  MPM.add(createWarnMissedTransformationsPass());
>> >> +
>> >>    // After vectorization and unrolling, assume intrinsics may tell us
>> more
>> >>    // about pointer alignments.
>> >>    MPM.add(createAlignmentFromAssumptionsPass());
>> >> @@ -877,6 +879,8 @@ void PassManagerBuilder::addLTOOptimizat
>> >>    if (!DisableUnrollLoops)
>> >>      PM.add(createLoopUnrollPass(OptLevel));
>> >>
>> >> +  PM.add(createWarnMissedTransformationsPass());
>> >> +
>> >>    // Now that we've optimized loops (in particular loop induction
>> variables),
>> >>    // we may have exposed more scalar opportunities. Run parts of the
>> scalar
>> >>    // optimizer again at this point.
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt (original)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/CMakeLists.txt Wed Dec 12
>> 09:32:52 2018
>> >> @@ -69,6 +69,7 @@ add_llvm_library(LLVMScalarOpts
>> >>    StraightLineStrengthReduce.cpp
>> >>    StructurizeCFG.cpp
>> >>    TailRecursionElimination.cpp
>> >> +  WarnMissedTransforms.cpp
>> >>
>> >>    ADDITIONAL_HEADER_DIRS
>> >>    ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -78,6 +78,18 @@ using namespace llvm;
>> >>  #define LDIST_NAME "loop-distribute"
>> >>  #define DEBUG_TYPE LDIST_NAME
>> >>
>> >> +/// @{
>> >> +/// Metadata attribute names
>> >> +static const char *const LLVMLoopDistributeFollowupAll =
>> >> +    "llvm.loop.distribute.followup_all";
>> >> +static const char *const LLVMLoopDistributeFollowupCoincident =
>> >> +    "llvm.loop.distribute.followup_coincident";
>> >> +static const char *const LLVMLoopDistributeFollowupSequential =
>> >> +    "llvm.loop.distribute.followup_sequential";
>> >> +static const char *const LLVMLoopDistributeFollowupFallback =
>> >> +    "llvm.loop.distribute.followup_fallback";
>> >> +/// @}
>> >> +
>> >>  static cl::opt<bool>
>> >>      LDistVerify("loop-distribute-verify", cl::Hidden,
>> >>                  cl::desc("Turn on DominatorTree and LoopInfo
>> verification "
>> >> @@ -186,7 +198,7 @@ public:
>> >>    /// Returns the loop where this partition ends up after
>> distribution.
>> >>    /// If this partition is mapped to the original loop then use the
>> block from
>> >>    /// the loop.
>> >> -  const Loop *getDistributedLoop() const {
>> >> +  Loop *getDistributedLoop() const {
>> >>      return ClonedLoop ? ClonedLoop : OrigLoop;
>> >>    }
>> >>
>> >> @@ -443,6 +455,9 @@ public:
>> >>      assert(&*OrigPH->begin() == OrigPH->getTerminator() &&
>> >>             "preheader not empty");
>> >>
>> >> +    // Preserve the original loop ID for use after the transformation.
>> >> +    MDNode *OrigLoopID = L->getLoopID();
>> >> +
>> >>      // Create a loop for each partition except the last.  Clone the
>> original
>> >>      // loop before PH along with adding a preheader for the cloned
>> loop.  Then
>> >>      // update PH to point to the newly added preheader.
>> >> @@ -457,9 +472,13 @@ public:
>> >>
>> >>        Part->getVMap()[ExitBlock] = TopPH;
>> >>        Part->remapInstructions();
>> >> +      setNewLoopID(OrigLoopID, Part);
>> >>      }
>> >>      Pred->getTerminator()->replaceUsesOfWith(OrigPH, TopPH);
>> >>
>> >> +    // Also set a new loop ID for the last loop.
>> >> +    setNewLoopID(OrigLoopID, &PartitionContainer.back());
>> >> +
>> >>      // Now go in forward order and update the immediate dominator for
>> the
>> >>      // preheaders with the exiting block of the previous loop.
>> Dominance
>> >>      // within the loop is updated in cloneLoopWithPreheader.
>> >> @@ -575,6 +594,19 @@ private:
>> >>        }
>> >>      }
>> >>    }
>> >> +
>> >> +  /// Assign new LoopIDs for the partition's cloned loop.
>> >> +  void setNewLoopID(MDNode *OrigLoopID, InstPartition *Part) {
>> >> +    Optional<MDNode *> PartitionID = makeFollowupLoopID(
>> >> +        OrigLoopID,
>> >> +        {LLVMLoopDistributeFollowupAll,
>> >> +         Part->hasDepCycle() ? LLVMLoopDistributeFollowupSequential
>> >> +                             : LLVMLoopDistributeFollowupCoincident});
>> >> +    if (PartitionID.hasValue()) {
>> >> +      Loop *NewLoop = Part->getDistributedLoop();
>> >> +      NewLoop->setLoopID(PartitionID.getValue());
>> >> +    }
>> >> +  }
>> >>  };
>> >>
>> >>  /// For each memory instruction, this class maintains difference of
>> the
>> >> @@ -743,6 +775,9 @@ public:
>> >>        return fail("TooManySCEVRuntimeChecks",
>> >>                    "too many SCEV run-time checks needed.\n");
>> >>
>> >> +    if (!IsForced.getValueOr(false) && hasDisableAllTransformsHint(L))
>> >> +      return fail("HeuristicDisabled", "distribution heuristic
>> disabled");
>> >> +
>> >>      LLVM_DEBUG(dbgs() << "\nDistributing loop: " << *L << "\n");
>> >>      // We're done forming the partitions set up the reverse mapping
>> from
>> >>      // instructions to partitions.
>> >> @@ -762,6 +797,8 @@ public:
>> >>                                                    RtPtrChecking);
>> >>
>> >>      if (!Pred.isAlwaysTrue() || !Checks.empty()) {
>> >> +      MDNode *OrigLoopID = L->getLoopID();
>> >> +
>> >>        LLVM_DEBUG(dbgs() << "\nPointers:\n");
>> >>
>> LLVM_DEBUG(LAI->getRuntimePointerChecking()->printChecks(dbgs(), Checks));
>> >>        LoopVersioning LVer(*LAI, L, LI, DT, SE, false);
>> >> @@ -769,6 +806,17 @@ public:
>> >>        LVer.setSCEVChecks(LAI->getPSE().getUnionPredicate());
>> >>        LVer.versionLoop(DefsUsedOutside);
>> >>        LVer.annotateLoopWithNoAlias();
>> >> +
>> >> +      // The unversioned loop will not be changed, so we inherit all
>> attributes
>> >> +      // from the original loop, but remove the loop distribution
>> metadata to
>> >> +      // avoid to distribute it again.
>> >> +      MDNode *UnversionedLoopID =
>> >> +          makeFollowupLoopID(OrigLoopID,
>> >> +                             {LLVMLoopDistributeFollowupAll,
>> >> +                              LLVMLoopDistributeFollowupFallback},
>> >> +                             "llvm.loop.distribute.", true)
>> >> +              .getValue();
>> >> +      LVer.getNonVersionedLoop()->setLoopID(UnversionedLoopID);
>> >>      }
>> >>
>> >>      // Create identical copies of the original loop for each
>> partition and hook
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp
>> (original)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollAndJamPass.cpp Wed Dec
>> 12 09:32:52 2018
>> >> @@ -56,6 +56,20 @@ using namespace llvm;
>> >>
>> >>  #define DEBUG_TYPE "loop-unroll-and-jam"
>> >>
>> >> +/// @{
>> >> +/// Metadata attribute names
>> >> +static const char *const LLVMLoopUnrollAndJamFollowupAll =
>> >> +    "llvm.loop.unroll_and_jam.followup_all";
>> >> +static const char *const LLVMLoopUnrollAndJamFollowupInner =
>> >> +    "llvm.loop.unroll_and_jam.followup_inner";
>> >> +static const char *const LLVMLoopUnrollAndJamFollowupOuter =
>> >> +    "llvm.loop.unroll_and_jam.followup_outer";
>> >> +static const char *const LLVMLoopUnrollAndJamFollowupRemainderInner =
>> >> +    "llvm.loop.unroll_and_jam.followup_remainder_inner";
>> >> +static const char *const LLVMLoopUnrollAndJamFollowupRemainderOuter =
>> >> +    "llvm.loop.unroll_and_jam.followup_remainder_outer";
>> >> +/// @}
>> >> +
>> >>  static cl::opt<bool>
>> >>      AllowUnrollAndJam("allow-unroll-and-jam", cl::Hidden,
>> >>                        cl::desc("Allows loops to be
>> unroll-and-jammed."));
>> >> @@ -112,11 +126,6 @@ static bool HasUnrollAndJamEnablePragma(
>> >>    return GetUnrollMetadataForLoop(L,
>> "llvm.loop.unroll_and_jam.enable");
>> >>  }
>> >>
>> >> -// Returns true if the loop has an unroll_and_jam(disable) pragma.
>> >> -static bool HasUnrollAndJamDisablePragma(const Loop *L) {
>> >> -  return GetUnrollMetadataForLoop(L,
>> "llvm.loop.unroll_and_jam.disable");
>> >> -}
>> >> -
>> >>  // If loop has an unroll_and_jam_count pragma return the (necessarily
>> >>  // positive) value from the pragma.  Otherwise return 0.
>> >>  static unsigned UnrollAndJamCountPragmaValue(const Loop *L) {
>> >> @@ -299,13 +308,16 @@ tryToUnrollAndJamLoop(Loop *L, Dominator
>> >>                      << L->getHeader()->getParent()->getName() << "]
>> Loop %"
>> >>                      << L->getHeader()->getName() << "\n");
>> >>
>> >> +  TransformationMode EnableMode = hasUnrollAndJamTransformation(L);
>> >> +  if (EnableMode & TM_Disable)
>> >> +    return LoopUnrollResult::Unmodified;
>> >> +
>> >>    // A loop with any unroll pragma (enabling/disabling/count/etc) is
>> left for
>> >>    // the unroller, so long as it does not explicitly have
>> unroll_and_jam
>> >>    // metadata. This means #pragma nounroll will disable unroll and
>> jam as well
>> >>    // as unrolling
>> >> -  if (HasUnrollAndJamDisablePragma(L) ||
>> >> -      (HasAnyUnrollPragma(L, "llvm.loop.unroll.") &&
>> >> -       !HasAnyUnrollPragma(L, "llvm.loop.unroll_and_jam."))) {
>> >> +  if (HasAnyUnrollPragma(L, "llvm.loop.unroll.") &&
>> >> +      !HasAnyUnrollPragma(L, "llvm.loop.unroll_and_jam.")) {
>> >>      LLVM_DEBUG(dbgs() << "  Disabled due to pragma.\n");
>> >>      return LoopUnrollResult::Unmodified;
>> >>    }
>> >> @@ -344,6 +356,19 @@ tryToUnrollAndJamLoop(Loop *L, Dominator
>> >>      return LoopUnrollResult::Unmodified;
>> >>    }
>> >>
>> >> +  // Save original loop IDs for after the transformation.
>> >> +  MDNode *OrigOuterLoopID = L->getLoopID();
>> >> +  MDNode *OrigSubLoopID = SubLoop->getLoopID();
>> >> +
>> >> +  // To assign the loop id of the epilogue, assign it before
>> unrolling it so it
>> >> +  // is applied to every inner loop of the epilogue. We later apply
>> the loop ID
>> >> +  // for the jammed inner loop.
>> >> +  Optional<MDNode *> NewInnerEpilogueLoopID = makeFollowupLoopID(
>> >> +      OrigOuterLoopID, {LLVMLoopUnrollAndJamFollowupAll,
>> >> +                        LLVMLoopUnrollAndJamFollowupRemainderInner});
>> >> +  if (NewInnerEpilogueLoopID.hasValue())
>> >> +    SubLoop->setLoopID(NewInnerEpilogueLoopID.getValue());
>> >> +
>> >>    // Find trip count and trip multiple
>> >>    unsigned OuterTripCount = SE.getSmallConstantTripCount(L, Latch);
>> >>    unsigned OuterTripMultiple = SE.getSmallConstantTripMultiple(L,
>> Latch);
>> >> @@ -359,9 +384,39 @@ tryToUnrollAndJamLoop(Loop *L, Dominator
>> >>    if (OuterTripCount && UP.Count > OuterTripCount)
>> >>      UP.Count = OuterTripCount;
>> >>
>> >> -  LoopUnrollResult UnrollResult =
>> >> -      UnrollAndJamLoop(L, UP.Count, OuterTripCount, OuterTripMultiple,
>> >> -                       UP.UnrollRemainder, LI, &SE, &DT, &AC, &ORE);
>> >> +  Loop *EpilogueOuterLoop = nullptr;
>> >> +  LoopUnrollResult UnrollResult = UnrollAndJamLoop(
>> >> +      L, UP.Count, OuterTripCount, OuterTripMultiple,
>> UP.UnrollRemainder, LI,
>> >> +      &SE, &DT, &AC, &ORE, &EpilogueOuterLoop);
>> >> +
>> >> +  // Assign new loop attributes.
>> >> +  if (EpilogueOuterLoop) {
>> >> +    Optional<MDNode *> NewOuterEpilogueLoopID = makeFollowupLoopID(
>> >> +        OrigOuterLoopID, {LLVMLoopUnrollAndJamFollowupAll,
>> >> +
>> LLVMLoopUnrollAndJamFollowupRemainderOuter});
>> >> +    if (NewOuterEpilogueLoopID.hasValue())
>> >> +      EpilogueOuterLoop->setLoopID(NewOuterEpilogueLoopID.getValue());
>> >> +  }
>> >> +
>> >> +  Optional<MDNode *> NewInnerLoopID =
>> >> +      makeFollowupLoopID(OrigOuterLoopID,
>> {LLVMLoopUnrollAndJamFollowupAll,
>> >> +
>>  LLVMLoopUnrollAndJamFollowupInner});
>> >> +  if (NewInnerLoopID.hasValue())
>> >> +    SubLoop->setLoopID(NewInnerLoopID.getValue());
>> >> +  else
>> >> +    SubLoop->setLoopID(OrigSubLoopID);
>> >> +
>> >> +  if (UnrollResult == LoopUnrollResult::PartiallyUnrolled) {
>> >> +    Optional<MDNode *> NewOuterLoopID = makeFollowupLoopID(
>> >> +        OrigOuterLoopID,
>> >> +        {LLVMLoopUnrollAndJamFollowupAll,
>> LLVMLoopUnrollAndJamFollowupOuter});
>> >> +    if (NewOuterLoopID.hasValue()) {
>> >> +      L->setLoopID(NewOuterLoopID.getValue());
>> >> +
>> >> +      // Do not setLoopAlreadyUnrolled if a followup was given.
>> >> +      return UnrollResult;
>> >> +    }
>> >> +  }
>> >>
>> >>    // If loop has an unroll count pragma or unrolled by explicitly set
>> count
>> >>    // mark loop as unrolled to prevent unrolling beyond that requested.
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -661,11 +661,6 @@ static bool HasUnrollEnablePragma(const
>> >>    return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.enable");
>> >>  }
>> >>
>> >> -// Returns true if the loop has an unroll(disable) pragma.
>> >> -static bool HasUnrollDisablePragma(const Loop *L) {
>> >> -  return GetUnrollMetadataForLoop(L, "llvm.loop.unroll.disable");
>> >> -}
>> >> -
>> >>  // Returns true if the loop has an runtime unroll(disable) pragma.
>> >>  static bool HasRuntimeUnrollDisablePragma(const Loop *L) {
>> >>    return GetUnrollMetadataForLoop(L,
>> "llvm.loop.unroll.runtime.disable");
>> >> @@ -713,12 +708,19 @@ static uint64_t getUnrolledLoopSize(
>> >>
>> >>  // Returns true if unroll count was set explicitly.
>> >>  // Calculates unroll count and writes it to UP.Count.
>> >> +// Unless IgnoreUser is true, will also use metadata and command-line
>> options
>> >> +// that are specific to to the LoopUnroll pass (which, for instance,
>> are
>> >> +// irrelevant for the LoopUnrollAndJam pass).
>> >> +// FIXME: This function is used by LoopUnroll and LoopUnrollAndJam,
>> but consumes
>> >> +// many LoopUnroll-specific options. The shared functionality should
>> be
>> >> +// refactored into it own function.
>> >>  bool llvm::computeUnrollCount(
>> >>      Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT,
>> LoopInfo *LI,
>> >>      ScalarEvolution &SE, const SmallPtrSetImpl<const Value *>
>> &EphValues,
>> >>      OptimizationRemarkEmitter *ORE, unsigned &TripCount, unsigned
>> MaxTripCount,
>> >>      unsigned &TripMultiple, unsigned LoopSize,
>> >>      TargetTransformInfo::UnrollingPreferences &UP, bool
>> &UseUpperBound) {
>> >> +
>> >>    // Check for explicit Count.
>> >>    // 1st priority is unroll count set by "unroll-count" option.
>> >>    bool UserUnrollCount = UnrollCount.getNumOccurrences() > 0;
>> >> @@ -969,7 +971,7 @@ static LoopUnrollResult tryToUnrollLoop(
>> >>    LLVM_DEBUG(dbgs() << "Loop Unroll: F["
>> >>                      << L->getHeader()->getParent()->getName() << "]
>> Loop %"
>> >>                      << L->getHeader()->getName() << "\n");
>> >> -  if (HasUnrollDisablePragma(L))
>> >> +  if (hasUnrollTransformation(L) & TM_Disable)
>> >>      return LoopUnrollResult::Unmodified;
>> >>    if (!L->isLoopSimplifyForm()) {
>> >>      LLVM_DEBUG(
>> >> @@ -1066,14 +1068,39 @@ static LoopUnrollResult tryToUnrollLoop(
>> >>    if (TripCount && UP.Count > TripCount)
>> >>      UP.Count = TripCount;
>> >>
>> >> +  // Save loop properties before it is transformed.
>> >> +  MDNode *OrigLoopID = L->getLoopID();
>> >> +
>> >>    // Unroll the loop.
>> >> +  Loop *RemainderLoop = nullptr;
>> >>    LoopUnrollResult UnrollResult = UnrollLoop(
>> >>        L, UP.Count, TripCount, UP.Force, UP.Runtime,
>> UP.AllowExpensiveTripCount,
>> >>        UseUpperBound, MaxOrZero, TripMultiple, UP.PeelCount,
>> UP.UnrollRemainder,
>> >> -      LI, &SE, &DT, &AC, &ORE, PreserveLCSSA);
>> >> +      LI, &SE, &DT, &AC, &ORE, PreserveLCSSA, &RemainderLoop);
>> >>    if (UnrollResult == LoopUnrollResult::Unmodified)
>> >>      return LoopUnrollResult::Unmodified;
>> >>
>> >> +  if (RemainderLoop) {
>> >> +    Optional<MDNode *> RemainderLoopID =
>> >> +        makeFollowupLoopID(OrigLoopID, {LLVMLoopUnrollFollowupAll,
>> >> +
>> LLVMLoopUnrollFollowupRemainder});
>> >> +    if (RemainderLoopID.hasValue())
>> >> +      RemainderLoop->setLoopID(RemainderLoopID.getValue());
>> >> +  }
>> >> +
>> >> +  if (UnrollResult != LoopUnrollResult::FullyUnrolled) {
>> >> +    Optional<MDNode *> NewLoopID =
>> >> +        makeFollowupLoopID(OrigLoopID, {LLVMLoopUnrollFollowupAll,
>> >> +
>> LLVMLoopUnrollFollowupUnrolled});
>> >> +    if (NewLoopID.hasValue()) {
>> >> +      L->setLoopID(NewLoopID.getValue());
>> >> +
>> >> +      // Do not setLoopAlreadyUnrolled if loop attributes have been
>> specified
>> >> +      // explicitly.
>> >> +      return UnrollResult;
>> >> +    }
>> >> +  }
>> >> +
>> >>    // If loop has an unroll count pragma or unrolled by explicitly set
>> count
>> >>    // mark loop as unrolled to prevent unrolling beyond that requested.
>> >>    // If the loop was peeled, we already "used up" the profile
>> information
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -594,6 +594,11 @@ bool LoopVersioningLICM::runOnLoop(Loop
>> >>
>> >>    if (skipLoop(L))
>> >>      return false;
>> >> +
>> >> +  // Do not do the transformation if disabled by metadata.
>> >> +  if (hasLICMVersioningTransformation(L) & TM_Disable)
>> >> +    return false;
>> >> +
>> >>    // Get Analysis information.
>> >>    AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
>> >>    SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Scalar/Scalar.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/Scalar.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Wed Dec 12 09:32:52
>> 2018
>> >> @@ -75,6 +75,7 @@ void llvm::initializeScalarOpts(PassRegi
>> >>    initializeLoopUnrollPass(Registry);
>> >>    initializeLoopUnrollAndJamPass(Registry);
>> >>    initializeLoopUnswitchPass(Registry);
>> >> +  initializeWarnMissedTransformationsLegacyPass(Registry);
>> >>    initializeLoopVersioningLICMPass(Registry);
>> >>    initializeLoopIdiomRecognizeLegacyPassPass(Registry);
>> >>    initializeLowerAtomicLegacyPassPass(Registry);
>> >>
>> >> Added: llvm/trunk/lib/Transforms/Scalar/WarnMissedTransforms.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/WarnMissedTransforms.cpp?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Scalar/WarnMissedTransforms.cpp (added)
>> >> +++ llvm/trunk/lib/Transforms/Scalar/WarnMissedTransforms.cpp Wed Dec
>> 12 09:32:52 2018
>> >> @@ -0,0 +1,144 @@
>> >> +//===- LoopTransformWarning.cpp -
>> ----------------------------------------===//
>> >> +//
>> >> +//                     The LLVM Compiler Infrastructure
>> >> +//
>> >> +// This file is distributed under the University of Illinois Open
>> Source
>> >> +// License. See LICENSE.TXT for details.
>> >> +//
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +//
>> >> +// Emit warnings if forced code transformations have not been
>> performed.
>> >> +//
>> >>
>> +//===----------------------------------------------------------------------===//
>> >> +
>> >> +#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
>> >> +#include "llvm/Analysis/OptimizationRemarkEmitter.h"
>> >> +#include "llvm/Transforms/Utils/LoopUtils.h"
>> >> +
>> >> +using namespace llvm;
>> >> +
>> >> +#define DEBUG_TYPE "transform-warning"
>> >> +
>> >> +/// Emit warnings for forced (i.e. user-defined) loop transformations
>> which have
>> >> +/// still not been performed.
>> >> +static void warnAboutLeftoverTransformations(Loop *L,
>> >> +
>>  OptimizationRemarkEmitter *ORE) {
>> >> +  if (hasUnrollTransformation(L) == TM_ForcedByUser) {
>> >> +    LLVM_DEBUG(dbgs() << "Leftover unroll transformation\n");
>> >> +    ORE->emit(
>> >> +        DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
>> >> +                                          "FailedRequestedUnrolling",
>> >> +                                          L->getStartLoc(),
>> L->getHeader())
>> >> +        << "loop not unrolled: the optimizer was unable to perform
>> the "
>> >> +           "requested transformation; the transformation might be
>> disabled or "
>> >> +           "specified as part of an unsupported transformation
>> ordering");
>> >> +  }
>> >> +
>> >> +  if (hasUnrollAndJamTransformation(L) == TM_ForcedByUser) {
>> >> +    LLVM_DEBUG(dbgs() << "Leftover unroll-and-jam transformation\n");
>> >> +    ORE->emit(
>> >> +        DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
>> >> +
>> "FailedRequestedUnrollAndJamming",
>> >> +                                          L->getStartLoc(),
>> L->getHeader())
>> >> +        << "loop not unroll-and-jammed: the optimizer was unable to
>> perform "
>> >> +           "the requested transformation; the transformation might be
>> disabled "
>> >> +           "or specified as part of an unsupported transformation
>> ordering");
>> >> +  }
>> >> +
>> >> +  if (hasVectorizeTransformation(L) == TM_ForcedByUser) {
>> >> +    LLVM_DEBUG(dbgs() << "Leftover vectorization transformation\n");
>> >> +    Optional<int> VectorizeWidth =
>> >> +        getOptionalIntLoopAttribute(L, "llvm.loop.vectorize.width");
>> >> +    Optional<int> InterleaveCount =
>> >> +        getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
>> >> +
>> >> +    if (VectorizeWidth.getValueOr(0) != 1)
>> >> +      ORE->emit(
>> >> +          DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
>> >> +
>> "FailedRequestedVectorization",
>> >> +                                            L->getStartLoc(),
>> L->getHeader())
>> >> +          << "loop not vectorized: the optimizer was unable to
>> perform the "
>> >> +             "requested transformation; the transformation might be
>> disabled "
>> >> +             "or specified as part of an unsupported transformation
>> ordering");
>> >> +    else if (InterleaveCount.getValueOr(0) != 1)
>> >> +      ORE->emit(
>> >> +          DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
>> >> +
>> "FailedRequestedInterleaving",
>> >> +                                            L->getStartLoc(),
>> L->getHeader())
>> >> +          << "loop not interleaved: the optimizer was unable to
>> perform the "
>> >> +             "requested transformation; the transformation might be
>> disabled "
>> >> +             "or specified as part of an unsupported transformation
>> ordering");
>> >> +  }
>> >> +
>> >> +  if (hasDistributeTransformation(L) == TM_ForcedByUser) {
>> >> +    LLVM_DEBUG(dbgs() << "Leftover distribute transformation\n");
>> >> +    ORE->emit(
>> >> +        DiagnosticInfoOptimizationFailure(DEBUG_TYPE,
>> >> +
>> "FailedRequestedDistribution",
>> >> +                                          L->getStartLoc(),
>> L->getHeader())
>> >> +        << "loop not distributed: the optimizer was unable to perform
>> the "
>> >> +           "requested transformation; the transformation might be
>> disabled or "
>> >> +           "specified as part of an unsupported transformation
>> ordering");
>> >> +  }
>> >> +}
>> >> +
>> >> +static void warnAboutLeftoverTransformations(Function *F, LoopInfo
>> *LI,
>> >> +
>>  OptimizationRemarkEmitter *ORE) {
>> >> +  for (auto *L : LI->getLoopsInPreorder())
>> >> +    warnAboutLeftoverTransformations(L, ORE);
>> >> +}
>> >> +
>> >> +// New pass manager boilerplate
>> >> +PreservedAnalyses
>> >> +WarnMissedTransformationsPass::run(Function &F,
>> FunctionAnalysisManager &AM) {
>> >> +  auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
>> >> +  auto &LI = AM.getResult<LoopAnalysis>(F);
>> >> +
>> >> +  warnAboutLeftoverTransformations(&F, &LI, &ORE);
>> >> +
>> >> +  return PreservedAnalyses::all();
>> >> +}
>> >> +
>> >> +// Legacy pass manager boilerplate
>> >> +namespace {
>> >> +class WarnMissedTransformationsLegacy : public FunctionPass {
>> >> +public:
>> >> +  static char ID;
>> >> +
>> >> +  explicit WarnMissedTransformationsLegacy() : FunctionPass(ID) {
>> >> +    initializeWarnMissedTransformationsLegacyPass(
>> >> +        *PassRegistry::getPassRegistry());
>> >> +  }
>> >> +
>> >> +  bool runOnFunction(Function &F) override {
>> >> +    if (skipFunction(F))
>> >> +      return false;
>> >> +
>> >> +    auto &ORE =
>> getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
>> >> +    auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
>> >> +
>> >> +    warnAboutLeftoverTransformations(&F, &LI, &ORE);
>> >> +    return false;
>> >> +  }
>> >> +
>> >> +  void getAnalysisUsage(AnalysisUsage &AU) const override {
>> >> +    AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
>> >> +    AU.addRequired<LoopInfoWrapperPass>();
>> >> +
>> >> +    AU.setPreservesAll();
>> >> +  }
>> >> +};
>> >> +} // end anonymous namespace
>> >> +
>> >> +char WarnMissedTransformationsLegacy::ID = 0;
>> >> +
>> >> +INITIALIZE_PASS_BEGIN(WarnMissedTransformationsLegacy,
>> "transform-warning",
>> >> +                      "Warn about non-applied transformations",
>> false, false)
>> >> +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
>> >> +INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
>> >> +INITIALIZE_PASS_END(WarnMissedTransformationsLegacy,
>> "transform-warning",
>> >> +                    "Warn about non-applied transformations", false,
>> false)
>> >> +
>> >> +Pass *llvm::createWarnMissedTransformationsPass() {
>> >> +  return new WarnMissedTransformationsLegacy();
>> >> +}
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Wed Dec 12 09:32:52
>> 2018
>> >> @@ -329,12 +329,15 @@ void llvm::simplifyLoopAfterUnroll(Loop
>> >>  ///
>> >>  /// This utility preserves LoopInfo. It will also preserve
>> ScalarEvolution and
>> >>  /// DominatorTree if they are non-null.
>> >> +///
>> >> +/// If RemainderLoop is non-null, it will receive the remainder loop
>> (if
>> >> +/// required and not fully unrolled).
>> >>  LoopUnrollResult llvm::UnrollLoop(
>> >>      Loop *L, unsigned Count, unsigned TripCount, bool Force, bool
>> AllowRuntime,
>> >>      bool AllowExpensiveTripCount, bool PreserveCondBr, bool
>> PreserveOnlyFirst,
>> >>      unsigned TripMultiple, unsigned PeelCount, bool UnrollRemainder,
>> >>      LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT,
>> AssumptionCache *AC,
>> >> -    OptimizationRemarkEmitter *ORE, bool PreserveLCSSA) {
>> >> +    OptimizationRemarkEmitter *ORE, bool PreserveLCSSA, Loop
>> **RemainderLoop) {
>> >>
>> >>    BasicBlock *Preheader = L->getLoopPreheader();
>> >>    if (!Preheader) {
>> >> @@ -468,7 +471,7 @@ LoopUnrollResult llvm::UnrollLoop(
>> >>    if (RuntimeTripCount && TripMultiple % Count != 0 &&
>> >>        !UnrollRuntimeLoopRemainder(L, Count, AllowExpensiveTripCount,
>> >>                                    EpilogProfitability,
>> UnrollRemainder, LI, SE,
>> >> -                                  DT, AC, PreserveLCSSA)) {
>> >> +                                  DT, AC, PreserveLCSSA,
>> RemainderLoop)) {
>> >>      if (Force)
>> >>        RuntimeTripCount = false;
>> >>      else {
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Utils/LoopUnrollAndJam.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnrollAndJam.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Utils/LoopUnrollAndJam.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Utils/LoopUnrollAndJam.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -167,12 +167,14 @@ static void moveHeaderPhiOperandsToForeB
>> >>
>> >>    isSafeToUnrollAndJam should be used prior to calling this to make
>> sure the
>> >>    unrolling will be valid. Checking profitablility is also advisable.
>> >> +
>> >> +  If EpilogueLoop is non-null, it receives the epilogue loop (if it
>> was
>> >> +  necessary to create one and not fully unrolled).
>> >>  */
>> >> -LoopUnrollResult
>> >> -llvm::UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount,
>> >> -                       unsigned TripMultiple, bool UnrollRemainder,
>> >> -                       LoopInfo *LI, ScalarEvolution *SE,
>> DominatorTree *DT,
>> >> -                       AssumptionCache *AC, OptimizationRemarkEmitter
>> *ORE) {
>> >> +LoopUnrollResult llvm::UnrollAndJamLoop(
>> >> +    Loop *L, unsigned Count, unsigned TripCount, unsigned
>> TripMultiple,
>> >> +    bool UnrollRemainder, LoopInfo *LI, ScalarEvolution *SE,
>> DominatorTree *DT,
>> >> +    AssumptionCache *AC, OptimizationRemarkEmitter *ORE, Loop
>> **EpilogueLoop) {
>> >>
>> >>    // When we enter here we should have already checked that it is safe
>> >>    BasicBlock *Header = L->getHeader();
>> >> @@ -196,7 +198,8 @@ llvm::UnrollAndJamLoop(Loop *L, unsigned
>> >>    if (TripMultiple == 1 || TripMultiple % Count != 0) {
>> >>      if (!UnrollRuntimeLoopRemainder(L, Count,
>> /*AllowExpensiveTripCount*/ false,
>> >>                                      /*UseEpilogRemainder*/ true,
>> >> -                                    UnrollRemainder, LI, SE, DT, AC,
>> true)) {
>> >> +                                    UnrollRemainder, LI, SE, DT, AC,
>> true,
>> >> +                                    EpilogueLoop)) {
>> >>        LLVM_DEBUG(dbgs() << "Won't unroll-and-jam; remainder loop
>> could not be "
>> >>                             "generated when assuming runtime trip
>> count\n");
>> >>        return LoopUnrollResult::Unmodified;
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -380,6 +380,7 @@ CloneLoopBlocks(Loop *L, Value *NewIter,
>> >>    }
>> >>    if (CreateRemainderLoop) {
>> >>      Loop *NewLoop = NewLoops[L];
>> >> +    MDNode *LoopID = NewLoop->getLoopID();
>> >>      assert(NewLoop && "L should have been cloned");
>> >>
>> >>      // Only add loop metadata if the loop is not going to be
>> completely
>> >> @@ -387,6 +388,16 @@ CloneLoopBlocks(Loop *L, Value *NewIter,
>> >>      if (UnrollRemainder)
>> >>        return NewLoop;
>> >>
>> >> +    Optional<MDNode *> NewLoopID = makeFollowupLoopID(
>> >> +        LoopID, {LLVMLoopUnrollFollowupAll,
>> LLVMLoopUnrollFollowupRemainder});
>> >> +    if (NewLoopID.hasValue()) {
>> >> +      NewLoop->setLoopID(NewLoopID.getValue());
>> >> +
>> >> +      // Do not setLoopAlreadyUnrolled if loop attributes have been
>> defined
>> >> +      // explicitly.
>> >> +      return NewLoop;
>> >> +    }
>> >> +
>> >>      // Add unroll disable metadata to disable future unrolling for
>> this loop.
>> >>      NewLoop->setLoopAlreadyUnrolled();
>> >>      return NewLoop;
>> >> @@ -525,10 +536,10 @@ static bool canProfitablyUnrollMultiExit
>> >>  bool llvm::UnrollRuntimeLoopRemainder(Loop *L, unsigned Count,
>> >>                                        bool AllowExpensiveTripCount,
>> >>                                        bool UseEpilogRemainder,
>> >> -                                      bool UnrollRemainder,
>> >> -                                      LoopInfo *LI, ScalarEvolution
>> *SE,
>> >> -                                      DominatorTree *DT,
>> AssumptionCache *AC,
>> >> -                                      bool PreserveLCSSA) {
>> >> +                                      bool UnrollRemainder, LoopInfo
>> *LI,
>> >> +                                      ScalarEvolution *SE,
>> DominatorTree *DT,
>> >> +                                      AssumptionCache *AC, bool
>> PreserveLCSSA,
>> >> +                                      Loop **ResultLoop) {
>> >>    LLVM_DEBUG(dbgs() << "Trying runtime unrolling on Loop: \n");
>> >>    LLVM_DEBUG(L->dump());
>> >>    LLVM_DEBUG(UseEpilogRemainder ? dbgs() << "Using epilog
>> remainder.\n"
>> >> @@ -911,16 +922,20 @@ bool llvm::UnrollRuntimeLoopRemainder(Lo
>> >>        formDedicatedExitBlocks(remainderLoop, DT, LI, PreserveLCSSA);
>> >>    }
>> >>
>> >> +  auto UnrollResult = LoopUnrollResult::Unmodified;
>> >>    if (remainderLoop && UnrollRemainder) {
>> >>      LLVM_DEBUG(dbgs() << "Unrolling remainder loop\n");
>> >> -    UnrollLoop(remainderLoop, /*Count*/ Count - 1, /*TripCount*/
>> Count - 1,
>> >> -               /*Force*/ false, /*AllowRuntime*/ false,
>> >> -               /*AllowExpensiveTripCount*/ false, /*PreserveCondBr*/
>> true,
>> >> -               /*PreserveOnlyFirst*/ false, /*TripMultiple*/ 1,
>> >> -               /*PeelCount*/ 0, /*UnrollRemainder*/ false, LI, SE,
>> DT, AC,
>> >> -               /*ORE*/ nullptr, PreserveLCSSA);
>> >> +    UnrollResult =
>> >> +        UnrollLoop(remainderLoop, /*Count*/ Count - 1, /*TripCount*/
>> Count - 1,
>> >> +                   /*Force*/ false, /*AllowRuntime*/ false,
>> >> +                   /*AllowExpensiveTripCount*/ false,
>> /*PreserveCondBr*/ true,
>> >> +                   /*PreserveOnlyFirst*/ false, /*TripMultiple*/ 1,
>> >> +                   /*PeelCount*/ 0, /*UnrollRemainder*/ false, LI,
>> SE, DT, AC,
>> >> +                   /*ORE*/ nullptr, PreserveLCSSA);
>> >>    }
>> >>
>> >> +  if (ResultLoop && UnrollResult != LoopUnrollResult::FullyUnrolled)
>> >> +    *ResultLoop = remainderLoop;
>> >>    NumRuntimeUnrolled++;
>> >>    return true;
>> >>  }
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp Wed Dec 12 09:32:52
>> 2018
>> >> @@ -42,6 +42,8 @@ using namespace llvm::PatternMatch;
>> >>
>> >>  #define DEBUG_TYPE "loop-utils"
>> >>
>> >> +static const char *LLVMLoopDisableNonforced =
>> "llvm.loop.disable_nonforced";
>> >> +
>> >>  bool llvm::formDedicatedExitBlocks(Loop *L, DominatorTree *DT,
>> LoopInfo *LI,
>> >>                                     bool PreserveLCSSA) {
>> >>    bool Changed = false;
>> >> @@ -183,14 +185,8 @@ void llvm::initializeLoopPassPass(PassRe
>> >>    INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
>> >>  }
>> >>
>> >> -/// Find string metadata for loop
>> >> -///
>> >> -/// If it has a value (e.g. {"llvm.distribute", 1} return the value
>> as an
>> >> -/// operand or null otherwise.  If the string metadata is not found
>> return
>> >> -/// Optional's not-a-value.
>> >> -Optional<const MDOperand *> llvm::findStringMetadataForLoop(Loop
>> *TheLoop,
>> >> -                                                            StringRef
>> Name) {
>> >> -  MDNode *LoopID = TheLoop->getLoopID();
>> >> +static Optional<MDNode *> findOptionMDForLoopID(MDNode *LoopID,
>> >> +                                                StringRef Name) {
>> >>    // Return none if LoopID is false.
>> >>    if (!LoopID)
>> >>      return None;
>> >> @@ -209,18 +205,253 @@ Optional<const MDOperand *> llvm::findSt
>> >>        continue;
>> >>      // Return true if MDString holds expected MetaData.
>> >>      if (Name.equals(S->getString()))
>> >> -      switch (MD->getNumOperands()) {
>> >> -      case 1:
>> >> -        return nullptr;
>> >> -      case 2:
>> >> -        return &MD->getOperand(1);
>> >> -      default:
>> >> -        llvm_unreachable("loop metadata has 0 or 1 operand");
>> >> -      }
>> >> +      return MD;
>> >>    }
>> >>    return None;
>> >>  }
>> >>
>> >> +static Optional<MDNode *> findOptionMDForLoop(const Loop *TheLoop,
>> >> +                                              StringRef Name) {
>> >> +  return findOptionMDForLoopID(TheLoop->getLoopID(), Name);
>> >> +}
>> >> +
>> >> +/// Find string metadata for loop
>> >> +///
>> >> +/// If it has a value (e.g. {"llvm.distribute", 1} return the value
>> as an
>> >> +/// operand or null otherwise.  If the string metadata is not found
>> return
>> >> +/// Optional's not-a-value.
>> >> +Optional<const MDOperand *> llvm::findStringMetadataForLoop(Loop
>> *TheLoop,
>> >> +                                                            StringRef
>> Name) {
>> >> +  auto MD = findOptionMDForLoop(TheLoop, Name).getValueOr(nullptr);
>> >> +  if (!MD)
>> >> +    return None;
>> >> +  switch (MD->getNumOperands()) {
>> >> +  case 1:
>> >> +    return nullptr;
>> >> +  case 2:
>> >> +    return &MD->getOperand(1);
>> >> +  default:
>> >> +    llvm_unreachable("loop metadata has 0 or 1 operand");
>> >> +  }
>> >> +}
>> >> +
>> >> +static Optional<bool> getOptionalBoolLoopAttribute(const Loop
>> *TheLoop,
>> >> +                                                   StringRef Name) {
>> >> +  Optional<MDNode *> MD = findOptionMDForLoop(TheLoop, Name);
>> >> +  if (!MD.hasValue())
>> >> +    return None;
>> >> +  MDNode *OptionNode = MD.getValue();
>> >> +  if (OptionNode == nullptr)
>> >> +    return None;
>> >> +  switch (OptionNode->getNumOperands()) {
>> >> +  case 1:
>> >> +    // When the value is absent it is interpreted as 'attribute set'.
>> >> +    return true;
>> >> +  case 2:
>> >> +    return mdconst::extract_or_null<ConstantInt>(
>> >> +        OptionNode->getOperand(1).get());
>> >> +  }
>> >> +  llvm_unreachable("unexpected number of options");
>> >> +}
>> >> +
>> >> +static bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef
>> Name) {
>> >> +  return getOptionalBoolLoopAttribute(TheLoop,
>> Name).getValueOr(false);
>> >> +}
>> >> +
>> >> +llvm::Optional<int> llvm::getOptionalIntLoopAttribute(Loop *TheLoop,
>> >> +                                                      StringRef Name)
>> {
>> >> +  const MDOperand *AttrMD =
>> >> +      findStringMetadataForLoop(TheLoop, Name).getValueOr(nullptr);
>> >> +  if (!AttrMD)
>> >> +    return None;
>> >> +
>> >> +  ConstantInt *IntMD =
>> mdconst::extract_or_null<ConstantInt>(AttrMD->get());
>> >> +  if (!IntMD)
>> >> +    return None;
>> >> +
>> >> +  return IntMD->getSExtValue();
>> >> +}
>> >> +
>> >> +Optional<MDNode *> llvm::makeFollowupLoopID(
>> >> +    MDNode *OrigLoopID, ArrayRef<StringRef> FollowupOptions,
>> >> +    const char *InheritOptionsExceptPrefix, bool AlwaysNew) {
>> >> +  if (!OrigLoopID) {
>> >> +    if (AlwaysNew)
>> >> +      return nullptr;
>> >> +    return None;
>> >> +  }
>> >> +
>> >> +  assert(OrigLoopID->getOperand(0) == OrigLoopID);
>> >> +
>> >> +  bool InheritAllAttrs = !InheritOptionsExceptPrefix;
>> >> +  bool InheritSomeAttrs =
>> >> +      InheritOptionsExceptPrefix && InheritOptionsExceptPrefix[0] !=
>> '\0';
>> >> +  SmallVector<Metadata *, 8> MDs;
>> >> +  MDs.push_back(nullptr);
>> >> +
>> >> +  bool Changed = false;
>> >> +  if (InheritAllAttrs || InheritSomeAttrs) {
>> >> +    for (const MDOperand &Existing :
>> drop_begin(OrigLoopID->operands(), 1)) {
>> >> +      MDNode *Op = cast<MDNode>(Existing.get());
>> >> +
>> >> +      auto InheritThisAttribute = [InheritSomeAttrs,
>> >> +                                   InheritOptionsExceptPrefix](MDNode
>> *Op) {
>> >> +        if (!InheritSomeAttrs)
>> >> +          return false;
>> >> +
>> >> +        // Skip malformatted attribute metadata nodes.
>> >> +        if (Op->getNumOperands() == 0)
>> >> +          return true;
>> >> +        Metadata *NameMD = Op->getOperand(0).get();
>> >> +        if (!isa<MDString>(NameMD))
>> >> +          return true;
>> >> +        StringRef AttrName = cast<MDString>(NameMD)->getString();
>> >> +
>> >> +        // Do not inherit excluded attributes.
>> >> +        return !AttrName.startswith(InheritOptionsExceptPrefix);
>> >> +      };
>> >> +
>> >> +      if (InheritThisAttribute(Op))
>> >> +        MDs.push_back(Op);
>> >> +      else
>> >> +        Changed = true;
>> >> +    }
>> >> +  } else {
>> >> +    // Modified if we dropped at least one attribute.
>> >> +    Changed = OrigLoopID->getNumOperands() > 1;
>> >> +  }
>> >> +
>> >> +  bool HasAnyFollowup = false;
>> >> +  for (StringRef OptionName : FollowupOptions) {
>> >> +    MDNode *FollowupNode =
>> >> +        findOptionMDForLoopID(OrigLoopID,
>> OptionName).getValueOr(nullptr);
>> >> +    if (!FollowupNode)
>> >> +      continue;
>> >> +
>> >> +    HasAnyFollowup = true;
>> >> +    for (const MDOperand &Option :
>> drop_begin(FollowupNode->operands(), 1)) {
>> >> +      MDs.push_back(Option.get());
>> >> +      Changed = true;
>> >> +    }
>> >> +  }
>> >> +
>> >> +  // Attributes of the followup loop not specified explicity, so
>> signal to the
>> >> +  // transformation pass to add suitable attributes.
>> >> +  if (!AlwaysNew && !HasAnyFollowup)
>> >> +    return None;
>> >> +
>> >> +  // If no attributes were added or remove, the previous loop Id can
>> be reused.
>> >> +  if (!AlwaysNew && !Changed)
>> >> +    return OrigLoopID;
>> >> +
>> >> +  // No attributes is equivalent to having no !llvm.loop metadata at
>> all.
>> >> +  if (MDs.size() == 1)
>> >> +    return nullptr;
>> >> +
>> >> +  // Build the new loop ID.
>> >> +  MDTuple *FollowupLoopID = MDNode::get(OrigLoopID->getContext(),
>> MDs);
>> >> +  FollowupLoopID->replaceOperandWith(0, FollowupLoopID);
>> >> +  return FollowupLoopID;
>> >> +}
>> >> +
>> >> +bool llvm::hasDisableAllTransformsHint(const Loop *L) {
>> >> +  return getBooleanLoopAttribute(L, LLVMLoopDisableNonforced);
>> >> +}
>> >> +
>> >> +TransformationMode llvm::hasUnrollTransformation(Loop *L) {
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.unroll.disable"))
>> >> +    return TM_SuppressedByUser;
>> >> +
>> >> +  Optional<int> Count =
>> >> +      getOptionalIntLoopAttribute(L, "llvm.loop.unroll.count");
>> >> +  if (Count.hasValue())
>> >> +    return Count.getValue() == 1 ? TM_SuppressedByUser :
>> TM_ForcedByUser;
>> >> +
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.unroll.enable"))
>> >> +    return TM_ForcedByUser;
>> >> +
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.unroll.full"))
>> >> +    return TM_ForcedByUser;
>> >> +
>> >> +  if (hasDisableAllTransformsHint(L))
>> >> +    return TM_Disable;
>> >> +
>> >> +  return TM_Unspecified;
>> >> +}
>> >> +
>> >> +TransformationMode llvm::hasUnrollAndJamTransformation(Loop *L) {
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.unroll_and_jam.disable"))
>> >> +    return TM_SuppressedByUser;
>> >> +
>> >> +  Optional<int> Count =
>> >> +      getOptionalIntLoopAttribute(L,
>> "llvm.loop.unroll_and_jam.count");
>> >> +  if (Count.hasValue())
>> >> +    return Count.getValue() == 1 ? TM_SuppressedByUser :
>> TM_ForcedByUser;
>> >> +
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.unroll_and_jam.enable"))
>> >> +    return TM_ForcedByUser;
>> >> +
>> >> +  if (hasDisableAllTransformsHint(L))
>> >> +    return TM_Disable;
>> >> +
>> >> +  return TM_Unspecified;
>> >> +}
>> >> +
>> >> +TransformationMode llvm::hasVectorizeTransformation(Loop *L) {
>> >> +  Optional<bool> Enable =
>> >> +      getOptionalBoolLoopAttribute(L, "llvm.loop.vectorize.enable");
>> >> +
>> >> +  if (Enable == false)
>> >> +    return TM_SuppressedByUser;
>> >> +
>> >> +  Optional<int> VectorizeWidth =
>> >> +      getOptionalIntLoopAttribute(L, "llvm.loop.vectorize.width");
>> >> +  Optional<int> InterleaveCount =
>> >> +      getOptionalIntLoopAttribute(L, "llvm.loop.interleave.count");
>> >> +
>> >> +  if (Enable == true) {
>> >> +    // 'Forcing' vector width and interleave count to one effectively
>> disables
>> >> +    // this tranformation.
>> >> +    if (VectorizeWidth == 1 && InterleaveCount == 1)
>> >> +      return TM_SuppressedByUser;
>> >> +    return TM_ForcedByUser;
>> >> +  }
>> >> +
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.isvectorized"))
>> >> +    return TM_Disable;
>> >> +
>> >> +  if (VectorizeWidth == 1 && InterleaveCount == 1)
>> >> +    return TM_Disable;
>> >> +
>> >> +  if (VectorizeWidth > 1 || InterleaveCount > 1)
>> >> +    return TM_Enable;
>> >> +
>> >> +  if (hasDisableAllTransformsHint(L))
>> >> +    return TM_Disable;
>> >> +
>> >> +  return TM_Unspecified;
>> >> +}
>> >> +
>> >> +TransformationMode llvm::hasDistributeTransformation(Loop *L) {
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.distribute.enable"))
>> >> +    return TM_ForcedByUser;
>> >> +
>> >> +  if (hasDisableAllTransformsHint(L))
>> >> +    return TM_Disable;
>> >> +
>> >> +  return TM_Unspecified;
>> >> +}
>> >> +
>> >> +TransformationMode llvm::hasLICMVersioningTransformation(Loop *L) {
>> >> +  if (getBooleanLoopAttribute(L, "llvm.loop.licm_versioning.disable"))
>> >> +    return TM_SuppressedByUser;
>> >> +
>> >> +  if (hasDisableAllTransformsHint(L))
>> >> +    return TM_Disable;
>> >> +
>> >> +  return TM_Unspecified;
>> >> +}
>> >> +
>> >>  /// Does a BFS from a given node to all of its children inside a
>> given loop.
>> >>  /// The returned vector of nodes includes the starting point.
>> >>  SmallVector<DomTreeNode *, 16>
>> >>
>> >> Modified: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp (original)
>> >> +++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp Wed Dec 12
>> 09:32:52 2018
>> >> @@ -152,6 +152,16 @@ using namespace llvm;
>> >>  #define LV_NAME "loop-vectorize"
>> >>  #define DEBUG_TYPE LV_NAME
>> >>
>> >> +/// @{
>> >> +/// Metadata attribute names
>> >> +static const char *const LLVMLoopVectorizeFollowupAll =
>> >> +    "llvm.loop.vectorize.followup_all";
>> >> +static const char *const LLVMLoopVectorizeFollowupVectorized =
>> >> +    "llvm.loop.vectorize.followup_vectorized";
>> >> +static const char *const LLVMLoopVectorizeFollowupEpilogue =
>> >> +    "llvm.loop.vectorize.followup_epilogue";
>> >> +/// @}
>> >> +
>> >>  STATISTIC(LoopsVectorized, "Number of loops vectorized");
>> >>  STATISTIC(LoopsAnalyzed, "Number of loops analyzed for
>> vectorization");
>> >>
>> >> @@ -796,27 +806,6 @@ void InnerLoopVectorizer::addMetadata(Ar
>> >>    }
>> >>  }
>> >>
>> >> -static void emitMissedWarning(Function *F, Loop *L,
>> >> -                              const LoopVectorizeHints &LH,
>> >> -                              OptimizationRemarkEmitter *ORE) {
>> >> -  LH.emitRemarkWithHints();
>> >> -
>> >> -  if (LH.getForce() == LoopVectorizeHints::FK_Enabled) {
>> >> -    if (LH.getWidth() != 1)
>> >> -      ORE->emit(DiagnosticInfoOptimizationFailure(
>> >> -                    DEBUG_TYPE, "FailedRequestedVectorization",
>> >> -                    L->getStartLoc(), L->getHeader())
>> >> -                << "loop not vectorized: "
>> >> -                << "failed explicitly specified loop vectorization");
>> >> -    else if (LH.getInterleave() != 1)
>> >> -      ORE->emit(DiagnosticInfoOptimizationFailure(
>> >> -                    DEBUG_TYPE, "FailedRequestedInterleaving",
>> L->getStartLoc(),
>> >> -                    L->getHeader())
>> >> -                << "loop not interleaved: "
>> >> -                << "failed explicitly specified loop interleaving");
>> >> -  }
>> >> -}
>> >> -
>> >>  namespace llvm {
>> >>
>> >>  /// LoopVectorizationCostModel - estimates the expected speedups due
>> to
>> >> @@ -1377,7 +1366,7 @@ static bool isExplicitVecOuterLoop(Loop
>> >>
>> >>    if (!Hints.getWidth()) {
>> >>      LLVM_DEBUG(dbgs() << "LV: Not vectorizing: No user vector
>> width.\n");
>> >> -    emitMissedWarning(Fn, OuterLp, Hints, ORE);
>> >> +    Hints.emitRemarkWithHints();
>> >>      return false;
>> >>    }
>> >>
>> >> @@ -1385,7 +1374,7 @@ static bool isExplicitVecOuterLoop(Loop
>> >>      // TODO: Interleave support is future work.
>> >>      LLVM_DEBUG(dbgs() << "LV: Not vectorizing: Interleave is not
>> supported for "
>> >>                           "outer loops.\n");
>> >> -    emitMissedWarning(Fn, OuterLp, Hints, ORE);
>> >> +    Hints.emitRemarkWithHints();
>> >>      return false;
>> >>    }
>> >>
>> >> @@ -2739,6 +2728,7 @@ BasicBlock *InnerLoopVectorizer::createV
>> >>    BasicBlock *OldBasicBlock = OrigLoop->getHeader();
>> >>    BasicBlock *VectorPH = OrigLoop->getLoopPreheader();
>> >>    BasicBlock *ExitBlock = OrigLoop->getExitBlock();
>> >> +  MDNode *OrigLoopID = OrigLoop->getLoopID();
>> >>    assert(VectorPH && "Invalid loop structure");
>> >>    assert(ExitBlock && "Must have an exit block");
>> >>
>> >> @@ -2882,6 +2872,17 @@ BasicBlock *InnerLoopVectorizer::createV
>> >>    LoopVectorBody = VecBody;
>> >>    LoopScalarBody = OldBasicBlock;
>> >>
>> >> +  Optional<MDNode *> VectorizedLoopID =
>> >> +      makeFollowupLoopID(OrigLoopID, {LLVMLoopVectorizeFollowupAll,
>> >> +
>> LLVMLoopVectorizeFollowupVectorized});
>> >> +  if (VectorizedLoopID.hasValue()) {
>> >> +    Lp->setLoopID(VectorizedLoopID.getValue());
>> >> +
>> >> +    // Do not setAlreadyVectorized if loop attributes have been
>> defined
>> >> +    // explicitly.
>> >> +    return LoopVectorPreHeader;
>> >> +  }
>> >> +
>> >>    // Keep all loop hints from the original loop on the vector loop
>> (we'll
>> >>    // replace the vectorizer-specific hints below).
>> >>    if (MDNode *LID = OrigLoop->getLoopID())
>> >> @@ -7177,7 +7178,7 @@ bool LoopVectorizePass::processLoop(Loop
>> >>                                  &Requirements, &Hints, DB, AC);
>> >>    if (!LVL.canVectorize(EnableVPlanNativePath)) {
>> >>      LLVM_DEBUG(dbgs() << "LV: Not vectorizing: Cannot prove
>> legality.\n");
>> >> -    emitMissedWarning(F, L, Hints, ORE);
>> >> +    Hints.emitRemarkWithHints();
>> >>      return false;
>> >>    }
>> >>
>> >> @@ -7250,7 +7251,7 @@ bool LoopVectorizePass::processLoop(Loop
>> >>
>> ORE->emit(createLVMissedAnalysis(Hints.vectorizeAnalysisPassName(),
>> >>                                       "NoImplicitFloat", L)
>> >>                << "loop not vectorized due to NoImplicitFloat
>> attribute");
>> >> -    emitMissedWarning(F, L, Hints, ORE);
>> >> +    Hints.emitRemarkWithHints();
>> >>      return false;
>> >>    }
>> >>
>> >> @@ -7265,7 +7266,7 @@ bool LoopVectorizePass::processLoop(Loop
>> >>      ORE->emit(
>> >>          createLVMissedAnalysis(Hints.vectorizeAnalysisPassName(),
>> "UnsafeFP", L)
>> >>          << "loop not vectorized due to unsafe FP support.");
>> >> -    emitMissedWarning(F, L, Hints, ORE);
>> >> +    Hints.emitRemarkWithHints();
>> >>      return false;
>> >>    }
>> >>
>> >> @@ -7307,7 +7308,7 @@ bool LoopVectorizePass::processLoop(Loop
>> >>    if (Requirements.doesNotMeet(F, L, Hints)) {
>> >>      LLVM_DEBUG(dbgs() << "LV: Not vectorizing: loop did not meet
>> vectorization "
>> >>                           "requirements.\n");
>> >> -    emitMissedWarning(F, L, Hints, ORE);
>> >> +    Hints.emitRemarkWithHints();
>> >>      return false;
>> >>    }
>> >>
>> >> @@ -7384,6 +7385,8 @@ bool LoopVectorizePass::processLoop(Loop
>> >>    LVP.setBestPlan(VF.Width, IC);
>> >>
>> >>    using namespace ore;
>> >> +  bool DisableRuntimeUnroll = false;
>> >> +  MDNode *OrigLoopID = L->getLoopID();
>> >>
>> >>    if (!VectorizeLoop) {
>> >>      assert(IC > 1 && "interleave count should not be 1 or 0");
>> >> @@ -7410,7 +7413,7 @@ bool LoopVectorizePass::processLoop(Loop
>> >>      // no runtime checks about strides and memory. A scalar loop that
>> is
>> >>      // rarely used is not worth unrolling.
>> >>      if (!LB.areSafetyChecksAdded())
>> >> -      AddRuntimeUnrollDisableMetaData(L);
>> >> +      DisableRuntimeUnroll = true;
>> >>
>> >>      // Report the vectorization decision.
>> >>      ORE->emit([&]() {
>> >> @@ -7422,8 +7425,18 @@ bool LoopVectorizePass::processLoop(Loop
>> >>      });
>> >>    }
>> >>
>> >> -  // Mark the loop as already vectorized to avoid vectorizing again.
>> >> -  Hints.setAlreadyVectorized();
>> >> +  Optional<MDNode *> RemainderLoopID =
>> >> +      makeFollowupLoopID(OrigLoopID, {LLVMLoopVectorizeFollowupAll,
>> >> +
>> LLVMLoopVectorizeFollowupEpilogue});
>> >> +  if (RemainderLoopID.hasValue()) {
>> >> +    L->setLoopID(RemainderLoopID.getValue());
>> >> +  } else {
>> >> +    if (DisableRuntimeUnroll)
>> >> +      AddRuntimeUnrollDisableMetaData(L);
>> >> +
>> >> +    // Mark the loop as already vectorized to avoid vectorizing again.
>> >> +    Hints.setAlreadyVectorized();
>> >> +  }
>> >>
>> >>    LLVM_DEBUG(verifyFunction(*L->getHeader()->getParent()));
>> >>    return true;
>> >>
>> >> Modified: llvm/trunk/test/Other/new-pm-defaults.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pm-defaults.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Other/new-pm-defaults.ll (original)
>> >> +++ llvm/trunk/test/Other/new-pm-defaults.ll Wed Dec 12 09:32:52 2018
>> >> @@ -246,6 +246,7 @@
>> >>  ; CHECK-O-NEXT: Running pass: InstCombinePass
>> >>  ; CHECK-O-NEXT: Running pass: LoopUnrollPass
>> >>  ; CHECK-O-NEXT: Running analysis: OuterAnalysisManagerProxy
>> >> +; CHECK-O-NEXT: Running pass: WarnMissedTransformationsPass
>> >>  ; CHECK-O-NEXT: Running pass: InstCombinePass
>> >>  ; CHECK-O-NEXT: Running pass:
>> RequireAnalysisPass<{{.*}}OptimizationRemarkEmitterAnalysis
>> >>  ; CHECK-O-NEXT: Running pass: FunctionToLoopPassAdaptor<{{.*}}LICMPass
>> >>
>> >> Modified: llvm/trunk/test/Other/new-pm-thinlto-defaults.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pm-thinlto-defaults.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Other/new-pm-thinlto-defaults.ll (original)
>> >> +++ llvm/trunk/test/Other/new-pm-thinlto-defaults.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -224,6 +224,7 @@
>> >>  ; CHECK-POSTLINK-O-NEXT: Running pass: InstCombinePass
>> >>  ; CHECK-POSTLINK-O-NEXT: Running pass: LoopUnrollPass
>> >>  ; CHECK-POSTLINK-O-NEXT: Running analysis: OuterAnalysisManagerProxy
>> >> +; CHECK-POSTLINK-O-NEXT: Running pass: WarnMissedTransformationsPass
>> >>  ; CHECK-POSTLINK-O-NEXT: Running pass: InstCombinePass
>> >>  ; CHECK-POSTLINK-O-NEXT: Running pass:
>> RequireAnalysisPass<{{.*}}OptimizationRemarkEmitterAnalysis
>> >>  ; CHECK-POSTLINK-O-NEXT: Running pass:
>> FunctionToLoopPassAdaptor<{{.*}}LICMPass
>> >>
>> >> Modified: llvm/trunk/test/Other/opt-O2-pipeline.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-O2-pipeline.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Other/opt-O2-pipeline.ll (original)
>> >> +++ llvm/trunk/test/Other/opt-O2-pipeline.ll Wed Dec 12 09:32:52 2018
>> >> @@ -250,6 +250,10 @@
>> >>  ; CHECK-NEXT:       Scalar Evolution Analysis
>> >>  ; CHECK-NEXT:       Loop Pass Manager
>> >>  ; CHECK-NEXT:         Loop Invariant Code Motion
>> >> +; CHECK-NEXT:       Lazy Branch Probability Analysis
>> >> +; CHECK-NEXT:       Lazy Block Frequency Analysis
>> >> +; CHECK-NEXT:       Optimization Remark Emitter
>> >> +; CHECK-NEXT:       Warn about non-applied transformations
>> >>  ; CHECK-NEXT:       Alignment from assumptions
>> >>  ; CHECK-NEXT:     Strip Unused Function Prototypes
>> >>  ; CHECK-NEXT:     Dead Global Elimination
>> >>
>> >> Modified: llvm/trunk/test/Other/opt-O3-pipeline.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-O3-pipeline.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Other/opt-O3-pipeline.ll (original)
>> >> +++ llvm/trunk/test/Other/opt-O3-pipeline.ll Wed Dec 12 09:32:52 2018
>> >> @@ -255,6 +255,10 @@
>> >>  ; CHECK-NEXT:       Scalar Evolution Analysis
>> >>  ; CHECK-NEXT:       Loop Pass Manager
>> >>  ; CHECK-NEXT:         Loop Invariant Code Motion
>> >> +; CHECK-NEXT:       Lazy Branch Probability Analysis
>> >> +; CHECK-NEXT:       Lazy Block Frequency Analysis
>> >> +; CHECK-NEXT:       Optimization Remark Emitter
>> >> +; CHECK-NEXT:       Warn about non-applied transformations
>> >>  ; CHECK-NEXT:       Alignment from assumptions
>> >>  ; CHECK-NEXT:     Strip Unused Function Prototypes
>> >>  ; CHECK-NEXT:     Dead Global Elimination
>> >>
>> >> Modified: llvm/trunk/test/Other/opt-Os-pipeline.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-Os-pipeline.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Other/opt-Os-pipeline.ll (original)
>> >> +++ llvm/trunk/test/Other/opt-Os-pipeline.ll Wed Dec 12 09:32:52 2018
>> >> @@ -237,6 +237,10 @@
>> >>  ; CHECK-NEXT:       Scalar Evolution Analysis
>> >>  ; CHECK-NEXT:       Loop Pass Manager
>> >>  ; CHECK-NEXT:         Loop Invariant Code Motion
>> >> +; CHECK-NEXT:       Lazy Branch Probability Analysis
>> >> +; CHECK-NEXT:       Lazy Block Frequency Analysis
>> >> +; CHECK-NEXT:       Optimization Remark Emitter
>> >> +; CHECK-NEXT:       Warn about non-applied transformations
>> >>  ; CHECK-NEXT:       Alignment from assumptions
>> >>  ; CHECK-NEXT:     Strip Unused Function Prototypes
>> >>  ; CHECK-NEXT:     Dead Global Elimination
>> >>
>> >> Modified: llvm/trunk/test/Other/opt-hot-cold-split.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-hot-cold-split.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Other/opt-hot-cold-split.ll (original)
>> >> +++ llvm/trunk/test/Other/opt-hot-cold-split.ll Wed Dec 12 09:32:52
>> 2018
>> >> @@ -236,6 +236,10 @@
>> >>  ; CHECK-NEXT:       Scalar Evolution Analysis
>> >>  ; CHECK-NEXT:       Loop Pass Manager
>> >>  ; CHECK-NEXT:         Loop Invariant Code Motion
>> >> +; CHECK-NEXT:       Lazy Branch Probability Analysis
>> >> +; CHECK-NEXT:       Lazy Block Frequency Analysis
>> >> +; CHECK-NEXT:       Optimization Remark Emitter
>> >> +; CHECK-NEXT:       Warn about non-applied transformations
>> >>  ; CHECK-NEXT:       Alignment from assumptions
>> >>  ; CHECK-NEXT:     Strip Unused Function Prototypes
>> >>  ; CHECK-NEXT:     Dead Global Elimination
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced.ll
>> (added)
>> >> +++ llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,50 @@
>> >> +; RUN: opt -loop-distribute -enable-loop-distribute=1 -S < %s |
>> FileCheck %s
>> >> +;
>> >> +; Check that the disable_nonforced is honored by loop distribution.
>> >> +;
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced(
>> >> +; CHECK-NOT: for.body.ldist1:
>> >> +define void @disable_nonforced(i32* noalias %a,
>> >> +                         i32* noalias %b,
>> >> +                         i32* noalias %c,
>> >> +                         i32* noalias %d,
>> >> +                         i32* noalias %e) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
>> >> +
>> >> +  %arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
>> >> +  %loadA = load i32, i32* %arrayidxA, align 4
>> >> +
>> >> +  %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
>> >> +  %loadB = load i32, i32* %arrayidxB, align 4
>> >> +
>> >> +  %mulA = mul i32 %loadB, %loadA
>> >> +
>> >> +  %add = add nuw nsw i64 %ind, 1
>> >> +  %arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
>> >> +  store i32 %mulA, i32* %arrayidxA_plus_4, align 4
>> >> +
>> >> +  %arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
>> >> +  %loadD = load i32, i32* %arrayidxD, align 4
>> >> +
>> >> +  %arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
>> >> +  %loadE = load i32, i32* %arrayidxE, align 4
>> >> +
>> >> +  %mulC = mul i32 %loadD, %loadE
>> >> +
>> >> +  %arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
>> >> +  store i32 %mulC, i32* %arrayidxC, align 4
>> >> +
>> >> +  %exitcond = icmp eq i64 %add, 20
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced_enable.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced_enable.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced_enable.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopDistribute/disable_nonforced_enable.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,51 @@
>> >> +; RUN: opt -loop-distribute -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that llvm.loop.distribute.enable overrides
>> >> +; llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced(
>> >> +; CHECK: for.body.ldist1:
>> >> +define void @disable_nonforced(i32* noalias %a,
>> >> +                         i32* noalias %b,
>> >> +                         i32* noalias %c,
>> >> +                         i32* noalias %d,
>> >> +                         i32* noalias %e) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
>> >> +
>> >> +  %arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
>> >> +  %loadA = load i32, i32* %arrayidxA, align 4
>> >> +
>> >> +  %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
>> >> +  %loadB = load i32, i32* %arrayidxB, align 4
>> >> +
>> >> +  %mulA = mul i32 %loadB, %loadA
>> >> +
>> >> +  %add = add nuw nsw i64 %ind, 1
>> >> +  %arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
>> >> +  store i32 %mulA, i32* %arrayidxA_plus_4, align 4
>> >> +
>> >> +  %arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
>> >> +  %loadD = load i32, i32* %arrayidxD, align 4
>> >> +
>> >> +  %arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
>> >> +  %loadE = load i32, i32* %arrayidxE, align 4
>> >> +
>> >> +  %mulC = mul i32 %loadD, %loadE
>> >> +
>> >> +  %arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
>> >> +  store i32 %mulC, i32* %arrayidxC, align 4
>> >> +
>> >> +  %exitcond = icmp eq i64 %add, 20
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.distribute.enable", i32 1}}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopDistribute/followup.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopDistribute/followup.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopDistribute/followup.ll (added)
>> >> +++ llvm/trunk/test/Transforms/LoopDistribute/followup.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -0,0 +1,66 @@
>> >> +; RUN: opt -basicaa -loop-distribute -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that followup loop-attributes are applied to the loops after
>> >> +; loop distribution.
>> >> +;
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +define void @f(i32* %a, i32* %b, i32* %c, i32* %d, i32* %e) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %ind = phi i64 [ 0, %entry ], [ %add, %for.body ]
>> >> +
>> >> +  %arrayidxA = getelementptr inbounds i32, i32* %a, i64 %ind
>> >> +  %loadA = load i32, i32* %arrayidxA, align 4
>> >> +
>> >> +  %arrayidxB = getelementptr inbounds i32, i32* %b, i64 %ind
>> >> +  %loadB = load i32, i32* %arrayidxB, align 4
>> >> +
>> >> +  %mulA = mul i32 %loadB, %loadA
>> >> +
>> >> +  %add = add nuw nsw i64 %ind, 1
>> >> +  %arrayidxA_plus_4 = getelementptr inbounds i32, i32* %a, i64 %add
>> >> +  store i32 %mulA, i32* %arrayidxA_plus_4, align 4
>> >> +
>> >> +  %arrayidxD = getelementptr inbounds i32, i32* %d, i64 %ind
>> >> +  %loadD = load i32, i32* %arrayidxD, align 4
>> >> +
>> >> +  %arrayidxE = getelementptr inbounds i32, i32* %e, i64 %ind
>> >> +  %loadE = load i32, i32* %arrayidxE, align 4
>> >> +
>> >> +  %mulC = mul i32 %loadD, %loadE
>> >> +
>> >> +  %arrayidxC = getelementptr inbounds i32, i32* %c, i64 %ind
>> >> +  store i32 %mulC, i32* %arrayidxC, align 4
>> >> +
>> >> +  %exitcond = icmp eq i64 %add, 20
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !1, !2, !3, !4, !5}
>> >> +!1 = !{!"llvm.loop.distribute.enable", i1 true}
>> >> +!2 = !{!"llvm.loop.distribute.followup_all", !{!"FollowupAll"}}
>> >> +!3 = !{!"llvm.loop.distribute.followup_coincident",
>> !{!"FollowupCoincident", i1 false}}
>> >> +!4 = !{!"llvm.loop.distribute.followup_sequential",
>> !{!"FollowupSequential", i32 8}}
>> >> +!5 = !{!"llvm.loop.distribute.followup_fallback",
>> !{!"FollowupFallback"}}
>> >> +
>> >> +
>> >> +; CHECK-LABEL: for.body.lver.orig:
>> >> +; CHECK: br i1 %exitcond.lver.orig, label %for.end, label
>> %for.body.lver.orig, !llvm.loop ![[LOOP_ORIG:[0-9]+]]
>> >> +; CHECK-LABEL: for.body.ldist1:
>> >> +; CHECK: br i1 %exitcond.ldist1, label %for.body.ph, label
>> %for.body.ldist1, !llvm.loop ![[LOOP_SEQUENTIAL:[0-9]+]]
>> >> +; CHECK-LABEL: for.body:
>> >> +; CHECK: br i1 %exitcond, label %for.end, label %for.body, !llvm.loop
>> ![[LOOP_COINCIDENT:[0-9]+]]
>> >> +
>> >> +; CHECK: ![[LOOP_ORIG]] = distinct !{![[LOOP_ORIG]],
>> ![[FOLLOWUP_ALL:[0-9]+]], ![[FOLLOUP_FALLBACK:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_ALL]] = !{!"FollowupAll"}
>> >> +; CHECK: ![[FOLLOUP_FALLBACK]] = !{!"FollowupFallback"}
>> >> +; CHECK: ![[LOOP_SEQUENTIAL]] = distinct !{![[LOOP_SEQUENTIAL]],
>> ![[FOLLOWUP_ALL]], ![[FOLLOWUP_SEQUENTIAL:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_SEQUENTIAL]] = !{!"FollowupSequential", i32 8}
>> >> +; CHECK: ![[LOOP_COINCIDENT]] = distinct !{![[LOOP_COINCIDENT]],
>> ![[FOLLOWUP_ALL]], ![[FOLLOWUP_COINCIDENT:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_COINCIDENT]] = !{!"FollowupCoincident", i1 false}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopTransformWarning/distribution-remarks-missed.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopTransformWarning/distribution-remarks-missed.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopTransformWarning/distribution-remarks-missed.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopTransformWarning/distribution-remarks-missed.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,99 @@
>> >> +; Legacy pass manager
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +; New pass manager
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +
>> >> +; CHECK: warning: source.cpp:19:5: loop not distributed: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering
>> >> +
>> >> +; YAML:     --- !Failure
>> >> +; YAML-NEXT: Pass:            transform-warning
>> >> +; YAML-NEXT: Name:            FailedRequestedDistribution
>> >> +; YAML-NEXT: DebugLoc:        { File: source.cpp, Line: 19, Column: 5
>> }
>> >> +; YAML-NEXT: Function:        _Z17test_array_boundsPiS_i
>> >> +; YAML-NEXT: Args:
>> >> +; YAML-NEXT:   - String:          'loop not distributed: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering'
>> >> +; YAML-NEXT: ...
>> >> +
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +define void @_Z17test_array_boundsPiS_i(i32* nocapture %A, i32*
>> nocapture readonly %B, i32 %Length) !dbg !8 {
>> >> +entry:
>> >> +  %cmp9 = icmp sgt i32 %Length, 0, !dbg !32
>> >> +  br i1 %cmp9, label %for.body.preheader, label %for.end, !dbg !32
>> >> +
>> >> +for.body.preheader:
>> >> +  br label %for.body, !dbg !35
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0,
>> %for.body.preheader ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv,
>> !dbg !35
>> >> +  %0 = load i32, i32* %arrayidx, align 4, !dbg !35, !tbaa !18
>> >> +  %idxprom1 = sext i32 %0 to i64, !dbg !35
>> >> +  %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %idxprom1,
>> !dbg !35
>> >> +  %1 = load i32, i32* %arrayidx2, align 4, !dbg !35, !tbaa !18
>> >> +  %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv,
>> !dbg !35
>> >> +  store i32 %1, i32* %arrayidx4, align 4, !dbg !35, !tbaa !18
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !32
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !32
>> >> +  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg
>> !32, !llvm.loop !50
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void, !dbg !36
>> >> +}
>> >> +
>> >> +!llvm.dbg.cu = !{!0}
>> >> +!llvm.module.flags = !{!9, !10}
>> >> +!llvm.ident = !{!11}
>> >> +
>> >> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer:
>> "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind:
>> LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2,
>> imports: !2)
>> >> +!1 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!2 = !{}
>> >> +!4 = distinct !DISubprogram(name: "test", line: 1, isLocal: false,
>> isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized:
>> true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes:
>> !2)
>> >> +!5 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!6 = !DISubroutineType(types: !2)
>> >> +!7 = distinct !DISubprogram(name: "test_disabled", line: 10, isLocal:
>> false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped,
>> isOptimized: true, unit: !0, scopeLine: 10, file: !1, scope: !5, type: !6,
>> retainedNodes: !2)
>> >> +!8 = distinct !DISubprogram(name: "test_array_bounds", line: 16,
>> isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 16, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +!9 = !{i32 2, !"Dwarf Version", i32 2}
>> >> +!10 = !{i32 2, !"Debug Info Version", i32 3}
>> >> +!11 = !{!"clang version 3.5.0"}
>> >> +!12 = !DILocation(line: 3, column: 8, scope: !13)
>> >> +!13 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope:
>> !4)
>> >> +!16 = !DILocation(line: 4, column: 5, scope: !17)
>> >> +!17 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope:
>> !13)
>> >> +!18 = !{!19, !19, i64 0}
>> >> +!19 = !{!"int", !20, i64 0}
>> >> +!20 = !{!"omnipotent char", !21, i64 0}
>> >> +!21 = !{!"Simple C/C++ TBAA"}
>> >> +!22 = !DILocation(line: 5, column: 9, scope: !23)
>> >> +!23 = distinct !DILexicalBlock(line: 5, column: 9, file: !1, scope:
>> !17)
>> >> +!24 = !DILocation(line: 8, column: 1, scope: !4)
>> >> +!25 = !DILocation(line: 12, column: 8, scope: !26)
>> >> +!26 = distinct !DILexicalBlock(line: 12, column: 3, file: !1, scope:
>> !7)
>> >> +!30 = !DILocation(line: 13, column: 5, scope: !26)
>> >> +!31 = !DILocation(line: 14, column: 1, scope: !7)
>> >> +!32 = !DILocation(line: 18, column: 8, scope: !33)
>> >> +!33 = distinct !DILexicalBlock(line: 18, column: 3, file: !1, scope:
>> !8)
>> >> +!35 = !DILocation(line: 19, column: 5, scope: !33)
>> >> +!36 = !DILocation(line: 20, column: 1, scope: !8)
>> >> +!37 = distinct !DILexicalBlock(line: 24, column: 3, file: !1, scope:
>> !46)
>> >> +!38 = !DILocation(line: 27, column: 3, scope: !37)
>> >> +!39 = !DILocation(line: 31, column: 3, scope: !37)
>> >> +!40 = !DILocation(line: 28, column: 9, scope: !37)
>> >> +!41 = !DILocation(line: 29, column: 11, scope: !37)
>> >> +!42 = !DILocation(line: 29, column: 7, scope: !37)
>> >> +!43 = !DILocation(line: 27, column: 32, scope: !37)
>> >> +!44 = !DILocation(line: 27, column: 30, scope: !37)
>> >> +!45 = !DILocation(line: 27, column: 21, scope: !37)
>> >> +!46 = distinct !DISubprogram(name: "test_multiple_failures", line:
>> 26, isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 26, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +
>> >> +!50 = !{!50, !{!"llvm.loop.distribute.enable"}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopTransformWarning/unrollandjam-remarks-missed.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopTransformWarning/unrollandjam-remarks-missed.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopTransformWarning/unrollandjam-remarks-missed.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopTransformWarning/unrollandjam-remarks-missed.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,99 @@
>> >> +; Legacy pass manager
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +; New pass manager
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +
>> >> +; CHECK: warning: source.cpp:19:5: loop not unroll-and-jammed: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering
>> >> +
>> >> +; YAML:     --- !Failure
>> >> +; YAML-NEXT: Pass:            transform-warning
>> >> +; YAML-NEXT: Name:            FailedRequestedUnrollAndJamming
>> >> +; YAML-NEXT: DebugLoc:        { File: source.cpp, Line: 19, Column: 5
>> }
>> >> +; YAML-NEXT: Function:        _Z17test_array_boundsPiS_i
>> >> +; YAML-NEXT: Args:
>> >> +; YAML-NEXT:   - String:          'loop not unroll-and-jammed: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering'
>> >> +; YAML-NEXT: ...
>> >> +
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +define void @_Z17test_array_boundsPiS_i(i32* nocapture %A, i32*
>> nocapture readonly %B, i32 %Length) !dbg !8 {
>> >> +entry:
>> >> +  %cmp9 = icmp sgt i32 %Length, 0, !dbg !32
>> >> +  br i1 %cmp9, label %for.body.preheader, label %for.end, !dbg !32
>> >> +
>> >> +for.body.preheader:
>> >> +  br label %for.body, !dbg !35
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0,
>> %for.body.preheader ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv,
>> !dbg !35
>> >> +  %0 = load i32, i32* %arrayidx, align 4, !dbg !35, !tbaa !18
>> >> +  %idxprom1 = sext i32 %0 to i64, !dbg !35
>> >> +  %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %idxprom1,
>> !dbg !35
>> >> +  %1 = load i32, i32* %arrayidx2, align 4, !dbg !35, !tbaa !18
>> >> +  %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv,
>> !dbg !35
>> >> +  store i32 %1, i32* %arrayidx4, align 4, !dbg !35, !tbaa !18
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !32
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !32
>> >> +  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg
>> !32, !llvm.loop !50
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void, !dbg !36
>> >> +}
>> >> +
>> >> +!llvm.dbg.cu = !{!0}
>> >> +!llvm.module.flags = !{!9, !10}
>> >> +!llvm.ident = !{!11}
>> >> +
>> >> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer:
>> "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind:
>> LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2,
>> imports: !2)
>> >> +!1 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!2 = !{}
>> >> +!4 = distinct !DISubprogram(name: "test", line: 1, isLocal: false,
>> isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized:
>> true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes:
>> !2)
>> >> +!5 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!6 = !DISubroutineType(types: !2)
>> >> +!7 = distinct !DISubprogram(name: "test_disabled", line: 10, isLocal:
>> false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped,
>> isOptimized: true, unit: !0, scopeLine: 10, file: !1, scope: !5, type: !6,
>> retainedNodes: !2)
>> >> +!8 = distinct !DISubprogram(name: "test_array_bounds", line: 16,
>> isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 16, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +!9 = !{i32 2, !"Dwarf Version", i32 2}
>> >> +!10 = !{i32 2, !"Debug Info Version", i32 3}
>> >> +!11 = !{!"clang version 3.5.0"}
>> >> +!12 = !DILocation(line: 3, column: 8, scope: !13)
>> >> +!13 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope:
>> !4)
>> >> +!16 = !DILocation(line: 4, column: 5, scope: !17)
>> >> +!17 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope:
>> !13)
>> >> +!18 = !{!19, !19, i64 0}
>> >> +!19 = !{!"int", !20, i64 0}
>> >> +!20 = !{!"omnipotent char", !21, i64 0}
>> >> +!21 = !{!"Simple C/C++ TBAA"}
>> >> +!22 = !DILocation(line: 5, column: 9, scope: !23)
>> >> +!23 = distinct !DILexicalBlock(line: 5, column: 9, file: !1, scope:
>> !17)
>> >> +!24 = !DILocation(line: 8, column: 1, scope: !4)
>> >> +!25 = !DILocation(line: 12, column: 8, scope: !26)
>> >> +!26 = distinct !DILexicalBlock(line: 12, column: 3, file: !1, scope:
>> !7)
>> >> +!30 = !DILocation(line: 13, column: 5, scope: !26)
>> >> +!31 = !DILocation(line: 14, column: 1, scope: !7)
>> >> +!32 = !DILocation(line: 18, column: 8, scope: !33)
>> >> +!33 = distinct !DILexicalBlock(line: 18, column: 3, file: !1, scope:
>> !8)
>> >> +!35 = !DILocation(line: 19, column: 5, scope: !33)
>> >> +!36 = !DILocation(line: 20, column: 1, scope: !8)
>> >> +!37 = distinct !DILexicalBlock(line: 24, column: 3, file: !1, scope:
>> !46)
>> >> +!38 = !DILocation(line: 27, column: 3, scope: !37)
>> >> +!39 = !DILocation(line: 31, column: 3, scope: !37)
>> >> +!40 = !DILocation(line: 28, column: 9, scope: !37)
>> >> +!41 = !DILocation(line: 29, column: 11, scope: !37)
>> >> +!42 = !DILocation(line: 29, column: 7, scope: !37)
>> >> +!43 = !DILocation(line: 27, column: 32, scope: !37)
>> >> +!44 = !DILocation(line: 27, column: 30, scope: !37)
>> >> +!45 = !DILocation(line: 27, column: 21, scope: !37)
>> >> +!46 = distinct !DISubprogram(name: "test_multiple_failures", line:
>> 26, isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 26, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +
>> >> +!50 = !{!50, !{!"llvm.loop.unroll_and_jam.enable"}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopTransformWarning/unrolling-remarks-missed.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopTransformWarning/unrolling-remarks-missed.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopTransformWarning/unrolling-remarks-missed.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopTransformWarning/unrolling-remarks-missed.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,99 @@
>> >> +; Legacy pass manager
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +; New pass manager
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +
>> >> +; CHECK: warning: source.cpp:19:5: loop not unrolled: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering
>> >> +
>> >> +; YAML:     --- !Failure
>> >> +; YAML-NEXT: Pass:            transform-warning
>> >> +; YAML-NEXT: Name:            FailedRequestedUnrolling
>> >> +; YAML-NEXT: DebugLoc:        { File: source.cpp, Line: 19, Column: 5
>> }
>> >> +; YAML-NEXT: Function:        _Z17test_array_boundsPiS_i
>> >> +; YAML-NEXT: Args:
>> >> +; YAML-NEXT:   - String:          'loop not unrolled: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering'
>> >> +; YAML-NEXT: ...
>> >> +
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +define void @_Z17test_array_boundsPiS_i(i32* nocapture %A, i32*
>> nocapture readonly %B, i32 %Length) !dbg !8 {
>> >> +entry:
>> >> +  %cmp9 = icmp sgt i32 %Length, 0, !dbg !32
>> >> +  br i1 %cmp9, label %for.body.preheader, label %for.end, !dbg !32
>> >> +
>> >> +for.body.preheader:
>> >> +  br label %for.body, !dbg !35
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0,
>> %for.body.preheader ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv,
>> !dbg !35
>> >> +  %0 = load i32, i32* %arrayidx, align 4, !dbg !35, !tbaa !18
>> >> +  %idxprom1 = sext i32 %0 to i64, !dbg !35
>> >> +  %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %idxprom1,
>> !dbg !35
>> >> +  %1 = load i32, i32* %arrayidx2, align 4, !dbg !35, !tbaa !18
>> >> +  %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv,
>> !dbg !35
>> >> +  store i32 %1, i32* %arrayidx4, align 4, !dbg !35, !tbaa !18
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !32
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !32
>> >> +  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg
>> !32, !llvm.loop !50
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void, !dbg !36
>> >> +}
>> >> +
>> >> +!llvm.dbg.cu = !{!0}
>> >> +!llvm.module.flags = !{!9, !10}
>> >> +!llvm.ident = !{!11}
>> >> +
>> >> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer:
>> "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind:
>> LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2,
>> imports: !2)
>> >> +!1 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!2 = !{}
>> >> +!4 = distinct !DISubprogram(name: "test", line: 1, isLocal: false,
>> isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized:
>> true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes:
>> !2)
>> >> +!5 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!6 = !DISubroutineType(types: !2)
>> >> +!7 = distinct !DISubprogram(name: "test_disabled", line: 10, isLocal:
>> false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped,
>> isOptimized: true, unit: !0, scopeLine: 10, file: !1, scope: !5, type: !6,
>> retainedNodes: !2)
>> >> +!8 = distinct !DISubprogram(name: "test_array_bounds", line: 16,
>> isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 16, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +!9 = !{i32 2, !"Dwarf Version", i32 2}
>> >> +!10 = !{i32 2, !"Debug Info Version", i32 3}
>> >> +!11 = !{!"clang version 3.5.0"}
>> >> +!12 = !DILocation(line: 3, column: 8, scope: !13)
>> >> +!13 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope:
>> !4)
>> >> +!16 = !DILocation(line: 4, column: 5, scope: !17)
>> >> +!17 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope:
>> !13)
>> >> +!18 = !{!19, !19, i64 0}
>> >> +!19 = !{!"int", !20, i64 0}
>> >> +!20 = !{!"omnipotent char", !21, i64 0}
>> >> +!21 = !{!"Simple C/C++ TBAA"}
>> >> +!22 = !DILocation(line: 5, column: 9, scope: !23)
>> >> +!23 = distinct !DILexicalBlock(line: 5, column: 9, file: !1, scope:
>> !17)
>> >> +!24 = !DILocation(line: 8, column: 1, scope: !4)
>> >> +!25 = !DILocation(line: 12, column: 8, scope: !26)
>> >> +!26 = distinct !DILexicalBlock(line: 12, column: 3, file: !1, scope:
>> !7)
>> >> +!30 = !DILocation(line: 13, column: 5, scope: !26)
>> >> +!31 = !DILocation(line: 14, column: 1, scope: !7)
>> >> +!32 = !DILocation(line: 18, column: 8, scope: !33)
>> >> +!33 = distinct !DILexicalBlock(line: 18, column: 3, file: !1, scope:
>> !8)
>> >> +!35 = !DILocation(line: 19, column: 5, scope: !33)
>> >> +!36 = !DILocation(line: 20, column: 1, scope: !8)
>> >> +!37 = distinct !DILexicalBlock(line: 24, column: 3, file: !1, scope:
>> !46)
>> >> +!38 = !DILocation(line: 27, column: 3, scope: !37)
>> >> +!39 = !DILocation(line: 31, column: 3, scope: !37)
>> >> +!40 = !DILocation(line: 28, column: 9, scope: !37)
>> >> +!41 = !DILocation(line: 29, column: 11, scope: !37)
>> >> +!42 = !DILocation(line: 29, column: 7, scope: !37)
>> >> +!43 = !DILocation(line: 27, column: 32, scope: !37)
>> >> +!44 = !DILocation(line: 27, column: 30, scope: !37)
>> >> +!45 = !DILocation(line: 27, column: 21, scope: !37)
>> >> +!46 = distinct !DISubprogram(name: "test_multiple_failures", line:
>> 26, isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 26, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +
>> >> +!50 = !{!50, !{!"llvm.loop.unroll.enable"}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopTransformWarning/vectorization-remarks-missed.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopTransformWarning/vectorization-remarks-missed.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopTransformWarning/vectorization-remarks-missed.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopTransformWarning/vectorization-remarks-missed.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,113 @@
>> >> +; Legacy pass manager
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +; New pass manager
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-missed=transform-warning
>> -pass-remarks-analysis=transform-warning 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -passes=transform-warning -disable-output
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >> +
>> >> +
>> >> +; C/C++ code for tests
>> >> +; void test(int *A, int Length) {
>> >> +; #pragma clang loop vectorize(enable) interleave(enable)
>> >> +;   for (int i = 0; i < Length; i++) {
>> >> +;     A[i] = i;
>> >> +;     if (A[i] > Length)
>> >> +;       break;
>> >> +;   }
>> >> +; }
>> >> +; File, line, and column should match those specified in the metadata
>> >> +; CHECK: warning: source.cpp:19:5: loop not vectorized: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering
>> >> +
>> >> +; YAML:     --- !Failure
>> >> +; YAML-NEXT: Pass:            transform-warning
>> >> +; YAML-NEXT: Name:            FailedRequestedVectorization
>> >> +; YAML-NEXT: DebugLoc:        { File: source.cpp, Line: 19, Column: 5
>> }
>> >> +; YAML-NEXT: Function:        _Z17test_array_boundsPiS_i
>> >> +; YAML-NEXT: Args:
>> >> +; YAML-NEXT:   - String:          'loop not vectorized: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering'
>> >> +; YAML-NEXT: ...
>> >> +
>> >> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +define void @_Z17test_array_boundsPiS_i(i32* nocapture %A, i32*
>> nocapture readonly %B, i32 %Length) !dbg !8 {
>> >> +entry:
>> >> +  %cmp9 = icmp sgt i32 %Length, 0, !dbg !32
>> >> +  br i1 %cmp9, label %for.body.preheader, label %for.end, !dbg !32,
>> !llvm.loop !34
>> >> +
>> >> +for.body.preheader:
>> >> +  br label %for.body, !dbg !35
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0,
>> %for.body.preheader ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv,
>> !dbg !35
>> >> +  %0 = load i32, i32* %arrayidx, align 4, !dbg !35, !tbaa !18
>> >> +  %idxprom1 = sext i32 %0 to i64, !dbg !35
>> >> +  %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %idxprom1,
>> !dbg !35
>> >> +  %1 = load i32, i32* %arrayidx2, align 4, !dbg !35, !tbaa !18
>> >> +  %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv,
>> !dbg !35
>> >> +  store i32 %1, i32* %arrayidx4, align 4, !dbg !35, !tbaa !18
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !32
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32, !dbg !32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %Length, !dbg !32
>> >> +  br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg
>> !32, !llvm.loop !34
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void, !dbg !36
>> >> +}
>> >> +
>> >> +!llvm.dbg.cu = !{!0}
>> >> +!llvm.module.flags = !{!9, !10}
>> >> +!llvm.ident = !{!11}
>> >> +
>> >> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer:
>> "clang version 3.5.0", isOptimized: true, runtimeVersion: 6, emissionKind:
>> LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2,
>> imports: !2)
>> >> +!1 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!2 = !{}
>> >> +!4 = distinct !DISubprogram(name: "test", line: 1, isLocal: false,
>> isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized:
>> true, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes:
>> !2)
>> >> +!5 = !DIFile(filename: "source.cpp", directory: ".")
>> >> +!6 = !DISubroutineType(types: !2)
>> >> +!7 = distinct !DISubprogram(name: "test_disabled", line: 10, isLocal:
>> false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped,
>> isOptimized: true, unit: !0, scopeLine: 10, file: !1, scope: !5, type: !6,
>> retainedNodes: !2)
>> >> +!8 = distinct !DISubprogram(name: "test_array_bounds", line: 16,
>> isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 16, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >> +!9 = !{i32 2, !"Dwarf Version", i32 2}
>> >> +!10 = !{i32 2, !"Debug Info Version", i32 3}
>> >> +!11 = !{!"clang version 3.5.0"}
>> >> +!12 = !DILocation(line: 3, column: 8, scope: !13)
>> >> +!13 = distinct !DILexicalBlock(line: 3, column: 3, file: !1, scope:
>> !4)
>> >> +!14 = !{!14, !15, !15}
>> >> +!15 = !{!"llvm.loop.vectorize.enable", i1 true}
>> >> +!16 = !DILocation(line: 4, column: 5, scope: !17)
>> >> +!17 = distinct !DILexicalBlock(line: 3, column: 36, file: !1, scope:
>> !13)
>> >> +!18 = !{!19, !19, i64 0}
>> >> +!19 = !{!"int", !20, i64 0}
>> >> +!20 = !{!"omnipotent char", !21, i64 0}
>> >> +!21 = !{!"Simple C/C++ TBAA"}
>> >> +!22 = !DILocation(line: 5, column: 9, scope: !23)
>> >> +!23 = distinct !DILexicalBlock(line: 5, column: 9, file: !1, scope:
>> !17)
>> >> +!24 = !DILocation(line: 8, column: 1, scope: !4)
>> >> +!25 = !DILocation(line: 12, column: 8, scope: !26)
>> >> +!26 = distinct !DILexicalBlock(line: 12, column: 3, file: !1, scope:
>> !7)
>> >> +!27 = !{!27, !28, !29}
>> >> +!28 = !{!"llvm.loop.interleave.count", i32 1}
>> >> +!29 = !{!"llvm.loop.vectorize.width", i32 1}
>> >> +!30 = !DILocation(line: 13, column: 5, scope: !26)
>> >> +!31 = !DILocation(line: 14, column: 1, scope: !7)
>> >> +!32 = !DILocation(line: 18, column: 8, scope: !33)
>> >> +!33 = distinct !DILexicalBlock(line: 18, column: 3, file: !1, scope:
>> !8)
>> >> +!34 = !{!34, !15}
>> >> +!35 = !DILocation(line: 19, column: 5, scope: !33)
>> >> +!36 = !DILocation(line: 20, column: 1, scope: !8)
>> >> +!37 = distinct !DILexicalBlock(line: 24, column: 3, file: !1, scope:
>> !46)
>> >> +!38 = !DILocation(line: 27, column: 3, scope: !37)
>> >> +!39 = !DILocation(line: 31, column: 3, scope: !37)
>> >> +!40 = !DILocation(line: 28, column: 9, scope: !37)
>> >> +!41 = !DILocation(line: 29, column: 11, scope: !37)
>> >> +!42 = !DILocation(line: 29, column: 7, scope: !37)
>> >> +!43 = !DILocation(line: 27, column: 32, scope: !37)
>> >> +!44 = !DILocation(line: 27, column: 30, scope: !37)
>> >> +!45 = !DILocation(line: 27, column: 21, scope: !37)
>> >> +!46 = distinct !DISubprogram(name: "test_multiple_failures", line:
>> 26, isLocal: false, isDefinition: true, virtualIndex: 6, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, scopeLine: 26, file: !1,
>> scope: !5, type: !6, retainedNodes: !2)
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced.ll (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced.ll Wed Dec
>> 12 09:32:52 2018
>> >> @@ -0,0 +1,29 @@
>> >> +; RUN: opt -loop-unroll -unroll-count=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that the disable_nonforced loop property is honored by
>> >> +; loop unroll.
>> >> +;
>> >> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced(
>> >> +; CHECK: load
>> >> +; CHECK-NOT: load
>> >> +define void @disable_nonforced(i32* nocapture %a) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = load i32, i32* %arrayidx, align 4
>> >> +  %inc = add nsw i32 %0, 1
>> >> +  store i32 %inc, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
>> >> +  %exitcond = icmp eq i64 %indvars.iv.next, 64
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !{!"llvm.loop.disable_nonforced"}}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_count.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_count.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_count.ll
>> (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_count.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,30 @@
>> >> +; RUN: opt -loop-unroll -unroll-count=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check whether the llvm.loop.unroll.count loop property overrides
>> >> +; llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced_count(
>> >> +; CHECK: store
>> >> +; CHECK: store
>> >> +; CHECK-NOT: store
>> >> +define void @disable_nonforced_count(i32* nocapture %a) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = load i32, i32* %arrayidx, align 4
>> >> +  %inc = add nsw i32 %0, 1
>> >> +  store i32 %inc, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
>> >> +  %exitcond = icmp eq i64 %indvars.iv.next, 64
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.unroll.count", i32 2}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_enable.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_enable.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_enable.ll
>> (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_enable.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,30 @@
>> >> +; RUN: opt -loop-unroll -unroll-count=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that the llvm.loop.unroll.enable loop property overrides
>> >> +; llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced_enable(
>> >> +; CHECK: store
>> >> +; CHECK: store
>> >> +; CHECK-NOT: store
>> >> +define void @disable_nonforced_enable(i32* nocapture %a) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = load i32, i32* %arrayidx, align 4
>> >> +  %inc = add nsw i32 %0, 1
>> >> +  store i32 %inc, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
>> >> +  %exitcond = icmp eq i64 %indvars.iv.next, 64
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.unroll.enable"}}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_full.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_full.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_full.ll
>> (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnroll/disable_nonforced_full.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,32 @@
>> >> +; RUN: opt -loop-unroll -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that the llvm.loop.unroll.full loop property overrides
>> >> +; llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced_full(
>> >> +; CHECK: store
>> >> +; CHECK: store
>> >> +; CHECK: store
>> >> +; CHECK: store
>> >> +; CHECK-NOT: store
>> >> +define void @disable_nonforced_full(i32* nocapture %a) {
>> >> +entry:
>> >> +  br label %for.body
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = load i32, i32* %arrayidx, align 4
>> >> +  %inc = add nsw i32 %0, 1
>> >> +  store i32 %inc, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
>> >> +  %exitcond = icmp eq i64 %indvars.iv.next, 4
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.unroll.full"}}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopUnroll/followup.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/followup.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnroll/followup.ll (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnroll/followup.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -0,0 +1,63 @@
>> >> +; RUN: opt < %s -S -loop-unroll -unroll-count=2 | FileCheck %s
>> -check-prefixes=COUNT,COMMON
>> >> +; RUN: opt < %s -S -loop-unroll -unroll-runtime=true
>> -unroll-runtime-epilog=true  | FileCheck %s -check-prefixes=EPILOG,COMMON
>> >> +; RUN: opt < %s -S -loop-unroll -unroll-runtime=true
>> -unroll-runtime-epilog=false | FileCheck %s -check-prefixes=PROLOG,COMMON
>> >> +;
>> >> +; Check that followup-attributes are applied after LoopUnroll.
>> >> +;
>> >> +target datalayout =
>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> >> +
>> >> +define i32 @test(i32* nocapture %a, i32 %n) nounwind uwtable readonly
>> {
>> >> +entry:
>> >> +  %cmp1 = icmp eq i32 %n, 0
>> >> +  br i1 %cmp1, label %for.end, label %for.body
>> >> +
>> >> +for.body:                                         ; preds =
>> %for.body, %entry
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
>> >> +  %sum.02 = phi i32 [ %add, %for.body ], [ 0, %entry ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = load i32, i32* %arrayidx, align 4
>> >> +  %add = add nsw i32 %0, %sum.02
>> >> +  %indvars.iv.next = add i64 %indvars.iv, 1
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %n
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !4
>> >> +
>> >> +for.end:                                          ; preds =
>> %for.body, %entry
>> >> +  %sum.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ]
>> >> +  ret i32 %sum.0.lcssa
>> >> +}
>> >> +
>> >> +!1 = !{!"llvm.loop.unroll.followup_all", !{!"FollowupAll"}}
>> >> +!2 = !{!"llvm.loop.unroll.followup_unrolled", !{!"FollowupUnrolled"}}
>> >> +!3 = !{!"llvm.loop.unroll.followup_remainder",
>> !{!"FollowupRemainder"}}
>> >> +!4 = distinct !{!4, !1, !2, !3}
>> >> +
>> >> +
>> >> +; COMMON-LABEL: @test(
>> >> +
>> >> +
>> >> +; COUNT: br i1 %exitcond.1, label %for.end.loopexit, label %for.body,
>> !llvm.loop ![[LOOP:[0-9]+]]
>> >> +
>> >> +; COUNT: ![[FOLLOWUP_ALL:[0-9]+]] = !{!"FollowupAll"}
>> >> +; COUNT: ![[FOLLOWUP_UNROLLED:[0-9]+]] = !{!"FollowupUnrolled"}
>> >> +; COUNT: ![[LOOP]] = distinct !{![[LOOP]], ![[FOLLOWUP_ALL]],
>> ![[FOLLOWUP_UNROLLED]]}
>> >> +
>> >> +
>> >> +; EPILOG: br i1 %niter.ncmp.7, label
>> %for.end.loopexit.unr-lcssa.loopexit, label %for.body, !llvm.loop
>> ![[LOOP_0:[0-9]+]]
>> >> +; EPILOG: br i1 %epil.iter.cmp, label %for.body.epil, label
>> %for.end.loopexit.epilog-lcssa, !llvm.loop ![[LOOP_2:[0-9]+]]
>> >> +
>> >> +; EPILOG: ![[LOOP_0]] = distinct !{![[LOOP_0]],
>> ![[FOLLOWUP_ALL:[0-9]+]], ![[FOLLOWUP_UNROLLED:[0-9]+]]}
>> >> +; EPILOG: ![[FOLLOWUP_ALL]] = !{!"FollowupAll"}
>> >> +; EPILOG: ![[FOLLOWUP_UNROLLED]] = !{!"FollowupUnrolled"}
>> >> +; EPILOG: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[FOLLOWUP_ALL]],
>> ![[FOLLOWUP_REMAINDER:[0-9]+]]}
>> >> +; EPILOG: ![[FOLLOWUP_REMAINDER]] = !{!"FollowupRemainder"}
>> >> +
>> >> +
>> >> +; PROLOG:  br i1 %prol.iter.cmp, label %for.body.prol, label
>> %for.body.prol.loopexit.unr-lcssa, !llvm.loop ![[LOOP_0:[0-9]+]]
>> >> +; PROLOG:  br i1 %exitcond.7, label %for.end.loopexit.unr-lcssa,
>> label %for.body, !llvm.loop ![[LOOP_2:[0-9]+]]
>> >> +
>> >> +; PROLOG: ![[LOOP_0]] = distinct !{![[LOOP_0]],
>> ![[FOLLOWUP_ALL:[0-9]+]], ![[FOLLOWUP_REMAINDER:[0-9]+]]}
>> >> +; PROLOG: ![[FOLLOWUP_ALL]] = !{!"FollowupAll"}
>> >> +; PROLOG: ![[FOLLOWUP_REMAINDER]] = !{!"FollowupRemainder"}
>> >> +; PROLOG: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[FOLLOWUP_ALL]],
>> ![[FOLLOWUP_UNROLLED:[0-9]+]]}
>> >> +; PROLOG: ![[FOLLOWUP_UNROLLED]] = !{!"FollowupUnrolled"}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced.ll
>> (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,50 @@
>> >> +; RUN: opt -loop-unroll-and-jam -allow-unroll-and-jam
>> -unroll-and-jam-count=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that the disable_nonforced loop property is honored by
>> >> +; loop unroll-and-jam.
>> >> +;
>> >> +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
>> >> +
>> >> +; CHECK-LABEL: disable_nonforced
>> >> +; CHECK: load
>> >> +; CHECK-NOT: load
>> >> +define void @disable_nonforced(i32 %I, i32 %J, i32* noalias nocapture
>> %A, i32* noalias nocapture readonly %B) {
>> >> +entry:
>> >> +  %cmp = icmp ne i32 %J, 0
>> >> +  %cmp122 = icmp ne i32 %I, 0
>> >> +  %or.cond = and i1 %cmp, %cmp122
>> >> +  br i1 %or.cond, label %for.outer.preheader, label %for.end
>> >> +
>> >> +for.outer.preheader:
>> >> +  br label %for.outer
>> >> +
>> >> +for.outer:
>> >> +  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0,
>> %for.outer.preheader ]
>> >> +  br label %for.inner
>> >> +
>> >> +for.inner:
>> >> +  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
>> >> +  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
>> >> +  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
>> >> +  %0 = load i32, i32* %arrayidx.us, align 4
>> >> +  %add.us = add i32 %0, %sum1.us
>> >> +  %inc.us = add nuw i32 %j.us, 1
>> >> +  %exitcond = icmp eq i32 %inc.us, %J
>> >> +  br i1 %exitcond, label %for.latch, label %for.inner
>> >> +
>> >> +for.latch:
>> >> +  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
>> >> +  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
>> >> +  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
>> >> +  %add8.us = add nuw i32 %i.us, 1
>> >> +  %exitcond25 = icmp eq i32 %add8.us, %I
>> >> +  br i1 %exitcond25, label %for.end.loopexit, label %for.outer,
>> !llvm.loop !0
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_count.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_count.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_count.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_count.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,52 @@
>> >> +; RUN: opt -loop-unroll-and-jam -allow-unroll-and-jam -S < %s |
>> FileCheck %s
>> >> +;
>> >> +; Verify that the llvm.loop.unroll_and_jam.count loop property
>> overrides
>> >> +; llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced_enable(
>> >> +; CHECK: load
>> >> +; CHECK: load
>> >> +; CHECK-NOT: load
>> >> +; CHECK: br i1
>> >> +define void @disable_nonforced_enable(i32 %I, i32 %J, i32* noalias
>> nocapture %A, i32* noalias nocapture readonly %B) {
>> >> +entry:
>> >> +  %cmp = icmp ne i32 %J, 0
>> >> +  %cmp122 = icmp ne i32 %I, 0
>> >> +  %or.cond = and i1 %cmp, %cmp122
>> >> +  br i1 %or.cond, label %for.outer.preheader, label %for.end
>> >> +
>> >> +for.outer.preheader:
>> >> +  br label %for.outer
>> >> +
>> >> +for.outer:
>> >> +  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0,
>> %for.outer.preheader ]
>> >> +  br label %for.inner
>> >> +
>> >> +for.inner:
>> >> +  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
>> >> +  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
>> >> +  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
>> >> +  %0 = load i32, i32* %arrayidx.us, align 4
>> >> +  %add.us = add i32 %0, %sum1.us
>> >> +  %inc.us = add nuw i32 %j.us, 1
>> >> +  %exitcond = icmp eq i32 %inc.us, %J
>> >> +  br i1 %exitcond, label %for.latch, label %for.inner
>> >> +
>> >> +for.latch:
>> >> +  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
>> >> +  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
>> >> +  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
>> >> +  %add8.us = add nuw i32 %i.us, 1
>> >> +  %exitcond25 = icmp eq i32 %add8.us, %I
>> >> +  br i1 %exitcond25, label %for.end.loopexit, label %for.outer,
>> !llvm.loop !0
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.unroll_and_jam.count", i32 2}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_enable.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_enable.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_enable.ll
>> (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopUnrollAndJam/disable_nonforced_enable.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,52 @@
>> >> +; RUN: opt -loop-unroll-and-jam -allow-unroll-and-jam
>> -unroll-and-jam-count=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Verify that the llvm.loop.unroll_and_jam.enable loop property
>> >> +; overrides llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
>> >> +
>> >> +; CHECK-LABEL: disable_nonforced_enable
>> >> +; CHECK: load
>> >> +; CHECK: load
>> >> +; CHECK-NOT: load
>> >> +; CHECK: br i1
>> >> +define void @disable_nonforced_enable(i32 %I, i32 %J, i32* noalias
>> nocapture %A, i32* noalias nocapture readonly %B) {
>> >> +entry:
>> >> +  %cmp = icmp ne i32 %J, 0
>> >> +  %cmp122 = icmp ne i32 %I, 0
>> >> +  %or.cond = and i1 %cmp, %cmp122
>> >> +  br i1 %or.cond, label %for.outer.preheader, label %for.end
>> >> +
>> >> +for.outer.preheader:
>> >> +  br label %for.outer
>> >> +
>> >> +for.outer:
>> >> +  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0,
>> %for.outer.preheader ]
>> >> +  br label %for.inner
>> >> +
>> >> +for.inner:
>> >> +  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
>> >> +  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
>> >> +  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
>> >> +  %0 = load i32, i32* %arrayidx.us, align 4
>> >> +  %add.us = add i32 %0, %sum1.us
>> >> +  %inc.us = add nuw i32 %j.us, 1
>> >> +  %exitcond = icmp eq i32 %inc.us, %J
>> >> +  br i1 %exitcond, label %for.latch, label %for.inner
>> >> +
>> >> +for.latch:
>> >> +  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
>> >> +  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
>> >> +  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
>> >> +  %add8.us = add nuw i32 %i.us, 1
>> >> +  %exitcond25 = icmp eq i32 %add8.us, %I
>> >> +  br i1 %exitcond25, label %for.end.loopexit, label %for.outer,
>> !llvm.loop !0
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.unroll_and_jam.enable"}}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopUnrollAndJam/followup.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnrollAndJam/followup.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnrollAndJam/followup.ll (added)
>> >> +++ llvm/trunk/test/Transforms/LoopUnrollAndJam/followup.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -0,0 +1,66 @@
>> >> +; RUN: opt -basicaa -tbaa -loop-unroll-and-jam -allow-unroll-and-jam
>> -unroll-and-jam-count=4 -unroll-remainder < %s -S | FileCheck %s
>> >> +;
>> >> +; Check that followup attributes are set in the new loops.
>> >> +;
>> >> +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
>> >> +
>> >> +define void @followup(i32 %I, i32 %J, i32* noalias nocapture %A, i32*
>> noalias nocapture readonly %B) {
>> >> +entry:
>> >> +  %cmp = icmp ne i32 %J, 0
>> >> +  %cmp122 = icmp ne i32 %I, 0
>> >> +  %or.cond = and i1 %cmp, %cmp122
>> >> +  br i1 %or.cond, label %for.outer.preheader, label %for.end
>> >> +
>> >> +for.outer.preheader:
>> >> +  br label %for.outer
>> >> +
>> >> +for.outer:
>> >> +  %i.us = phi i32 [ %add8.us, %for.latch ], [ 0,
>> %for.outer.preheader ]
>> >> +  br label %for.inner
>> >> +
>> >> +for.inner:
>> >> +  %j.us = phi i32 [ 0, %for.outer ], [ %inc.us, %for.inner ]
>> >> +  %sum1.us = phi i32 [ 0, %for.outer ], [ %add.us, %for.inner ]
>> >> +  %arrayidx.us = getelementptr inbounds i32, i32* %B, i32 %j.us
>> >> +  %0 = load i32, i32* %arrayidx.us, align 4
>> >> +  %add.us = add i32 %0, %sum1.us
>> >> +  %inc.us = add nuw i32 %j.us, 1
>> >> +  %exitcond = icmp eq i32 %inc.us, %J
>> >> +  br i1 %exitcond, label %for.latch, label %for.inner
>> >> +
>> >> +for.latch:
>> >> +  %add.us.lcssa = phi i32 [ %add.us, %for.inner ]
>> >> +  %arrayidx6.us = getelementptr inbounds i32, i32* %A, i32 %i.us
>> >> +  store i32 %add.us.lcssa, i32* %arrayidx6.us, align 4
>> >> +  %add8.us = add nuw i32 %i.us, 1
>> >> +  %exitcond25 = icmp eq i32 %add8.us, %I
>> >> +  br i1 %exitcond25, label %for.end.loopexit, label %for.outer,
>> !llvm.loop !0
>> >> +
>> >> +for.end.loopexit:
>> >> +  br label %for.end
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !1, !2, !3, !4, !6}
>> >> +!1 = !{!"llvm.loop.unroll_and_jam.enable"}
>> >> +!2 = !{!"llvm.loop.unroll_and_jam.followup_outer",
>> !{!"FollowupOuter"}}
>> >> +!3 = !{!"llvm.loop.unroll_and_jam.followup_inner",
>> !{!"FollowupInner"}}
>> >> +!4 = !{!"llvm.loop.unroll_and_jam.followup_all", !{!"FollowupAll"}}
>> >> +!6 = !{!"llvm.loop.unroll_and_jam.followup_remainder_inner",
>> !{!"FollowupRemainderInner"}}
>> >> +
>> >> +
>> >> +; CHECK: br i1 %exitcond.3, label %for.latch, label %for.inner,
>> !llvm.loop ![[LOOP_INNER:[0-9]+]]
>> >> +; CHECK: br i1 %niter.ncmp.3, label
>> %for.end.loopexit.unr-lcssa.loopexit, label %for.outer, !llvm.loop
>> ![[LOOP_OUTER:[0-9]+]]
>> >> +; CHECK: br i1 %exitcond.epil, label %for.latch.epil, label
>> %for.inner.epil, !llvm.loop ![[LOOP_REMAINDER_INNER:[0-9]+]]
>> >> +; CHECK: br i1 %exitcond.epil.1, label %for.latch.epil.1, label
>> %for.inner.epil.1, !llvm.loop ![[LOOP_REMAINDER_INNER]]
>> >> +; CHECK: br i1 %exitcond.epil.2, label %for.latch.epil.2, label
>> %for.inner.epil.2, !llvm.loop ![[LOOP_REMAINDER_INNER]]
>> >> +
>> >> +; CHECK: ![[LOOP_INNER]] = distinct !{![[LOOP_INNER]],
>> ![[FOLLOWUP_ALL:[0-9]+]], ![[FOLLOWUP_INNER:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_ALL]] = !{!"FollowupAll"}
>> >> +; CHECK: ![[FOLLOWUP_INNER]] = !{!"FollowupInner"}
>> >> +; CHECK: ![[LOOP_OUTER]] = distinct !{![[LOOP_OUTER]],
>> ![[FOLLOWUP_ALL]], ![[FOLLOWUP_OUTER:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_OUTER]] = !{!"FollowupOuter"}
>> >> +; CHECK: ![[LOOP_REMAINDER_INNER]] = distinct
>> !{![[LOOP_REMAINDER_INNER]], ![[FOLLOWUP_ALL]],
>> ![[FOLLOWUP_REMAINDER_INNER:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_REMAINDER_INNER]] = !{!"FollowupRemainderInner"}
>> >>
>> >> Modified: llvm/trunk/test/Transforms/LoopUnrollAndJam/pragma.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnrollAndJam/pragma.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopUnrollAndJam/pragma.ll (original)
>> >> +++ llvm/trunk/test/Transforms/LoopUnrollAndJam/pragma.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -316,4 +316,4 @@ for.end:
>> >>  !8 = distinct !{!"llvm.loop.unroll.disable"}
>> >>  !9 = distinct !{!9, !10}
>> >>  !10 = distinct !{!"llvm.loop.unroll.enable"}
>> >> -!11 = distinct !{!11, !8, !6}
>> >> \ No newline at end of file
>> >> +!11 = distinct !{!11, !8, !6}
>> >>
>> >> Modified:
>> llvm/trunk/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll
>> (original)
>> >> +++
>> llvm/trunk/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll
>> Wed Dec 12 09:32:52 2018
>> >> @@ -1,9 +1,9 @@
>> >> -; RUN: opt < %s -loop-vectorize -S
>> -pass-remarks-missed='loop-vectorize'
>> -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s
>> >> -; RUN: opt < %s -loop-vectorize -o /dev/null
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: opt < %s -loop-vectorize -transform-warning -S
>> -pass-remarks-missed='loop-vectorize'
>> -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -loop-vectorize -transform-warning -o /dev/null
>> -pass-remarks-output=%t.yaml
>> >>  ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >>
>> >> -; RUN: opt < %s -passes=loop-vectorize -S
>> -pass-remarks-missed='loop-vectorize'
>> -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s
>> >> -; RUN: opt < %s -passes=loop-vectorize -o /dev/null
>> -pass-remarks-output=%t.yaml
>> >> +; RUN: opt < %s -passes=loop-vectorize,transform-warning -S
>> -pass-remarks-missed='loop-vectorize'
>> -pass-remarks-analysis='loop-vectorize'  2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -passes=loop-vectorize,transform-warning -o /dev/null
>> -pass-remarks-output=%t.yaml
>> >>  ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
>> >>
>> >>  ; C/C++ code for tests
>> >> @@ -33,7 +33,7 @@
>> >>  ; }
>> >>  ; CHECK: remark: source.cpp:19:5: loop not vectorized: cannot
>> identify array bounds
>> >>  ; CHECK: remark: source.cpp:19:5: loop not vectorized
>> >> -; CHECK: warning: source.cpp:19:5: loop not vectorized: failed
>> explicitly specified loop vectorization
>> >> +; CHECK: warning: source.cpp:19:5: loop not vectorized: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering
>> >>
>> >>  ; int foo();
>> >>  ; void test_multiple_failures(int *A) {
>> >> @@ -94,13 +94,12 @@
>> >>  ; YAML-NEXT:   - String:          ')'
>> >>  ; YAML-NEXT: ...
>> >>  ; YAML-NEXT: --- !Failure
>> >> -; YAML-NEXT: Pass:            loop-vectorize
>> >> +; YAML-NEXT: Pass:            transform-warning
>> >>  ; YAML-NEXT: Name:            FailedRequestedVectorization
>> >>  ; YAML-NEXT: DebugLoc:        { File: source.cpp, Line: 19, Column: 5
>> }
>> >>  ; YAML-NEXT: Function:        _Z17test_array_boundsPiS_i
>> >>  ; YAML-NEXT: Args:
>> >> -; YAML-NEXT:   - String:          'loop not vectorized: '
>> >> -; YAML-NEXT:   - String:          failed explicitly specified loop
>> vectorization
>> >> +; YAML-NEXT:   - String:          'loop not vectorized: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering'
>> >>  ; YAML-NEXT: ...
>> >>  ; YAML-NEXT: --- !Analysis
>> >>  ; YAML-NEXT: Pass:            loop-vectorize
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced.ll
>> (added)
>> >> +++ llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,29 @@
>> >> +; RUN: opt -loop-vectorize -force-vector-interleave=1
>> -force-vector-width=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that the disable_nonforced loop property is honored by the
>> >> +; loop vectorizer.
>> >> +;
>> >> +target datalayout =
>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced(
>> >> +; CHECK-NOT: x i32>
>> >> +define void @disable_nonforced(i32* nocapture %a, i32 %n) {
>> >> +entry:
>> >> +  %cmp4 = icmp sgt i32 %n, 0
>> >> +  br i1 %cmp4, label %for.body, label %for.end
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = trunc i64 %indvars.iv to i32
>> >> +  store i32 %0, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add i64 %indvars.iv, 1
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %n
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !{!"llvm.loop.disable_nonforced"}}
>> >>
>> >> Added:
>> llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced_enable.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced_enable.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> ---
>> llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced_enable.ll (added)
>> >> +++
>> llvm/trunk/test/Transforms/LoopVectorize/disable_nonforced_enable.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -0,0 +1,29 @@
>> >> +; RUN: opt -loop-vectorize -force-vector-interleave=1
>> -force-vector-width=2 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check whether the llvm.loop.vectorize.enable loop property overrides
>> >> +; llvm.loop.disable_nonforced.
>> >> +;
>> >> +target datalayout =
>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> >> +
>> >> +; CHECK-LABEL: @disable_nonforced_enable(
>> >> +; CHECK: store <2 x i32>
>> >> +define void @disable_nonforced_enable(i32* nocapture %a, i32 %n) {
>> >> +entry:
>> >> +  %cmp4 = icmp sgt i32 %n, 0
>> >> +  br i1 %cmp4, label %for.body, label %for.end
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = trunc i64 %indvars.iv to i32
>> >> +  store i32 %0, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add i64 %indvars.iv, 1
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %n
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = !{!0, !{!"llvm.loop.disable_nonforced"},
>> !{!"llvm.loop.vectorize.enable", i32 1}}
>> >>
>> >> Added: llvm/trunk/test/Transforms/LoopVectorize/followup.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/followup.ll?rev=348944&view=auto
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopVectorize/followup.ll (added)
>> >> +++ llvm/trunk/test/Transforms/LoopVectorize/followup.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -0,0 +1,43 @@
>> >> +; RUN: opt -loop-vectorize -force-vector-width=4
>> -force-vector-interleave=1 -S < %s | FileCheck %s
>> >> +;
>> >> +; Check that the followup loop attributes are applied.
>> >> +;
>> >> +target datalayout =
>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> >> +
>> >> +define void @followup(i32* nocapture %a, i32 %n) {
>> >> +entry:
>> >> +  %cmp4 = icmp sgt i32 %n, 0
>> >> +  br i1 %cmp4, label %for.body, label %for.end
>> >> +
>> >> +for.body:
>> >> +  %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
>> >> +  %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>> >> +  %0 = trunc i64 %indvars.iv to i32
>> >> +  store i32 %0, i32* %arrayidx, align 4
>> >> +  %indvars.iv.next = add i64 %indvars.iv, 1
>> >> +  %lftr.wideiv = trunc i64 %indvars.iv.next to i32
>> >> +  %exitcond = icmp eq i32 %lftr.wideiv, %n
>> >> +  br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
>> >> +
>> >> +for.end:
>> >> +  ret void
>> >> +}
>> >> +
>> >> +!0 = distinct !{!0, !3, !4, !5}
>> >> +!3 = !{!"llvm.loop.vectorize.followup_vectorized",
>> !{!"FollowupVectorized"}}
>> >> +!4 = !{!"llvm.loop.vectorize.followup_epilogue",
>> !{!"FollowupEpilogue"}}
>> >> +!5 = !{!"llvm.loop.vectorize.followup_all", !{!"FollowupAll"}}
>> >> +
>> >> +
>> >> +; CHECK-LABEL @followup(
>> >> +
>> >> +; CHECK-LABEL: vector.body:
>> >> +; CHECK: br i1 %13, label %middle.block, label %vector.body,
>> !llvm.loop ![[LOOP_VECTOR:[0-9]+]]
>> >> +; CHECK-LABEL: for.body:
>> >> +; CHECK: br i1 %exitcond, label %for.end.loopexit, label %for.body,
>> !llvm.loop ![[LOOP_EPILOGUE:[0-9]+]]
>> >> +
>> >> +; CHECK: ![[LOOP_VECTOR]] = distinct !{![[LOOP_VECTOR]],
>> ![[FOLLOWUP_ALL:[0-9]+]], ![[FOLLOWUP_VECTORIZED:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_ALL]] = !{!"FollowupAll"}
>> >> +; CHECK: ![[FOLLOWUP_VECTORIZED:[0-9]+]] = !{!"FollowupVectorized"}
>> >> +; CHECK: ![[LOOP_EPILOGUE]] = distinct !{![[LOOP_EPILOGUE]],
>> ![[FOLLOWUP_ALL]], ![[FOLLOWUP_EPILOGUE:[0-9]+]]}
>> >> +; CHECK: ![[FOLLOWUP_EPILOGUE]] = !{!"FollowupEpilogue"}
>> >>
>> >> Modified: llvm/trunk/test/Transforms/LoopVectorize/no_array_bounds.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/no_array_bounds.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopVectorize/no_array_bounds.ll
>> (original)
>> >> +++ llvm/trunk/test/Transforms/LoopVectorize/no_array_bounds.ll Wed
>> Dec 12 09:32:52 2018
>> >> @@ -1,8 +1,8 @@
>> >> -; RUN: opt < %s -loop-vectorize -S 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -loop-vectorize -transform-warning -S 2>&1 |
>> FileCheck %s
>> >>
>> >>  ; Verify warning is generated when vectorization/ interleaving is
>> explicitly specified and fails to occur.
>> >> -; CHECK: warning: no_array_bounds.cpp:5:5: loop not vectorized:
>> failed explicitly specified loop vectorization
>> >> -; CHECK: warning: no_array_bounds.cpp:10:5: loop not interleaved:
>> failed explicitly specified loop interleaving
>> >> +; CHECK: warning: no_array_bounds.cpp:5:5: loop not vectorized: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering
>> >> +; CHECK: warning: no_array_bounds.cpp:10:5: loop not interleaved: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering
>> >>
>> >>  ;  #pragma clang loop vectorize(enable)
>> >>  ;  for (int i = 0; i < number; i++) {
>> >>
>> >> Modified: llvm/trunk/test/Transforms/LoopVectorize/no_switch.ll
>> >> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopVectorize/no_switch.ll?rev=348944&r1=348943&r2=348944&view=diff
>> >>
>> ==============================================================================
>> >> --- llvm/trunk/test/Transforms/LoopVectorize/no_switch.ll (original)
>> >> +++ llvm/trunk/test/Transforms/LoopVectorize/no_switch.ll Wed Dec 12
>> 09:32:52 2018
>> >> @@ -1,16 +1,16 @@
>> >> -; RUN: opt < %s -loop-vectorize -force-vector-width=4 -S 2>&1 |
>> FileCheck %s
>> >> -; RUN: opt < %s -loop-vectorize -force-vector-width=1 -S 2>&1 |
>> FileCheck %s -check-prefix=NOANALYSIS
>> >> -; RUN: opt < %s -loop-vectorize -force-vector-width=4
>> -pass-remarks-missed='loop-vectorize' -S 2>&1 | FileCheck %s
>> -check-prefix=MOREINFO
>> >> +; RUN: opt < %s -loop-vectorize -force-vector-width=4
>> -transform-warning -S 2>&1 | FileCheck %s
>> >> +; RUN: opt < %s -loop-vectorize -force-vector-width=1
>> -transform-warning -S 2>&1 | FileCheck %s -check-prefix=NOANALYSIS
>> >> +; RUN: opt < %s -loop-vectorize -force-vector-width=4
>> -transform-warning -pass-remarks-missed='loop-vectorize' -S 2>&1 |
>> FileCheck %s -check-prefix=MOREINFO
>> >>
>> >>  ; CHECK: remark: source.cpp:4:5: loop not vectorized: loop contains a
>> switch statement
>> >> -; CHECK: warning: source.cpp:4:5: loop not vectorized: failed
>> explicitly specified loop vectorization
>> >> +; CHECK: warning: source.cpp:4:5: loop not vectorized: the optimizer
>> was unable to perform the requested transformation; the transformation
>> might be disabled or specified as part of an unsupported transformation
>> ordering
>> >>
>> >>  ; NOANALYSIS-NOT: remark: {{.*}}
>> >> -; NOANALYSIS: warning: source.cpp:4:5: loop not interleaved: failed
>> explicitly specified loop interleaving
>> >> +; NOANALYSIS: warning: source.cpp:4:5: loop not vectorized: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering
>> >>
>> >>  ; MOREINFO: remark: source.cpp:4:5: loop not vectorized: loop
>> contains a switch statement
>> >>  ; MOREINFO: remark: source.cpp:4:5: loop not vectorized (Force=true,
>> Vector Width=4)
>> >> -; MOREINFO: warning: source.cpp:4:5: loop not vectorized: failed
>> explicitly specified loop vectorization
>> >> +; MOREINFO: warning: source.cpp:4:5: loop not vectorized: the
>> optimizer was unable to perform the requested transformation; the
>> transformation might be disabled or specified as part of an unsupported
>> transformation ordering
>> >>
>> >>  ; CHECK: _Z11test_switchPii
>> >>  ; CHECK-NOT: x i32>
>> >>
>> >>
>> >> _______________________________________________
>> >> llvm-commits mailing list
>> >> llvm-commits at lists.llvm.org
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181213/4854c818/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4849 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181213/4854c818/attachment-0001.bin>


More information about the llvm-commits mailing list