61 Commits

Author SHA1 Message Date
Mehdi Amini
ff0dcc4614
[MLIR][Linalg] Harden parsing Linalg named ops (#145337)
This thread through proper error handling / reporting capabilities to
avoid hitting llvm_unreachable while parsing linalg ops.

Fixes #132755
Fixes #132740
Fixes #129185
2025-06-26 00:22:08 +02:00
Matthias Springer
0b2197b0cf
[mlir][Interfaces] Clean up DestinationStyleOpInterface (#67015)
* "init" operands are specified with `MutableOperandRange` (which gives
access to the underlying `OpOperand *`). No more magic numbers.
* Remove most interface methods and make them helper functions. Only
`getInitsMutable` should be implemented.
* Provide separate helper functions for accessing mutable/immutable
operands (`OpOperand`/`Value`, in line with #66515): `getInitsMutable`
and `getInits` (same naming convention as auto-generated op accessors).
`getInputOperands` was not renamed because this function cannot return a
`MutableOperandRange` (because the operands are not necessarily
consecutive). `OpOperandVector` is no longer needed.
* The new `getDpsInits`/`getDpsInitsMutable` is more efficient than the
old `getDpsInitOperands` because no `SmallVector` is created. The new
functions return a range of operands.
* Fix a bug in `getDpsInputOperands`: out-of-bounds operands were
potentially returned.
2023-09-21 18:04:08 +02:00
Andrey Turetskiy
fe8e7e30f9 [mlir-linalg-ods-yaml-gen] Fix a bug in getDpsInitsPositionRange
definition to support operators with multiple outputs.

Differential Revision: https://reviews.llvm.org/D152388
2023-08-30 21:08:56 -07:00
Benjamin Maxwell
0d3abdc263 [mlir][Linalg] Fix formatting of generated docs markdown
This patch prevents `mlir-linalg-ods-yaml-gen` from adding extra
whitespace around the summary and description fields. This broke the
_italics_ of the summary as _ this _ is not recognised by markdown.
It also meant the first line of the description was in a code block
  as it was indented two spaces.

The separator between summary and description has also been updated to
two newlines. This was already followed and prevents line wrapping the
summary putting part of it in the description.

These issues can be currently seen at: https://mlir.llvm.org/docs/Dialects/Linalg/

Reviewed By: awarzynski

Differential Revision: https://reviews.llvm.org/D157853
2023-08-16 15:08:51 +00:00
Tres Popp
6de63b82cc [mlir] Move tblgen code generation to use functional forms of cast/isa
Summary:
The method forms are deprecated. This updates the rest of the tblgen
uses of methods where a function call is available.

Context:
- https://mlir.llvm.org/deprecation/ at "Use the free function variants for dyn_cast/cast/isa/…"
- Original discussion at https://discourse.llvm.org/t/preferred-casting-style-going-forward/68443

Reviewers: rriddle
2023-05-26 07:47:03 +02:00
Alexander Belyaev
b4db15a949 [mlir] Rename getInputs->getDpsInputs and getOutputs->getDpsInits in DPS interface.
https://discourse.llvm.org/t/rfc-interface-for-destination-style-ops/64056

Differential Revision: https://reviews.llvm.org/D136943
2022-10-28 15:41:12 +02:00
Oleg Shyshkov
c38d9cf20e [mlir] Remove iterator_types() method from LinalgStructuredInterface.
`getIteratorTypesArray` should be used instead. It's a better substitute for all the current usages of the interface.

The current `ArrayAttr iterator_types()` has a few problems:
* It creates an assumption operation has iterators types as an attribute, but it's not always the case. Sometime iterator types can be inferred from other attribute, or they're just static.
* ArrayAttr is an obscure contained and required extracting values in the client code.
* Makes it hard to migrate iterator types from strings to enums ([RFC](https://discourse.llvm.org/t/rfc-enumattr-for-iterator-types-in-linalg/64535/9)).

Concrete ops, like `linalg.generic` will still have iterator types as an attribute if needed.

As a side effect, this change helps a bit with migration to prefixed accessors.

Differential Revision: https://reviews.llvm.org/D135765
2022-10-13 07:52:43 +00:00
Matthias Springer
2d2737667e [mlir][linalg][NFC] Drop emitAccessorPrefix from Linalg dialect
Differential Revision: https://reviews.llvm.org/D135048
2022-10-03 11:35:41 +09:00
Jacques Pienaar
7d273fde11 [mlir] Populate default attributes on op creation
Default attributes were only handled by ODS accessors generated with the
intention that these behave as if set attributes. This addresses the
long standing TODO to address this inconsistency. Moving the
initialization to construction vs every access. Removing need for
duplicated default attribute population in python bindings.

Switch some of the OpenMP ones to optional attribute with default as the
currently set default values are not legal. May need to dig more there.

Switched LinAlg generated ones to optional attribute with default as its
quite widely used and unclear where it falls on two different
interpretations.

Differential Revision: https://reviews.llvm.org/D130916
2022-08-22 16:49:46 -07:00
Jacques Pienaar
d2c0572b2e [mlir] Flip LinAlg dialect to _Both
This one required more changes than ideal due to overlapping generated name
with different return types. Changed getIndexingMaps to getIndexingMapsArray to
move it out of the way/highlight that it returns (more expensively) a
SmallVector and uses the prefixed name for the Attribute.

Differential Revision: https://reviews.llvm.org/D129919
2022-07-19 14:42:58 -07:00
gysit
407b351da2 [mlir][linalg] Add ods-gen helper to simplify the build methods.
Add a helper used to implement the build methods generated by ods-gen. The change reduces code size and compilation time since all structured op builders use the same build method. The change reduces the LinalgOps.cpp compilation time from 10.2s to 9.8s (debug build).

Depends On D123987

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D124003
2022-04-20 13:14:38 +00:00
gysit
17721b6915 [mlir][linalg] Avoid template methods for parsing and printing.
The revision avoids template methods for parsing and printing that are replicated for every named operation. Instead, the new methods take a regionBuilder argument. The revision reduces the compile time of LinalgOps.cpp from 11.2 to 10.2 seconds (debug build).

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D123987
2022-04-20 13:06:31 +00:00
gysit
d629645fcd [mlir][OpDSL] Add support for adding canonicalization patterns.
Extend OpDSL with a `defines` method that can set the `hasCanonicalizer` flag for an OpDSL operation. If the flag is set via `defines(Canonicalizer)` the operation needs to implement the `getCanonicalizationPatterns` method. The revision specifies the flag for linalg.fill_tensor and adds an empty `FillTensorOp::getCanonicalizationPatterns` implementation.

This revision is a preparation step to replace linalg.fill by its OpDSL counterpart linalg.fill_tensor. The two are only functionally equivalent if both specify the same canonicalization patterns. The revision is thus a prerequisite for the linalg.fill replacement.

Depends On D120725

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D120726
2022-03-08 15:56:59 +00:00
gysit
e9085d0d25 [mlir][OpDSL] Rename function to make signedness explicit (NFC).
The revision renames the following OpDSL functions:
```
TypeFn.cast -> TypeFn.cast_signed
BinaryFn.min -> BinaryFn.min_signed
BinaryFn.max -> BinaryFn.max_signed
```
The corresponding enum values on the C++ side are renamed accordingly:
```
#linalg.type_fn<cast> -> #linalg.type_fn<cast_signed>
#linalg.binary_fn<min> -> #linalg.binary_fn<min_signed>
#linalg.binary_fn<max> -> #linalg.binary_fn<max_signed>
```

Depends On D120110

Reviewed By: aartbik

Differential Revision: https://reviews.llvm.org/D120562
2022-03-01 08:15:53 +00:00
gysit
24357fec8d [mlir][OpDSL] Add arithmetic function attributes.
The revision extends OpDSL with unary and binary function attributes. A function attribute, makes the operations used in the body of a structured operation configurable. For example, a pooling operation may take an aggregation function attribute that specifies if the op shall implement a min or a max pooling. The goal of this revision is to define less and more flexible operations.

We may thus for example define an element wise op:
```
linalg.elem(lhs, rhs, outs=[out], op=BinaryFn.mul)
```
If the op argument is not set the default operation is used.

Depends On D120109

Reviewed By: nicolasvasilache, aartbik

Differential Revision: https://reviews.llvm.org/D120110
2022-03-01 07:45:47 +00:00
gysit
cd2776b0d5 [mlir][OpDSL] Split arithmetic functions.
Split arithmetic function into unary and binary functions. The revision prepares the introduction of unary and binary function attributes that work similar to type function attributes.

Depends On D120108

Reviewed By: aartbik

Differential Revision: https://reviews.llvm.org/D120109
2022-02-25 15:27:42 +00:00
gysit
4d4cb17da8 [mlir][OpDSL] Refactor function handling.
Prepare the OpDSL function handling to introduce more function classes. A follow up commit will split ArithFn into UnaryFn and BinaryFn. This revision prepares the split by adding a function kind enum to handle different function types using a single class on the various levels of the stack (for example, there is now one TensorFn and one ScalarFn).

Depends On D119718

Reviewed By: aartbik

Differential Revision: https://reviews.llvm.org/D120108
2022-02-25 15:05:32 +00:00
gysit
51fdd802c7 [mlir][OpDSL] Add type function attributes.
Previously, OpDSL operation used hardcoded type conversion operations (cast or cast_unsigned). Supporting signed and unsigned casts thus meant implementing two different operations. Type function attributes allow us to define a single operation that has a cast type function attribute which at operation instantiation time may be set to cast or cast_unsigned. We may for example, defina a matmul operation with a cast argument:

```
@linalg_structured_op
def matmul(A=TensorDef(T1, S.M, S.K), B=TensorDef(T2, S.K, S.N), C=TensorDef(U, S.M, S.N, output=True),
    cast=TypeFnAttrDef(default=TypeFn.cast)):
  C[D.m, D.n] += cast(U, A[D.m, D.k]) * cast(U, B[D.k, D.n])
```

When instantiating the operation the attribute may be set to the desired cast function:

```
linalg.matmul(lhs, rhs, outs=[out], cast=TypeFn.cast_unsigned)
```

The revsion introduces a enum in the Linalg dialect that maps one-by-one to the type functions defined by OpDSL.

Reviewed By: aartbik

Differential Revision: https://reviews.llvm.org/D119718
2022-02-25 08:25:23 +00:00
gysit
348bfc8e50 [mlir][linalg] Add attributes to region builder (NFC).
Adapt the region builder signature to hand in the attributes of the created ops. The revision is a preparation step the support named ops that need access to the operation attributes during op creation.

Depends On D119692

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D119693
2022-02-14 13:14:14 +00:00
gysit
d50571ab07 [mlir][OpDSL] Add default value to index attributes.
Index attributes had no default value, which means the attribute values had to be set on the operation. This revision adds a default parameter to `IndexAttrDef`. After the change, every index attribute has to define a default value. For example, we may define the following strides attribute:
```

```
When using the operation the default stride is used if the strides attribute is not set. The mechanism is implemented using `DefaultValuedAttr`.

Additionally, the revision uses the naming index attribute instead of attribute more consistently, which is a preparation for follow up revisions that will introduce function attributes.

Depends On D119125

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D119126
2022-02-14 12:14:12 +00:00
gysit
a3655de2c8 [mlir][OpDSL] Add support for basic rank polymorphism.
Previously, OpDSL did not support rank polymorphism, which required a separate implementation of linalg.fill. This revision extends OpDSL to support rank polymorphism for a limited class of operations that access only scalars and tensors of rank zero. At operation instantiation time, it scales these scalar computations to multi-dimensional pointwise computations by replacing the empty indexing maps with identity index maps. The revision does not change the DSL itself, instead it adapts the Python emitter and the YAML generator to generate different indexing maps and and iterators depending on the rank of the first output.

Additionally, the revision introduces a `linalg.fill_tensor` operation that in a future revision shall replace the current handwritten `linalg.fill` operation. `linalg.fill_tensor` is thus only temporarily available and will be renamed to `linalg.fill`.

Reviewed By: nicolasvasilache, stellaraccident

Differential Revision: https://reviews.llvm.org/D119003
2022-02-11 08:27:49 +00:00
gysit
cf05668c17 [mlir][OpDSL] Rename PrimFn to ArithFn.
The revision renames `PrimFn` to `ArithFn`. The name resembles the newly introduced arith dialect that implements most of the arithmetic functions. An exception are log/exp that are part of the math dialect.

Depends On D115239

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D115240
2022-01-07 12:38:03 +00:00
gysit
15757ea80a [mlir][OpDSL] Add TypeFn class.
This revision introduces a the `TypeFn` class that similar to the `PrimFn` class contains an extensible set of type conversion functions. Having the same mechanism for both type conversion functions and arithmetic functions improves code consistency. Additionally, having an explicit function class and function name is a prerequisite to specify a conversion or arithmetic function via attribute. In a follow up commits, we will introduce function attributes to make OpDSL operations more generic. In particular, the goal is to handle signed and unsigned computation in one operations. Today, there is a linalg.matmul and a linalg.matmul_unsigned.

The commit implements the following changes:
- Introduce the class of type conversion functions `TypeFn`
- Replace the hardwired cast and cast_unsigned ops by the `TypeFn` counterparts
- Adapt the python and C++ code generation paths to support the new cast operations

Example:
```
cast(U, A[D.m, D.k])
```
changes to
```
TypeFn.cast(U, A[D.m, D.k])
```

Depends On D115237

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D115239
2022-01-07 12:26:47 +00:00
gysit
2648e2d5dd [mlir][OpDSL] Rename AttributeDef to IndexAttrDef.
Renaming `AttributeDef` to `IndexAttrDef` prepares OpDSL to support different kinds of attributes and more closely reflects the purpose of the attribute.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D115237
2022-01-07 12:09:25 +00:00
River Riddle
ae40d62541 [mlir] Refactor ElementsAttr's value access API
There are several aspects of the API that either aren't easy to use, or are
deceptively easy to do the wrong thing. The main change of this commit
is to remove all of the `getValue<T>`/`getFlatValue<T>` from ElementsAttr
and instead provide operator[] methods on the ranges returned by
`getValues<T>`. This provides a much more convenient API for the value
ranges. It also removes the easy-to-be-inefficient nature of
getValue/getFlatValue, which under the hood would construct a new range for
the type `T`. Constructing a range is not necessarily cheap in all cases, and
could lead to very poor performance if used within a loop; i.e. if you were to
naively write something like:

```
DenseElementsAttr attr = ...;
for (int i = 0; i < size; ++i) {
  // We are internally rebuilding the APFloat value range on each iteration!!
  APFloat it = attr.getFlatValue<APFloat>(i);
}
```

Differential Revision: https://reviews.llvm.org/D113229
2021-11-09 00:15:08 +00:00
Tobias Gysi
3fe7fe4424 [mlir][linalg] Add unsigned min/max/cast function to OpDSL.
Update OpDSL to support unsigned integers by adding unsigned min/max/cast signatures. Add tests in OpDSL and on the C++ side to verify the proper signed and unsigned operations are emitted.

The patch addresses an issue brought up in https://reviews.llvm.org/D111170.

Reviewed By: rsuderman

Differential Revision: https://reviews.llvm.org/D111230
2021-10-07 06:27:20 +00:00
Stella Laurenzo
267bb194f3 [mlir] Remove old "tc" linalg ods generator.
* This could have been removed some time ago as it only had one op left in it, which is redundant with the new approach.
* `matmul_i8_i8_i32` (the remaining op) can be trivially replaced by `matmul`, which natively supports mixed precision.

Differential Revision: https://reviews.llvm.org/D110792
2021-09-30 16:30:06 +00:00
MaheshRavishankar
4aeeb91a92 [mlir][Linalg] Allow all build methods of Structured ops to specify additional attributes.
Differential Revision: https://reviews.llvm.org/D108338
2021-08-23 13:06:34 -07:00
MaheshRavishankar
16ffb283c5 Revert "[mlir][Linalg] Allow all build methods of Structured ops to specify additional attributes."
This reverts commit 95ddc8341ae2c27229ad3dcf1d55abebcec15d02.

Differential Revision: https://reviews.llvm.org/D108396
2021-08-19 11:53:41 -07:00
MaheshRavishankar
95ddc8341a [mlir][Linalg] Allow all build methods of Structured ops to specify additional attributes.
Differential Revision: https://reviews.llvm.org/D108338
2021-08-19 11:14:35 -07:00
Tobias Gysi
234c4d2362 [mlir][linalg] Set result types in all builders.
Add code to set the result types in all yaml op builders.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D108273
2021-08-19 06:19:12 +00:00
Tobias Gysi
bbf4436a82 [mlir][linalg] Remove the StructuredOp capture mechanism.
After https://reviews.llvm.org/D104109, structured ops support scalar inputs. As a result, the capture mechanism meant to pass non-shaped parameters got redundant. The patch removes the capture semantics after the FillOp migrated to use scalar operands https://reviews.llvm.org/D104121.

Differential Revision: https://reviews.llvm.org/D104785
2021-06-28 07:57:40 +00:00
Tobias Gysi
25bb616490 [mlir][linalg][python] Add attribute support to the YAML codegen.
Extend the yaml code generation to support the index attributes that https://reviews.llvm.org/D104711 added to the OpDSL.

Differential Revision: https://reviews.llvm.org/D104712
2021-06-24 12:33:48 +00:00
Tobias Gysi
ff2ef4d684 [mlir][linalg] Adapt yaml codegen to support scalar parameters.
The patch updates the C++ yaml code generation to support scalar operands as added in https://reviews.llvm.org/D104220.

Differential Revision: https://reviews.llvm.org/D104224
2021-06-15 15:20:48 +00:00
Nicolas Vasilache
4519ca3d2e [mlir][Linalg] NFC - Drop Linalg EDSC usage
Drop the Linalg dialect EDSC subdirectory and update all uses.

Differential Revision: https://reviews.llvm.org/D102848
2021-05-20 15:33:56 +00:00
Tobias Gysi
9a2769db80 [mir][Python][linalg] Support OpDSL extensions in C++.
The patch extends the yaml code generation to support the following new OpDSL constructs:
- captures
- constants
- iteration index accesses
- predefined types
These changes have been introduced by revision
https://reviews.llvm.org/D101364.

Differential Revision: https://reviews.llvm.org/D102075
2021-05-19 13:36:56 +00:00
Hanhan Wang
d5d4fb635e [mlir][linalg] Add support for using scalar attributes in TC ops.
Reviewed By: antiagainst

Differential Revision: https://reviews.llvm.org/D97876
2021-03-10 01:51:12 -08:00
Alex Zinenko
32c49c7d73 [mlir] ODS: change OpBuilderDAG to OpBuilder
We no longer have the non-DAG version.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D97856
2021-03-04 10:55:02 +01:00
Hanhan Wang
497b7b8c00 [mlir][linalg] Delete unused vars if there are shaped-only operands.
Reviewed By: stella.stamenova

Differential Revision: https://reviews.llvm.org/D97851
2021-03-03 09:36:08 -08:00
Hanhan Wang
c0f8115c73 [mlir][linalg] Only generate one var for an attrUse.
Some variables are unused after D97383 landed. We should generate one symbol for one attrUse.

Reviewed By: stellaraccident

Differential Revision: https://reviews.llvm.org/D97794
2021-03-02 12:48:20 -08:00
Hanhan Wang
855a119604 [mlir][linalg] Allow TC ops taking an unused shaped operand.
If one operand is not used in the formula, it will be considered a
shaped operand. And the result of indexing map of the operand will be the first
reduction dims.

Depends On D97383

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D97384
2021-02-26 06:45:56 -08:00
Hanhan Wang
21895a2bef [mlir][linalg] Reuse the symbol if attribute uses are identical.
Depends On D97312

Reviewed By: antiagainst

Differential Revision: https://reviews.llvm.org/D97383
2021-02-24 11:42:13 -08:00
Hanhan Wang
705068cb8c [mlir][linalg] Support for using output values in TC definitions.
This will allow us to define select(pred, in, out) for TC ops, which is useful
for pooling ops.

Reviewed By: antiagainst

Differential Revision: https://reviews.llvm.org/D97312
2021-02-24 11:37:45 -08:00
Mehdi Amini
aa4e466caa [mlir][Linalg] Improve region support in Linalg ops
This revision takes advantage of the newly extended `ref` directive in assembly format
to allow better region handling for LinalgOps. Specifically, FillOp and CopyOp now build their regions explicitly which allows retiring older behavior that relied on specific op knowledge in both lowering to loops and vectorization.

This reverts commit 3f22547fd1 and reland 973e133b769 with a workaround for
a gcc bug that does not accept lambda default parameters:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59949

Differential Revision: https://reviews.llvm.org/D96598
2021-02-12 19:11:24 +00:00
Mehdi Amini
3f22547fd1 Revert "[mlir][Linalg] Improve region support in Linalg ops."
This reverts commit 973e133b769773c89ce4b8bbfd6c77612d2ff9d4.

It triggers an issue in gcc5 that require investigation, the build is
broken with:

/tmp/ccdpj3B9.s: Assembler messages:
/tmp/ccdpj3B9.s:5821: Error: symbol `_ZNSt17_Function_handlerIFvjjEUljjE2_E9_M_invokeERKSt9_Any_dataOjS6_' is already defined
/tmp/ccdpj3B9.s:5860: Error: symbol `_ZNSt14_Function_base13_Base_managerIUljjE2_E10_M_managerERSt9_Any_dataRKS3_St18_Manager_operation' is already defined
2021-02-12 18:15:51 +00:00
Nicolas Vasilache
973e133b76 [mlir][Linalg] Improve region support in Linalg ops.
This revision takes advantage of the newly extended `ref` directive in assembly format
to allow better region handling for LinalgOps. Specifically, FillOp and CopyOp now build their regions explicitly which allows retiring older behavior that relied on specific op knowledge in both lowering to loops and vectorization.

Differential Revision: https://reviews.llvm.org/D96598
2021-02-12 14:51:03 +00:00
Lei Zhang
4c640e49c9 [mlir][linalg] Verify indexing map required attributes
Indexing maps for named ops can reference attributes so that
we can synthesize the indexing map dynamically. This supports
cases like strides for convolution ops. However, it does cause
an issue: now the indexing_maps() function call is dependent
on those attributes.

Linalg ops inherit LinalgOpInterfaceTraits, which calls
verifyStructuredOpInterface() to verify the interface.
verifyStructuredOpInterface() further calls indexing_maps().
Note that trait verification is done before the op itself,
where ODS generates the verification for those attributes.
So we can have indexing_maps() referencing non-existing or
invalid attribute, before the ODS-generated verification
kick in.

There isn't a dependency handling mechansim for traits.
This commit adds new interface methods to query whether an
op hasDynamicIndexingMaps() and then perform
verifyIndexingMapRequiredAttributes() in
verifyStructuredOpInterface() to handle the dependency issue.

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D96297
2021-02-09 08:48:29 -05:00
Lei Zhang
0acc260b57 [mlir][linalg] Support generating builders for named op attributes
This commit adds support to generate an additional builder for
each named op that has attributes. This gives better experience
when creating the named ops.

Along the way adds support for i64.

Reviewed By: hanchung

Differential Revision: https://reviews.llvm.org/D94733
2021-01-15 09:00:30 -05:00
Lei Zhang
6b9fa8a50d [mlir][linalg] Add docstring support for named op spec
Depends on D94335

Reviewed By: nicolasvasilache, hanchung

Differential Revision: https://reviews.llvm.org/D94548
2021-01-14 09:57:56 -05:00
Lei Zhang
3bc7555ffa [mlir][linalg] Use attributes in named ops' indexing maps
This commit adds support for parsing attribute uses in indexing
maps. These attribute uses are represented as affine symbols in
the resultant indexing maps because we can only know their
concrete value (which are coming from op attributes and are
constants) for specific op instances. The `indxing_maps()`
calls are synthesized to read these attributes and create affine
constants to replace the placeholder affine symbols and simplify.

Depends on D94240

Reviewed By: nicolasvasilache

Differential Revision: https://reviews.llvm.org/D94335
2021-01-13 10:04:49 -05:00