Commit Graph

110 Commits

Author SHA1 Message Date
Diego Caballero b7cac864b2 [mlir] Fix typo in SuperVectorizer
NFC.

Reviewed By: aartbik

Differential Revision: https://reviews.llvm.org/D108334
2021-08-18 22:55:12 +00:00
Matthias Springer 4c4ab673f1 [mlir][Analysis][NFC] Split FlatAffineConstraints class
* Extract "value" functionality of `FlatAffineConstraints` into a new derived `FlatAffineValueConstraints` class. Current users of `FlatAffineConstraints` can use `FlatAffineValueConstraints` without additional code changes, thus NFC.
* `FlatAffineConstraints` no longer associates dimensions with SSA Values. All functionality that requires this, is moved to `FlatAffineValueConstraints`.
* `FlatAffineConstraints` no longer makes assumptions about where Values associated with dimensions are coming from.

Differential Revision: https://reviews.llvm.org/D107725
2021-08-17 10:09:17 +09:00
Amy Zhuang a8b7e56f65 [mlir] Set insertion point of vector constant to the top of the vectorized loop body
When we vectorize a scalar constant, the vector constant is inserted before its
first user if the scalar constant is defined outside the loops to be vectorized.
It is possible that the vector constant does not dominate all its users. To fix
the problem, we find the innermost vectorized loop that encloses that first user
and insert the vector constant at the top of the loop body.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D106609
2021-07-29 15:42:23 -07:00
Uday Bondhugula 7932d21f5d [MLIR] Introduce a new rewrite driver to simplify supplied list of ops
Introduce a new rewrite driver (MultiOpPatternRewriteDriver) to rewrite
a supplied list of ops and other ops. Provide a knob to restrict
rewrites strictly to those ops or also to affected ops (but still not to
completely related ops).

This rewrite driver is commonly needed to run any simplification and
cleanup at the end of a transforms pass or transforms utility in a way
that only simplifies relevant IR. This makes it easy to write test cases
while not performing unrelated whole IR simplification that may
invalidate other state at the caller.

The introduced utility provides more freedom to developers of transforms
and transform utilities to perform focussed and local simplification. In
several cases, it provides greater efficiency as well as more
simplification when compared to repeatedly calling
`applyOpPatternsAndFold`; in other cases, it avoids the need to
undesirably call `applyPatternsAndFoldGreedily` to do unrelated
simplification in a FuncOp.

Update a few transformations that were earlier using
applyOpPatternsAndFold (SimplifyAffineStructures,
affineDataCopyGenerate, a linalg transform).

TODO:
- OpPatternRewriteDriver can be removed as it's a special case of
  MultiOpPatternRewriteDriver, i.e., both can be merged.

Differential Revision: https://reviews.llvm.org/D106232
2021-07-21 20:25:16 +05:30
Uday Bondhugula 11d88c4acb [MLIR][NFC] Move normalizeAffine methods to Affine utils
The normalizeAffineForOp and normalizedAffineParallel methods were
misplaced in the AffineLoopNormalize pass file while their declarations
were in affine utils. Move these to affine Utils.cpp. NFC.

Differential Revision: https://reviews.llvm.org/D105468
2021-07-07 08:11:28 +05:30
William S. Moses 0cd8422e8c [MLIR] Eliminate unnecessary affine stores
Deduce circumstances where an affine load could not possibly be read by an operation (such as an affine load), and if so, eliminate the load

Differential Revision: https://reviews.llvm.org/D105041
2021-06-30 09:45:26 -04:00
William S. Moses 44826ecd92 [MLIR] Correct memrefdataflow behavior in the presence of cast and other operations
MemRefDataFlow performs mem2reg style operations for affine load/stores. Unfortunately, it is not presently correct in the presence of external operations such as memref.cast, or function calls. This diff extends the functionality of the pass to remain correct in the presence of such ops.

