Commit Graph

43 Commits

Author SHA1 Message Date
Chandler Carruth 16879be0da Update Polly to reflect a change to a clang-format patch. I'm not sure
this is a great test file name based on this update, but I'll let Polly
folks sort out how they want this to work long-term, I just want tho
bots back.

llvm-svn: 306767
2017-06-29 23:58:03 +00:00
Philip Pfaffe 483340bb83 [Polly][NewPM] Reenable ScopPassManager unittest
llvm-svn: 303629
2017-05-23 11:28:50 +00:00
Tobias Grosser e890d5ba1b Drop nonexisting ScopPassManager directory
llvm-svn: 303066
2017-05-15 14:12:30 +00:00
Philip Pfaffe 762ec5a3eb [Polly][NewPM] Add missing Unittests
llvm-svn: 303064
2017-05-15 13:52:10 +00:00
Philip Pfaffe 35bdcaf9e9 [Polly][NewPM][WIP] Add a ScopPassManager
This patch adds both a ScopAnalysisManager and a ScopPassManager.

The ScopAnalysisManager is itself a Function-Analysis, and manages
analyses on Scops. The ScopPassManager takes care of building Scop pass
pipelines.

This patch is marked WIP because I've left two FIXMEs which I need to
think about some more. Both of these deal with invalidation:

Deferred invalidation is currently not implemented. Deferred
invalidation deals with analyses which cache references to other
analysis results. If these results are invalidated, invalidation needs
to be propagated into the caching analyses.
The ScopPassManager as implemented assumes that ScopPasses do not affect
other Scops in any way. There has been some discussion about this on
other patch threads, however it makes sense to reiterate this for this
specific patch.
I'm uploading this patch even though it's incomplete to encourage
discussion and give you an impression of how this is going to work.

Differential Revision: https://reviews.llvm.org/D33192

llvm-svn: 303062
2017-05-15 13:43:01 +00:00
Michael Kruse 792a6fcc57 [CMake] Use object library to build the two flavours of Polly.
Polly comes in two library flavors: One loadable module to use the
LLVM framework -load mechanism, and another one that host applications
can link to. These have very different requirements for Polly's
own dependencies.

The loadable module assumes that all its LLVM dependencies are already
available in the address space of the host application, and is not allowed
to bring in its own copy of any LLVM library (including the NVPTX
backend in case of Polly-ACC).

The non-module library is intended to be linked to using
target_link_libraries. CMake would then resolve all of its dependencies,
including NVPTX and ensure that only a single instance of each library
will be used.

Differential Revision: https://reviews.llvm.org/D32442

llvm-svn: 301558
2017-04-27 16:13:03 +00:00
Michael Kruse e6d2bebb25 [unittests/DeLICM] Add test for Written vs Written.
The interpretation of multiple known ValInsts for the same element and
timepoint is that these are alterntivate names for the same values,
for instance a PHINode and the incoming value when knowning it was
the last executed block. That means that known values do not conflict
if there at least (but necessarily all) one common ValInst.

This prinviple also applies to Written values. Add a test for this
principle.

llvm-svn: 301481
2017-04-26 21:52:55 +00:00
Michael Kruse 8080011ca1 [unittests/DeLICM] Add test for Occipied vs Occupied.
The interpretation of multiple known ValInsts for the same element and
timepoint is that these are alterntivate names for the same values,
for instance a PHINode and the incoming value when knowning it was
the last executed block. That means that known values do not conflict
if there at least (but necessarily all) one common ValInst.

Add a case to test this principle.

llvm-svn: 301480
2017-04-26 21:52:51 +00:00
Michael Kruse 3e519b949b [DeLICM] Use Known information when comparing Occupied and Written.
Do not conflict if a write writes the same value as already known.

This change only affects unit tests, but no functional changes are
expected on LLVM-IR, as no Known information is yet extracted and
consequently this functionality is only triggered through unit tests.

Differential Revision: https://reviews.llvm.org/D32026

llvm-svn: 301460
2017-04-26 20:35:07 +00:00
Michael Kruse cd2be66bf0 [DeLICM] Use Known information when comparing Existing.Occupied and Proposed.Occupied.
Do not conflict if the value of Existing and Proposed are the same.

This change only affects unit tests, but no functional changes are
expected on LLVM-IR, as no Known information is yet extracted and
consequently this functionality is only triggered through unit tests.

