[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