Differential Revision: https://reviews.llvm.org/D104053
2021-06-28 12:23:29 -04:00
Matthias Springer 66f878cee9 [mlir][NFC] Remove Standard dialect dependency on MemRef dialect
* Remove dependency: Standard --> MemRef
* Add dependencies: GPUToNVVMTransforms --> MemRef, Linalg --> MemRef, MemRef --> Tensor
* Note: The `subtensor_insert_propagate_dest_cast` test case in MemRef/canonicalize.mlir will be moved to Tensor/canonicalize.mlir in a subsequent commit, which moves over the remaining Tensor ops from the Standard dialect to the Tensor dialect.

Differential Revision: https://reviews.llvm.org/D104506
2021-06-21 17:55:23 +09:00
Uday Bondhugula 54384d1723 [MLIR] Make store to load fwd condition less conservative
Make store to load fwd condition for -memref-dataflow-opt less
conservative. Post dominance info is not really needed. Add additional
check for common cases.

Differential Revision: https://reviews.llvm.org/D104174
2021-06-17 01:26:38 +05:30
Prashant Kumar 51d43bbc46 [MLIR] Fix affine parallelize pass.
To control the number of outer parallel loops, we need to process the
 outer loops first and hence pre-order walk fixes the issue.

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D104361
2021-06-17 01:25:24 +05:30
Uday Bondhugula 88e4aae57d [MLIR][NFC] Rename MemRefDataFlow -> AffineScalarReplacement
NFC. Rename MemRefDataFlow -> AffineScalarReplacement and move to
AffineTransforms library. Pass command line rename: -memref-dataflow-opt
-> affine-scalrep. Update outdated pass documentation.

Rationale:
https://llvm.discourse.group/t/move-and-rename-memref-dataflow-opt-lib-transforms-lib-affine-dialect-transforms/3640

Differential Revision: https://reviews.llvm.org/D104190
2021-06-14 17:52:53 +05:30
Stephen Neuendorffer 984e270a9a [mlir] make normalizeAffineFor public
Previously this was just a static method.
2021-06-11 20:12:37 -07:00
Vinayaka Bandishti eff269fc9f [MLIR][Affine][LICM] Mark users of `iter_args` variant
Prevent users of `iter_args` of an affine for loop from being hoisted
out of it. Otherwise, LICM leads to a violation of the SSA dominance
(as demonstrated in the added test case).

Fixes: https://bugs.llvm.org/show_bug.cgi?id=50103

Reviewed By: bondhugula, ayzhuang

Differential Revision: https://reviews.llvm.org/D102984
2021-05-25 15:56:52 +05:30
Nicolas Vasilache 8eb18a0f3e [mlir][Standard] NFC - Drop remaining EDSC usage
Drop the remaining EDSC subdirectories and update all uses.

Differential Revision: https://reviews.llvm.org/D102911
2021-05-21 10:40:39 +00:00
Julian Gross 1fbb484ea4 [WIP][mlir] Resolve memref dependency in canonicalize pass.
Splitting the memref dialect lead to an introduction of several dependencies
to avoid compilation issues. The canonicalize pass also depends on the
memref dialect, but it shouldn't. This patch resolves the dependencies
and the unintuitive includes are removed. However, the dependency moves
to the constructor of the std dialect.

Differential Revision: https://reviews.llvm.org/D102060
2021-05-17 11:33:38 +02:00
Sean Silva 12874e93a1 [mlir][NFC] Add helper for common pattern of replaceAllUsesExcept
This covers the extremely common case of replacing all uses of a Value
with a new op that is itself a user of the original Value.

This should also be a little bit more efficient than the
`SmallPtrSet<Operation *, 1>{op}` idiom that was being used before.

Differential Revision: https://reviews.llvm.org/D102373
2021-05-13 12:42:10 -07:00
Sergei Grechanik d80b04ab00 [mlir][Affine][Vector] Support vectorizing reduction loops
This patch adds support for vectorizing loops with 'iter_args'
implementing known reductions along the vector dimension. Comparing to
the non-vector-dimension case, two additional things are done during
vectorization of such loops:
- The resulting vector returned from the loop is reduced to a scalar
  using `vector.reduce`.
- In some cases a mask is applied to the vector yielded at the end of
  the loop to prevent garbage values from being written to the
  accumulator.

Vectorization of reduction loops is disabled by default. To enable it, a
map from loops to array of reduction descriptors should be explicitly passed to
`vectorizeAffineLoops`, or `vectorize-reductions=true` should be passed
to the SuperVectorize pass.