Differential Revision: https://reviews.llvm.org/D32025

llvm-svn: 301301
2017-04-25 10:57:32 +00:00
Michael Kruse a8b0be819a [unittests] Derive Occupied from Unused when given.
When both, OccupiedAndKnown and Unused are given, use the former only
for the Known values. The relation Unused \union Occupied must always
hold.

This allows us to specify Known independently of Occupied. It is needed
for an artificial test case in https://reviews.llvm.org/D32025.

llvm-svn: 301284
2017-04-25 00:30:42 +00:00
Michael Kruse b745b740f9 [unittests] Add postcondition to completeLifetime.
llvm-svn: 301283
2017-04-25 00:30:32 +00:00
Michael Kruse 9c19d1f3aa [CMake] Fix unittests in out-of-LLVM-tree builds.
Unittests are linked against a subset of LLVM libraries and its
transitive dependencies resolved by CMake. The information about indirect
library dependency is not available when building separately from
LLVM, which result in missing symbol errors while linking.

Resolve this issue by querying llvm-config about the available
LLVM libraries and link against all of them, since dependence
information is still not available.

llvm-svn: 301095
2017-04-22 23:02:46 +00:00
Michael Kruse ab6b47d2e7 [CMake] Link unittests only against libLLVM.so, if available.
We can only link against libLLVM.so or the individual libLLVM*.so
components, but not both of them. Doing so results in these components
exist twice in the programs address space, since it is already contained
in libLLVM.so. The observable effect of this is that command line
switches are registered multiple times (once for each instance),
which is an error.

This fixes llvm.org/PR32735.

Reported-by: Singapuram Sanjay Srivallabh <singapuram.sanjay@gmail.com>
llvm-svn: 301020
2017-04-21 19:03:51 +00:00
Michael Kruse 8431e996d3 [DeLICM] Use Known information when comparing Existing.Written and Proposed.Written.
This change only affects unit tests, but no functional changes are
expected on LLVM-IR, as no Known information is yet extracted and
consequently this functionality is only triggered through unit tests.

Differential Revision: https://reviews.llvm.org/D32027

llvm-svn: 300874
2017-04-20 19:16:39 +00:00
Tobias Grosser 75aa1a9a49 Use isl C++ foreach implementation
This commit switches Polly over to the isl::obj::foreach_* implementation, which
is part of the new isl bindings and follows the foreach pattern established in
Polly by Michael Kruse.

The original isl C function:

  isl_stat isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
      isl_stat (*fn)(__isl_take isl_set *set, void *user), void *user);

which required the user to define a static callback function to which all
interesting parameters are passed via a 'void *' user-pointer, is on the
C++ side available as a function that takes a std::function<>, which can
carry any additional arguments without the need for a user pointer:

  stat UnionSet::foreach_set(const std::function<stat(set)> &fn) const;

The following code illustrates the use of the new C++ interface:

  auto Lambda = [=, &Result](isl::set Set) -> isl::stat {
    auto Shifted = shiftDimension(Set, Pos, Amount);
    Result = Result.add(Shifted);
    return isl::stat::ok;
  }

  UnionSet.foreach_set(Lambda);

Polly had some specialized foreach functions which did not require the lambdas
to return a status flag. We remove these functions in this commit to move Polly
completely over to the new isl interface. We may in the future discuss if
functors without return values can be supported easily.

Another extension proposed by Michael Kruse is the use of C++ iterators to allow
the use of normal for loops to iterate over these sets. Such an extension would
allow us to further simplify the code.

Reviewed-by: Michael Kruse <llvm@meinersbur.de>

Differential Revision: https://reviews.llvm.org/D30620

llvm-svn: 300323
2017-04-14 13:39:40 +00:00
Michael Kruse a8e885d87c [DeLICM] Introduce unittesting infrastructure for Known and Written. NFC.
llvm-svn: 300212
2017-04-13 16:32:46 +00:00
Michael Kruse 72f3922534 [DeLICM] Export Known and Written to DeLICMTests. NFC.
This will allow unittesting of new functionality based on
Known and Written.

llvm-svn: 300211
2017-04-13 16:32:39 +00:00
Michael Kruse 5e6456979b [DeLICM] Rename Knowledge to KnowledgeStr. NFC.
Some debuggers get confused by different class of the same name
defined independently in different translation units.