Current limitations:
- Loops with a non-unit step size are not supported.
- n-D vectorization with n > 1 is not supported.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D100694
2021-05-05 09:03:59 -07:00
Alex Zinenko 6841e6afba [mlir] support max/min lower/upper bounds in affine.parallel
This enables to express more complex parallel loops in the affine framework,
for example, in cases of tiling by sizes not dividing loop trip counts perfectly
or inner wavefront parallelism, among others. One can't use affine.max/min
and supply values to the nested loop bounds since the results of such
affine.max/min operations aren't valid symbols. Making them valid symbols
isn't an option since they would introduce selection trees into memref
subscript arithmetic as an unintended and undesired consequence. Also
add support for converting such loops to SCF. Drop some API that isn't used in
the core repo from AffineParallelOp since its semantics becomes ambiguous in
presence of max/min bounds. Loop normalization is currently unavailable for
such loops.

Depends On D101171

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D101172
2021-04-29 13:16:25 +02:00
Alex Zinenko 545fa37834 [mlir] Affine: parallelize affine loops with reductions
Introduce a basic support for parallelizing affine loops with reductions
expressed using iteration arguments. Affine parallelism detector now has a flag
to assume such reductions are parallel. The transformation handles a subset of
parallel reductions that are can be expressed using affine.parallel:
integer/float addition and multiplication. This requires to detect the
reduction operation since affine.parallel only supports a fixed set of
reduction operators.

Reviewed By: chelini, kumasento, bondhugula

Differential Revision: https://reviews.llvm.org/D101171
2021-04-29 13:16:24 +02:00
Nico Weber 297a5b7cbc [mlir] hopefully final round of iwyu fixes after ba7a92c01e 2021-04-21 11:03:06 -04:00
Nico Weber 56f987fafe [mlir] yet more iwyu fixes after ba7a92c01e 2021-04-21 10:54:44 -04:00
Amy Zhuang 9194071626 [mlir] Support hoisting whole affine for loops in LICM
Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D100512
2021-04-20 18:07:06 -07:00
Sumesh Udayakumaran f56791ae2e [mlir] Prevent operations with users from being hoisted
This patch collects operations that have users in a for loop and uses
them  when loop invariant operations are detected and hoisted.

Reviewed By: bondhugula, vinayaka-polymage

Differential Revision: https://reviews.llvm.org/D99761
2021-04-13 15:29:17 -07:00
Chris Lattner 79d7f618af Rename FrozenRewritePatternList -> FrozenRewritePatternSet; NFC.
This nicely aligns the naming with RewritePatternSet.  This type isn't
as widely used, but we keep a using declaration in to help with
downstream consumption of this change.

Differential Revision: https://reviews.llvm.org/D99131
2021-03-22 17:40:45 -07:00
Chris Lattner dc4e913be9 [PatternMatch] Big mechanical rename OwningRewritePatternList -> RewritePatternSet and insert -> add. NFC
This doesn't change APIs, this just cleans up the many in-tree uses of these
names to use the new preferred names.  We'll keep the old names around for a
couple weeks to help transitions.

Differential Revision: https://reviews.llvm.org/D99127
2021-03-22 17:20:50 -07:00
Chris Lattner 3a506b31a3 Change OwningRewritePatternList to carry an MLIRContext with it.
This updates the codebase to pass the context when creating an instance of
OwningRewritePatternList, and starts removing extraneous MLIRContext
parameters.  There are many many more to be removed.

Differential Revision: https://reviews.llvm.org/D99028
2021-03-21 10:06:31 -07:00
Julian Gross e2310704d8 [MLIR] Create memref dialect and move dialect-specific ops from std.
Create the memref dialect and move dialect-specific ops
from std dialect to this dialect.