llvm-svn: 300207
2017-04-13 16:32:16 +00:00
Michael Kruse 174f483990 [Support] Add functions to ISLTools.
Add shiftDim and convertZoneToTimepoints overloads for isl maps.

Add distributeDomain, liftDomains and applyDomainRange functions.

These are going to be used in https://reviews.llvm.org/D31247
(Add known array contents to Knowledge)

llvm-svn: 298543
2017-03-22 19:31:06 +00:00
Michael Kruse 0d10696693 [DeLICM] Refector out parseSetOrNull. NFC.
Note that the isl::union_set(isl_ctx,std::string) constructor will
auto-convert the char* to an std::string. Converting a nullptr to
std::string is undefined in C++11 (sect. 21.4.2.9).

llvm-svn: 298259
2017-03-20 15:37:32 +00:00
Michael Kruse d75d56e9bf [DeLICM] Add forgotten isl_space_set_tuple_id in unittests.
Otherwise the isl_id NewId which ensures uniqueness of the
created space is unused. None of the tests currently uses an
nameless tuple, so there is not change in what is tested.

llvm-svn: 298258
2017-03-20 15:24:45 +00:00
Tobias Grosser 9cc7e3561d [unittest] Do not convert large unsigned long to isl::val
Currently the isl::val constructor only takes a signed long as parameter, which
on Windows is only 32 bit large and can consequently not be used to obtain the
same result when loading from the expression '(1ull << 32) - 1)' that we get
when loading this value via isl_val_int_from_ui or when loading the value
on Linux systems with 64 bit long data types. We avoid this issue by performing
the shift and subtractiong within the isl::val.

It would be nice to teach the isl++ bindings to construct isl::val from other
integer types, but the current interface is not sufficient to do so. If
constructors from both signed long and unsigned long are exposed, then integer
literals that are of type 'int' and which must be converted to 'long' to match
the constructor have two ambigious constructors to choose from, which result
in a compiler error. The right solution is likely to additionally expose
constructors from signed and unsigned int, but these are not yet available in
the isl C interface and adding those adhoc to our bindings is something I would
like to avoid for now. We should address this issue with a proper discussion
on the isl side.

llvm-svn: 297522
2017-03-10 22:25:39 +00:00
Tobias Grosser 3cc57fa1e7 [unittest] Translate isl tests to C++ bindings
For this translation we introduce two functions, valFromAPInt and APIntFromVal,
to convert between isl::val and APInt. For now these are just proxies, but in
the future they will replace the current isl_val* based conversion functions.

The isl unit test cases benefit most from the new isl::boolean (from Michael
Kruse), which can be explicitly casted to bool and which -- as part of this cast
-- emits a check that no error condition has been triggered so far. This allows
us to simplify

  EXPECT_EQ(isl_bool_true, isl_val_is_zero(IslZero));

to

  EXPECT_TRUE(IslZero.is_zero());

This simplification also becomes very clear in operator==, which changes from

  auto IsEqual = isl_set_is_equal(LHS.keep(), RHS.keep());
  EXPECT_NE(isl_bool_error, IsEqual);
  return IsEqual;

to just

  return bool(LHS.is_equal(RHS));

Some background for non-isl users. The isl C interface has an isl_bool type,
which can be either true, false, or error. Hence, whenever a function returns
a value of type isl_bool, an explicit error check should be considered. By
using isl::boolean, we can just cast the isl::boolean to 'bool' or simply use
the isl::boolean in a context where it will automatically be casted to bool
(e.g., in an if-condition). When doing so, the C++ bindings automatically add
code that verifies that the return value is not an error code. If it is, the
program will warn about this and abort. For cases where errors are expected,
isl::boolean provides checks such as boolean::is_true_or_error() or
boolean::is_true_no_error() to explicitly control program behavior in case of
error conditions.

Thanks to the new automatic memory management, we also can avoid many calls to
isl_*_free. For code that had previously been managed by IslPtr<>, many calls
to give/take/copy are eliminated.

Tags: #polly

Reviewed By: Meinersbur

Differential Revision: https://reviews.llvm.org/D30618