Moved ops:
AllocOp -> MemRef_AllocOp
AllocaOp -> MemRef_AllocaOp
AssumeAlignmentOp -> MemRef_AssumeAlignmentOp
DeallocOp -> MemRef_DeallocOp
DimOp -> MemRef_DimOp
MemRefCastOp -> MemRef_CastOp
MemRefReinterpretCastOp -> MemRef_ReinterpretCastOp
GetGlobalMemRefOp -> MemRef_GetGlobalOp
GlobalMemRefOp -> MemRef_GlobalOp
LoadOp -> MemRef_LoadOp
PrefetchOp -> MemRef_PrefetchOp
ReshapeOp -> MemRef_ReshapeOp
StoreOp -> MemRef_StoreOp
SubViewOp -> MemRef_SubViewOp
TransposeOp -> MemRef_TransposeOp
TensorLoadOp -> MemRef_TensorLoadOp
TensorStoreOp -> MemRef_TensorStoreOp
TensorToMemRefOp -> MemRef_BufferCastOp
ViewOp -> MemRef_ViewOp

The roadmap to split the memref dialect from std is discussed here:
https://llvm.discourse.group/t/rfc-split-the-memref-dialect-from-std/2667

Differential Revision: https://reviews.llvm.org/D98041
2021-03-15 11:14:09 +01:00
Diego Caballero 0fd0fb5329 Reland: [mlir][Affine][Vector] Add initial support for 'iter_args' to Affine vectorizer.
This patch adds support for vectorizing loops with 'iter_args' when those loops
are not a vector dimension. This allows vectorizing outer loops with an inner
'iter_args' loop (e.g., reductions). Vectorizing scenarios where 'iter_args'
loops are vector dimensions would require more work (e.g., analysis,
generating horizontal reduction, etc.) not included in this patch.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D97892
2021-03-12 01:08:28 +02:00
Diego Caballero 96891f0418 Reland: [mlir][Vector][Affine] Improve affine vectorizer algorithm
This patch replaces the root-terminal vectorization approach implemented in the
Affine vectorizer with a topological order approach that vectorizes all the
operations within the target loop nest. These are the most important changes
introduced by the new algorithm:
  * Removed tracking of root and terminal ops. Existing vectorization
    functionality is preserved and extended so that loop nests without
    root-terminal chains can be vectorized.
  * Vectorizing a loop nest now only requires a single topological traversal.
  * A new vector loop nest is incrementally built along the vectorization
    process. The original scalar loop is kept intact. No cloning guard is needed
    to recover the scalar loop if vectorization fails. This approach also
    simplifies the challenging task of replacing a loop operation amid the
    vectorization process without invalidating the analysis information that
    depends on the original loop.
  * Vectorization of specific operations has been implemented as independent,
    preparing them to be moved to a potential vectorization interface.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D97442
2021-03-12 00:19:50 +02:00
Diego Caballero ed193bce9d [mlir][Vector][Affine] Fix heap-use-after-free in vectorizer
This patch fixes a heap-use-after-free introduced by the recent changes
in the vectorizer: https://reviews.llvm.org/rG95db7b4aeaad590f37720898e339a6d54313422f
The problem is due to the way candidate loops are visited. All candidate loops
are pattern-matched beforehand using the 'NestedMatch' utility. These matches may
intersect with each other so it may happen that we try to vectorize a loop that
was previously vectorized. The new vectorization algorithm replaces the original
loops that are vectorized with new loops and, therefore, any reference to the
original loops in the pre-computed matches becomes invalid.

This patch fixes the problem by classifying the candidate matches into buckets
before vectorization. Each bucket contains all the matches that intersect. The
vectorizer uses these buckets to make sure that we only vectorize *one* match from
each bucket, at most.

Differential Revision: https://reviews.llvm.org/D98382
2021-03-11 20:44:07 +02:00
Alex Zinenko 79da91c59a Revert "[mlir][Vector][Affine] Improve affine vectorizer algorithm"
This reverts commit 95db7b4aea.

This breaks vectorize_2d.mlir and vectorize_3d.mlir test under ASAN (use
after free).
2021-03-10 20:25:49 +01:00
Alex Zinenko ed715536f1 Revert "[mlir][Affine][Vector] Add initial support for 'iter_args' to Affine vectorizer."
This reverts commit 77a9d1549f.