llvm-svn: 297464
2017-03-10 14:58:50 +00:00
Tobias Grosser deaef15f52 Introduce isl C++ bindings, Part 1: value_ptr style interface
Over the last couple of months several authors of independent isl C++ bindings
worked together to jointly design an official set of isl C++ bindings which
combines their experience in developing isl C++ bindings. The new bindings have
been designed around a value pointer style interface and remove the need for
explicit pointer managenent and instead use C++ language features to manage isl
objects.

This commit introduces the smart-pointer part of the isl C++ bindings and
replaces the current IslPtr<T> classes, which served the very same purpose, but
had to be manually maintained. Instead, we now rely on automatically generated
classes for each isl object, which provide value_ptr semantics.

An isl object has the following smart pointer interface:

    inline set manage(__isl_take isl_set *ptr);

    class set {
      friend inline set manage(__isl_take isl_set *ptr);
      isl_set *ptr = nullptr;
      inline explicit set(__isl_take isl_set *ptr);

    public:
      inline set();
      inline set(const set &obj);
      inline set &operator=(set obj);
      inline ~set();
      inline __isl_give isl_set *copy() const &;
      inline __isl_give isl_set *copy() && = delete;
      inline __isl_keep isl_set *get() const;
      inline __isl_give isl_set *release();
      inline bool is_null() const;
    }

The interface and behavior of the new value pointer style classes is inspired
by http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3339.pdf, which
proposes a std::value_ptr, a smart pointer that applies value semantics to its
pointee.

We currently only provide a limited set of public constructors and instead
require provide a global overloaded type constructor method "isl::obj
isl::manage(isl_obj *)", which allows to convert an isl_set* to an isl::set by
calling 'S = isl::manage(s)'. This pattern models the make_unique() constructor
for unique pointers.

The next two functions isl::obj::get() and isl::obj::release() are taken
directly from the std::value_ptr proposal:

S.get() extracts the raw pointer of the object managed by S.
S.release() extracts the raw pointer of the object managed by S and sets the
object in S to null.

We additionally add std::obj::copy(). S.copy() returns a raw pointer refering
to a copy of S, which is a shortcut for "isl::obj(oldobj).release()", a
functionality commonly needed when interacting directly with the isl C
interface where all methods marked with __isl_take require consumable raw
pointers.

S.is_null() checks if S manages a pointer or if the managed object is currently
null. We add this function to provide a more explicit way to check if the
pointer is empty compared to a direct conversion to bool.

This commit also introduces a couple of polly-specific extensions that cover
features currently not handled by the official isl C++ bindings draft, but
which have been provided by IslPtr<T> and are consequently added to avoid code
churn. These extensions include:

	- operator bool() : Conversion from objects to bool
	- construction from nullptr_t
	- get_ctx() method
	- take/keep/give methods, which match the currently used naming
	  convention of IslPtr<T> in Polly. They just forward to
	  (release/get/manage).
	- raw_ostream printers

We expect that these extensions are over time either removed or upstreamed to
the official isl bindings.

We also export a couple of classes that have not yet been exported in isl (e.g.,
isl::space)

As part of the code review, the following two questions were asked:

- Why do we not use a standard smart pointer?

std::value_ptr was a proposal that has not been accepted. It is consequently
not available in the standard library. Even if it would be available, we want
to expand this interface with a complete method interface that is conveniently
available from each managed pointer. The most direct way to achieve this is to
generate a specialiced value style pointer class for each isl object type and
add any additional methods to this class. The relevant changes follow in
subsequent commits.

- Why do we not use templates or macros to avoid code duplication?

It is certainly possible to use templates or macros, but as this code is
auto-generated there is no need to make writing this code more efficient. Also,
most of these classes will be specialized with individual member functions in
subsequent commits, such that there will be little code reuse to exploit. Hence,
we decided to do so at the moment.

These bindings are not yet officially part of isl, but the draft is already very
stable. The smart pointer interface itself did not change since serveral months.
Adding this code to Polly is against our normal policy of only importing
official isl code. In this case however, we make an exception to showcase a
non-trivial use case of these bindings which should increase confidence in these
bindings and will help upstreaming them to isl.

Tags: #polly

Reviewed By: Meinersbur

Differential Revision: https://reviews.llvm.org/D30325

llvm-svn: 297452
2017-03-10 11:41:03 +00:00
Michael Kruse f4e201e09f [Support] Remove NonowningIslPtr. NFC.
NonowningIslPtr<isl_X> was used as types of function parameters when the
function does not consume the isl object, i.e. an __isl_keep parameter.

The alternatives are:

1. IslPtr<isl_X>
   This has additional calls to isl_X_copy and isl_X_free to
   increase/decrease the reference counter even though not needed. The
   caller already owns a reference to the isl object.

2. const IslPtr<isl_X>&
   This does not change the reference counter, but requires an
   additional load to get the pointer to the isl object (instead of just
   passing the pointer itself).
   Moreover, the compiler cannot rely on the constness of the pointer
   and has to reload the pointer every time it writes to memory (unless
   alias analysis such as TBAA says it is not possible).

The isl C++ bindings currently in development do not have an equivalent
to NonowningIslPtr and adding one would make the binding more
complicated and its advantage in performance is small. In order to
simplify the transition to these C++ bindings, remove NonowningIslPtr.
Change every former use of it to alternative 2 mentioned aboce
(const IslPtr<isl_X>&).

llvm-svn: 295998
2017-02-23 17:57:27 +00:00
Michael Kruse c28c584604 [DeLICM] Add forgotten unittests in previous commit. NFC.
llvm-svn: 295204
2017-02-15 17:19:22 +00:00
Michael Kruse e23e94a08d [DeLICM] Add Knowledge class. NFC.
The Knowledge class remembers the state of data at any timepoint of a SCoP's
execution. Currently, it tracks whether an array element is unused or is
occupied by some value, and the writes to it. A future addition will be to also
remember which value it contains.

Objects are used to determine whether two Knowledge contain conflicting
information, i.e. two states cannot be true a the same time.

This commit was extracted from the DeLICM algorithm at
https://reviews.llvm.org/D24716.