Parent commit is broken.
2021-03-10 20:25:32 +01:00
Diego Caballero 77a9d1549f [mlir][Affine][Vector] Add initial support for 'iter_args' to Affine vectorizer.
This patch adds support for vectorizing loops with 'iter_args' when those loops
are not a vector dimension. This allows vectorizing outer loops with an inner
'iter_args' loop (e.g., reductions). Vectorizing scenarios where 'iter_args'
loops are vector dimensions would require more work (e.g., analysis,
generating horizontal reduction, etc.) not included in this patch.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D97892
2021-03-10 20:40:21 +02:00
Diego Caballero 95db7b4aea [mlir][Vector][Affine] Improve affine vectorizer algorithm
This patch replaces the root-terminal vectorization approach implemented in the
Affine vectorizer with a topological order approach that vectorizes all the
operations within the target loop nest. These are the most important changes
introduced by the new algorithm:
  * Removed tracking of root and terminal ops. Existing vectorization
    functionality is preserved and extended so that loop nests without
    root-terminal chains can be vectorized.
  * Vectorizing a loop nest now only requires a single topological traversal.
  * A new vector loop nest is incrementally built along the vectorization
    process. The original scalar loop is kept intact. No cloning guard is needed
    to recover the scalar loop if vectorization fails. This approach also
    simplifies the challenging task of replacing a loop operation amid the
    vectorization process without invalidating the analysis information that
    depends on the original loop.
  * Vectorization of specific operations has been implemented as independent,
    preparing them to be moved to a potential vectorization interface.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D97442
2021-03-10 20:29:58 +02:00
Adam Straw 99c0458f2f separate AffineMapAccessInterface from AffineRead/WriteOpInterface
Separating the AffineMapAccessInterface from AffineRead/WriteOp interface so that dialects which extend Affine capabilities (e.g. PlaidML PXA = parallel extensions for Affine) can utilize relevant passes (e.g. MemRef normalization).

Reviewed By: bondhugula

Differential Revision: https://reviews.llvm.org/D96284
2021-02-16 13:05:27 -08:00
River Riddle fe7c0d90b2 [mlir][IR] Remove the concept of `OperationProperties`
These properties were useful for a few things before traits had a better integration story, but don't really carry their weight well these days. Most of these properties are already checked via traits in most of the code. It is better to align the system around traits, and improve the performance/cost of traits in general.

Differential Revision: https://reviews.llvm.org/D96088
2021-02-09 12:00:15 -08:00
River Riddle e21adfa32d [mlir] Mark LogicalResult as LLVM_NODISCARD
This makes ignoring a result explicit by the user, and helps to prevent accidental errors with dropped results. Marking LogicalResult as no discard was always the intention from the beginning, but got lost along the way.

Differential Revision: https://reviews.llvm.org/D95841
2021-02-04 15:10:10 -08:00
Diego Caballero f9f6b4f30b [mlir] Silence GCC warnings
Reviewed By: mehdi_amini, rriddle

Differential Revision: https://reviews.llvm.org/D95906
2021-02-04 20:54:18 +02:00
Alex Zinenko 80766ecc65 [mlir] Add an option to control the number of loops in affine parallelizer
Add a pass option to control the number of nested parallel loops produced by
the parallelization passes. This is useful to build end-to-end passes targeting
systems that don't need multiple parallel dimensions (e.g., CPUs typically need
only one).

Reviewed By: wsmoses, chelini

Differential Revision: https://reviews.llvm.org/D92765
2020-12-08 10:44:37 +01:00
Navdeep Kumar dc930e5f2f [MLIR][Affine] Add affine.for normalization support
Add support to normalize affine.for ops i.e., convert the lower bound to zero
and loop step to one. The Upper bound is set to the trip count of the loop.
The exact value of loopIV is calculated just inside the body of affine.for.
Currently loops with lower bounds having single result are supported. No such
restriction exists on upper bounds.

Differential Revision: https://reviews.llvm.org/D92233
2020-12-07 22:04:07 +05:30
Christian Sigg c4a0405902 Add `Operation* OpState::operator->()` to provide more convenient access to members of Operation.
Given that OpState already implicit converts to Operator*, this seems reasonable.

The alternative would be to add more functions to OpState which forward to Operation.

Reviewed By: rriddle, ftynse