llvm-svn: 295197
2017-02-15 16:59:10 +00:00
Michael Kruse acb08aaed5 [Support] Add convertZoneToTimepoints. NFC.
This function has been extracted from the upcoming DeLICM patch
(https://reviews.llvm.org/D24716).

In contrast to computeReachingWrite and computeArrayUnused,
convertZoneToTimepoints implies a format for zones (ranges between timepoints).
Zones at the moment are unique to DeLICM, but convertZoneToTimepoints makes most
sense in conjunction with the previous two functions.

llvm-svn: 294094
2017-02-04 15:42:17 +00:00
Michael Kruse ec67d36493 [Support] Add computeArrayUnused. NFC.
This function has been extracted from the upcoming DeLICM patch
(https://reviews.llvm.org/D24716).

llvm-svn: 294093
2017-02-04 15:42:10 +00:00
Michael Kruse f4dc133e69 [Support] Add computeReachingWrite. NFC.
This function has been extracted from the upcoming DeLICM patch
(https://reviews.llvm.org/D24716).

llvm-svn: 294092
2017-02-04 15:42:01 +00:00
Tobias Grosser ff40087a6a Update to recent formatting changes
llvm-svn: 293756
2017-02-01 10:12:09 +00:00
Michael Kruse d1508812f5 [Support] Add general isl tools for DeLICM. NFC.
Add some generally useful isl tools into a their own new ISLTools.cpp.
These are the helpers were extracted from and will be use by the DeLICM
algorithm (https://reviews.llvm.org/D24716).

Suggested-by: 	Tobias Grosser <tobias@grosser.es>
llvm-svn: 293340
2017-01-27 22:51:36 +00:00
Tobias Grosser 21a059af09 Adjust formatting to commit r292110 [NFC]
llvm-svn: 292123
2017-01-16 14:08:10 +00:00
Chandler Carruth 290ea508a6 Teach Polly's unittest macro to link LLVMDemangle which LLVMSupport now
depends on...

llvm-svn: 291637
2017-01-11 01:07:35 +00:00
Michael Kruse 209b463240 Add unittests for foreach(Elt|Piece). NFC.
llvm-svn: 288925
2016-12-07 17:48:02 +00:00
Michael Kruse 7886bd7ca5 Add -polly-flatten-schedule pass.
The -polly-flatten-schedule pass reduces the number of scattering
dimensions in its isl_union_map form to make them easier to understand.
It is not meant to be used in production, only for debugging and
regression tests.

To illustrate, how it can make sets simpler, here is a lifetime set
used computed by the porposed DeLICM pass without flattening:

    { Stmt_reduction_for[0, 4] -> [0, 2, o2, o3] : o2 < 0;
      Stmt_reduction_for[0, 4] -> [0, 1, o2, o3] : o2 >= 5;
      Stmt_reduction_for[0, 4] -> [0, 1, 4, o3] : o3 > 0;
      Stmt_reduction_for[0, i1] -> [0, 1, i1, 1] : 0 <= i1 <= 3;
      Stmt_reduction_for[0, 4] -> [0, 2, 0, o3] : o3 <= 0 }

And here the same lifetime for a semantically identical one-dimensional
schedule:

    { Stmt_reduction_for[0, i1] -> [2 + 3i1] : 0 <= i1 <= 4 }

Differential Revision: https://reviews.llvm.org/D24310

llvm-svn: 280948
2016-09-08 15:02:36 +00:00
Tobias Grosser 9d61e4a980 Avoid the use of large unsigned values in isl unit test
isl_val_int_from_ui takes an 'unsigned long' which has on 32-bit and LLP64
windows systems only 32 bit. Hence, make sure we do not use it with constants
that are larger than 32 bit.

Reported-by: Michael Kruse <llvm@meinersbur.de>
llvm-svn: 279824
2016-08-26 15:42:38 +00:00
Tobias Grosser aa6eb5cd80 unittests: Make the expected value the first argument in EXPECT_EQ [NFC]
This improves the readability of failing test results, as gtest prints always
the first argument as the 'expected value'.

In the previous commit we already changed the tests for isl_valFromAPInt. In
this commit, the tests for IslValToAPInt follow.

Suggested-by: Michael Kruse <llvm@meinersbur.de>
llvm-svn: 279817
2016-08-26 12:25:08 +00:00
Tobias Grosser 437200089d Improve documentation and testing for isl_valFromAPInt
The recent unit tests we gained made clear that the semantics of
isl_valFromAPInt are not clear, due to missing documentation. In this change we
document both the calling interface as well as the implementation of
isl_valFromAPInt.

We also make the implementation easier to read by removing integer wrappig in
abs() when passing in the minimal integer value for a given bitwidth. Even
though wrapping and subsequently interpreting the result as unsigned value gives
the correct result, this is far from obvious.  Instead, we explicitly add one
more bit to the input type to ensure that abs will never wrap. This change did
not uncover a bug in the old implementation, but was introduced to increase
readability.

We update the tests to add a test case for this special case and use this
opportunity to also test a number larger than 64 bit. Finally, we order the
arguments of the test cases to make sure the expected output is first. This
helps readability in case of failing test cases as gtest assumes the first value
to be the exected value.

Reviewed-by: Michael Kruse <llvm@meinersbur.de>
Differential Revision: https://reviews.llvm.org/D23917

llvm-svn: 279815
2016-08-26 12:01:07 +00:00
Tobias Grosser 76f8279e44 Improve documentation and testing of APIntFromVal
The recent unit tests we gained made clear that the semantics of APIntFromVal
are not clear, due to missing documentation. In this change we document both
the calling interface as well as the implementation of APIntFromVal. We also
make the implementation easier to read by removing the use of magic numbers.
Finally, we add tests to check the bitwidth of the created values as well as
the correct modeling of very large numbers.

Reviewed-by: Michael Kruse <llvm@meinersbur.de>
Differential Revision: https://reviews.llvm.org/D23910

llvm-svn: 279813
2016-08-26 10:43:28 +00:00
Michael Kruse fd4a332a3a Do not build unittests by default.
Only build them for check-polly and check-polly-unittests in out-of-tree builds.

In LLVM, this behaviour is controlled with LLVM_BUILD_TESTS. Polly out-of-tree
does not have such a flag.

llvm-svn: 279740
2016-08-25 14:33:44 +00:00
Michael Kruse 05cf9c22f1 Introduce unittests.
Add the infrastructure for unittests to Polly and two simple tests for
conversion between isl_val and APInt. In addition, a build target
check-polly-unittests is added to run only the unittests but not the regression
tests.

Clang's unittest mechanism served as as a blueprint which then was adapted to
Polly.

Differential Revision: https://reviews.llvm.org/D23833

llvm-svn: 279734
2016-08-25 12:36:15 +00:00