Differential Revision: https://reviews.llvm.org/D92266
2020-12-02 15:46:20 +01:00
Diego Caballero f82d307c98 [mlir][Affine] Remove single iteration affine.for ops in AffineLoopNormalize
This patch renames AffineParallelNormalize to AffineLoopNormalize to make it
more generic and be able to hold more loop normalization transformations in
the future for affine.for and affine.parallel ops. Eventually, it could also be
extended to support scf.for and scf.parallel. As a starting point for affine.for,
the patch also adds support for removing single iteration affine.for ops to the
the pass.

Differential Revision: https://reviews.llvm.org/D90267
2020-11-02 16:44:04 -08:00
River Riddle 3fffffa882 [mlir][Pattern] Add a new FrozenRewritePatternList class
This class represents a rewrite pattern list that has been frozen, and thus immutable. This replaces the uses of OwningRewritePatternList in pattern driver related API, such as dialect conversion. When PDL becomes more prevalent, this API will allow for optimizing a set of patterns once without the need to do this per run of a pass.

Differential Revision: https://reviews.llvm.org/D89104
2020-10-26 18:01:06 -07:00
River Riddle b6eb26fd0e [mlir][NFC] Move around the code related to PatternRewriting to improve layering
There are several pieces of pattern rewriting infra in IR/ that really shouldn't be there. This revision moves those pieces to a better location such that they are easier to evolve in the future(e.g. with PDL). More concretely this revision does the following:

* Create a Transforms/GreedyPatternRewriteDriver.h and move the apply*andFold methods there.
The definitions for these methods are already in Transforms/ so it doesn't make sense for the declarations to be in IR.

* Create a new lib/Rewrite library and move PatternApplicator there.
This new library will be focused on applying rewrites, and will also include compiling rewrites with PDL.

Differential Revision: https://reviews.llvm.org/D89103
2020-10-26 18:01:06 -07:00
Geoffrey Martin-Noble d4e889f1f5 Remove `Ops` suffix from dialect library names
Dialects include more than just ops, so this suffix is outdated. Follows
discussion in
https://llvm.discourse.group/t/rfc-canonical-file-paths-to-dialects/621

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D88530
2020-09-30 18:00:44 -07:00
Diego Caballero 93936da904 [mlir][Affine][VectorOps] Fix super vectorizer utility (D85869)
Adding missing code that should have been part of "D85869: Utility to
vectorize loop nest using strategy."

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D88346
2020-09-28 16:24:11 -07:00
Fangrui Song 91671e13ef [mlir] Fix -Wunused-variable in -DLLVM_ENABLE_ASSERTIONS=off build after D85869 2020-09-21 18:34:49 -07:00
Diego Caballero 14d0735d34 [MLIR][Affine][VectorOps] Utility to vectorize loop nest using strategy
This patch adds a utility based on SuperVectorizer to vectorize an
affine loop nest using a given vectorization strategy. This strategy allows
targeting specific loops for vectorization instead of relying of the
SuperVectorizer analysis to choose the right loops to vectorize.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D85869
2020-09-21 16:28:28 -07:00
Navdeep Kumar 0602e8f77f [MLIR][Affine] Add parametric tile size support for affine.for tiling
Add support to tile affine.for ops with parametric sizes (i.e., SSA
values). Currently supports hyper-rectangular loop nests with constant
lower bounds only. Move methods

  - moveLoopBody(*)
  - getTileableBands(*)
  - checkTilingLegality(*)
  - tilePerfectlyNested(*)
  - constructTiledIndexSetHyperRect(*)

to allow reuse with constant tile size API. Add a test pass -test-affine
-parametric-tile to test parametric tiling.

Differential Revision: https://reviews.llvm.org/D87353
2020-09-17 23:39:14 +05:30
Diego Caballero 609f5e050c [mlir] Rename 'setInsertionPointAfter' to avoid ambiguity
Rename 'setInsertionPointAfter(Value)' API to avoid ambiguity with
'setInsertionPointAfter(Operation *)' for SingleResult operations which
implicitly convert to Value (see D86756).

Differential Revision: https://reviews.llvm.org/D87155
2020-09-15 13:58:42 -07:00