Skip to content

Commit be7352c

Browse files
committed
[mlir][splitting std] move 2 more ops to tensor
- DynamicTensorFromElementsOp - TensorFromElements Differential Revision: https://reviews.llvm.org/D94994
1 parent ce24bb0 commit be7352c

File tree

25 files changed

+740
-763
lines changed

25 files changed

+740
-763
lines changed

mlir/include/mlir/Dialect/StandardOps/IR/Ops.td

Lines changed: 0 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,47 +1591,6 @@ def DivFOp : FloatArithmeticOp<"divf"> {
15911591
let summary = "floating point division operation";
15921592
}
15931593

1594-
//===----------------------------------------------------------------------===//
1595-
// DynamicTensorFromElementsOp
1596-
//===----------------------------------------------------------------------===//
1597-
1598-
def DynamicTensorFromElementsOp : Std_Op<"dynamic_tensor_from_elements",
1599-
[RecursiveSideEffects, SingleBlockImplicitTerminator<"YieldOp">]> {
1600-
string summary = "Creates a dynamically sized tensor from elements";
1601-
string description = [{
1602-
This operation creates a dynamically sized tensor with elements of any type.
1603-
It expects one index operand per dynamic extent of the result tensor.
1604-
1605-
The body region defines the tensor's elements. It takes index operands as
1606-
its region arguments that span the index space. The element at the given
1607-
position is yielded with the `yield` operation (see `YieldOp`). There is
1608-
no defined ordering to the invocations of the body. It is conceptually
1609-
a "parallel map" operation.
1610-
1611-
Example:
1612-
1613-
```mlir
1614-
%tnsr = dynamic_tensor_from_elements %m, %n {
1615-
^bb0(%i : index, %j : index, %k : index):
1616-
...
1617-
yield %elem : f32
1618-
} : tensor<?x3x?f32>
1619-
```
1620-
}];
1621-
1622-
let arguments = (ins Variadic<Index>:$dynamicExtents);
1623-
let results = (outs AnyRankedTensor:$result);
1624-
let regions = (region SizedRegion<1>:$body);
1625-
1626-
let builders = [
1627-
// Build op and populate its body per callback function.
1628-
OpBuilderDAG<(ins "Type":$resultTy, "ValueRange":$dynamicExtents,
1629-
"function_ref<void(OpBuilder &, Location, ValueRange)>")>,
1630-
];
1631-
1632-
let hasCanonicalizer = 1;
1633-
}
1634-
16351594
//===----------------------------------------------------------------------===//
16361595
// ExpOp
16371596
//===----------------------------------------------------------------------===//
@@ -1672,46 +1631,6 @@ def Exp2Op : FloatUnaryOp<"exp2"> {
16721631
let summary = "base-2 exponential of the specified value";
16731632
}
16741633

1675-
//===----------------------------------------------------------------------===//
1676-
// TensorFromElementsOp
1677-
//===----------------------------------------------------------------------===//
1678-
1679-
def TensorFromElementsOp : Std_Op<"tensor_from_elements", [
1680-
NoSideEffect,
1681-
TypesMatchWith<"operand types match result element type",
1682-
"result", "elements", "SmallVector<Type, 2>("
1683-
"$_self.cast<ShapedType>().getDimSize(0), "
1684-
"$_self.cast<ShapedType>().getElementType())">
1685-
]> {
1686-
string summary = "tensor from elements operation.";
1687-
string description = [{
1688-
Create a 1D tensor from a range of same-type arguments.
1689-
1690-
Example:
1691-
1692-
```mlir
1693-
tensor_from_elements(i_1, ..., i_N) : tensor<Nxindex>
1694-
```
1695-
}];
1696-
1697-
let arguments = (ins Variadic<AnyType>:$elements);
1698-
let results = (outs 1DTensorOf<[AnyType]>:$result);
1699-
1700-
let assemblyFormat = "$elements attr-dict `:` type($result)";
1701-
1702-
// This op is fully verified by its traits.
1703-
let verifier = ?;
1704-
1705-
let skipDefaultBuilders = 1;
1706-
let builders = [
1707-
OpBuilderDAG<(ins "Type":$elementType, "ValueRange":$elements)>,
1708-
// Special case builder for when `elements` has size >=1.
1709-
OpBuilderDAG<(ins "ValueRange":$elements)>
1710-
];
1711-
1712-
let hasCanonicalizer = 1;
1713-
}
1714-
17151634
//===----------------------------------------------------------------------===//
17161635
// FPExtOp
17171636
//===----------------------------------------------------------------------===//
@@ -3837,24 +3756,6 @@ def ViewOp : Std_Op<"view", [
38373756
let hasCanonicalizer = 1;
38383757
}
38393758

3840-
//===----------------------------------------------------------------------===//
3841-
// YieldOp
3842-
//===----------------------------------------------------------------------===//
3843-
3844-
def YieldOp : Std_Op<"yield", [NoSideEffect, ReturnLike, Terminator,
3845-
HasParent<"DynamicTensorFromElementsOp">]> {
3846-
let summary = "Yield a value from a region";
3847-
let description = [{
3848-
This operation is used to yield a single value from a within a region. It
3849-
is used to create dynamically sized tensors
3850-
(see `DynamicTensorFromElementsOp`).
3851-
}];
3852-
3853-
let arguments = (ins AnyType:$value);
3854-
let assemblyFormat = "$value attr-dict `:` type($value)";
3855-
let verifier = ?;
3856-
}
3857-
38583759
//===----------------------------------------------------------------------===//
38593760
// XOrOp
38603761
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/Tensor/IR/Tensor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "mlir/IR/Dialect.h"
1414
#include "mlir/IR/OpDefinition.h"
1515
#include "mlir/IR/OpImplementation.h"
16+
#include "mlir/Interfaces/ControlFlowInterfaces.h"
1617
#include "mlir/Interfaces/SideEffectInterfaces.h"
1718

1819
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define TENSOR_OPS
1111

1212
include "mlir/Dialect/Tensor/IR/TensorBase.td"
13+
include "mlir/Interfaces/ControlFlowInterfaces.td"
1314
include "mlir/Interfaces/SideEffectInterfaces.td"
1415

1516
class Tensor_Op<string mnemonic, list<OpTrait> traits = []>
@@ -105,4 +106,109 @@ def Tensor_ExtractOp : Tensor_Op<"extract",
105106
let hasFolder = 1;
106107
}
107108

109+
//===----------------------------------------------------------------------===//
110+
// FromElementsOp
111+
//===----------------------------------------------------------------------===//
112+
113+
def Tensor_FromElementsOp : Tensor_Op<"from_elements", [
114+
NoSideEffect,
115+
TypesMatchWith<"operand types match result element type",
116+
"result", "elements", "SmallVector<Type, 2>("
117+
"$_self.cast<ShapedType>().getDimSize(0), "
118+
"$_self.cast<ShapedType>().getElementType())">
119+
]> {
120+
string summary = "tensor from elements operation.";
121+
string description = [{
122+
Create a 1D tensor from a range of same-type arguments.
123+
124+
Example:
125+
126+
```mlir
127+
tensor.from_elements(i_1, ..., i_N) : tensor<Nxindex>
128+
```
129+
}];
130+
131+
let arguments = (ins Variadic<AnyType>:$elements);
132+
let results = (outs 1DTensorOf<[AnyType]>:$result);
133+
134+
let assemblyFormat = "$elements attr-dict `:` type($result)";
135+
136+
// This op is fully verified by its traits.
137+
let verifier = ?;
138+
139+
let skipDefaultBuilders = 1;
140+
let builders = [
141+
OpBuilderDAG<(ins "Type":$elementType, "ValueRange":$elements)>,
142+
// Special case builder for when `elements` has size >=1.
143+
OpBuilderDAG<(ins "ValueRange":$elements)>
144+
];
145+
146+
let hasCanonicalizer = 1;
147+
}
148+
149+
//===----------------------------------------------------------------------===//
150+
// GenerateOp
151+
//===----------------------------------------------------------------------===//
152+
153+
def Tensor_GenerateOp : Tensor_Op<"generate",
154+
[RecursiveSideEffects,
155+
SingleBlockImplicitTerminator<"mlir::tensor::YieldOp">]> {
156+
string summary = "Creates a dynamically sized tensor from elements";
157+
string description = [{
158+
This operation creates a dynamically sized tensor with elements of any type.
159+
It expects one index operand per dynamic extent of the result tensor.
160+
161+
The body region defines the tensor's elements. It takes index operands as
162+
its region arguments that span the index space. The element at the given
163+
position is yielded with the `yield` operation (see `YieldOp`). There is
164+
no defined ordering to the invocations of the body. It is conceptually
165+
a "parallel map" operation.
166+
167+
Example:
168+
169+
```mlir
170+
%tnsr = tensor.generate %m, %n {
171+
^bb0(%i : index, %j : index, %k : index):
172+
...
173+
yield %elem : f32
174+
} : tensor<?x3x?f32>
175+
```
176+
}];
177+
178+
let arguments = (ins Variadic<Index>:$dynamicExtents);
179+
let results = (outs AnyRankedTensor:$result);
180+
let regions = (region SizedRegion<1>:$body);
181+
let assemblyFormat = "$dynamicExtents $body attr-dict `:` type($result)";
182+
183+
let builders = [
184+
// Build op and populate its body per callback function.
185+
OpBuilderDAG<(ins "Type":$resultTy, "ValueRange":$dynamicExtents,
186+
"function_ref<void(OpBuilder &, Location, ValueRange)>")>,
187+
];
188+
189+
let hasCanonicalizer = 1;
190+
}
191+
192+
//===----------------------------------------------------------------------===//
193+
// YieldOp
194+
//===----------------------------------------------------------------------===//
195+
196+
def Tensor_YieldOp : Tensor_Op<"yield",
197+
[NoSideEffect, ReturnLike, Terminator,
198+
HasParent<"::mlir::tensor::GenerateOp">]> {
199+
let summary = "Yield a value from a region";
200+
let description = [{
201+
This operation is used to yield a single value from a within a region. It
202+
is used to create dynamically sized tensors
203+
(see `tensor.generate` op).
204+
}];
205+
206+
let arguments = (ins AnyType:$value);
207+
let assemblyFormat = "$value attr-dict `:` type($value)";
208+
// Dummy builder to appease code in templated ensureTerminator that
209+
// GenerateOp's auto-generated parser calls.
210+
let builders = [OpBuilderDAG<(ins), [{ /* nothing to do */ }]>];
211+
let verifier = ?;
212+
}
213+
108214
#endif // TENSOR_OPS

mlir/include/mlir/Dialect/Tensor/Transforms/Passes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ include "mlir/Pass/PassBase.td"
1414
def TensorBufferize : FunctionPass<"tensor-bufferize"> {
1515
let summary = "Bufferize the `tensor` dialect";
1616
let constructor = "mlir::createTensorBufferizePass()";
17+
let dependentDialects = ["scf::SCFDialect"];
1718
}
1819

1920
#endif // MLIR_DIALECT_TENSOR_TRANSFORMS_PASSES

mlir/lib/Conversion/ShapeToStandard/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_mlir_conversion_library(MLIRShapeToStandard
2020
MLIREDSC
2121
MLIRIR
2222
MLIRShape
23+
MLIRTensor
2324
MLIRPass
2425
MLIRSCF
2526
MLIRTransforms

mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ LogicalResult BroadcastOpConverter::matchAndRewrite(
113113

114114
Value rankDiff =
115115
rewriter.create<SubIOp>(loc, indexTy, greaterRank, lesserRank);
116-
rewriter.replaceOpWithNewOp<DynamicTensorFromElementsOp>(
116+
rewriter.replaceOpWithNewOp<tensor::GenerateOp>(
117117
op, getExtentTensorType(op.getContext()), ValueRange{greaterRank},
118118
[&](OpBuilder &b, Location loc, ValueRange args) {
119119
Value outputDimension = args[0];
@@ -151,7 +151,7 @@ LogicalResult BroadcastOpConverter::matchAndRewrite(
151151
greaterRankOperandExtent);
152152
b.create<scf::YieldOp>(loc, broadcastedExtent);
153153
});
154-
b.create<mlir::YieldOp>(loc, ifOp.getResult(0));
154+
b.create<tensor::YieldOp>(loc, ifOp.getResult(0));
155155
});
156156
return success();
157157
}
@@ -184,7 +184,7 @@ LogicalResult ConstShapeOpConverter::matchAndRewrite(
184184
}
185185
Type indexTy = rewriter.getIndexType();
186186
Value tensor =
187-
rewriter.create<TensorFromElementsOp>(loc, indexTy, extentOperands);
187+
rewriter.create<tensor::FromElementsOp>(loc, indexTy, extentOperands);
188188
Type resultTy = RankedTensorType::get({ShapedType::kDynamicSize}, indexTy);
189189
rewriter.replaceOpWithNewOp<tensor::CastOp>(op, resultTy, tensor);
190190
return success();
@@ -503,7 +503,7 @@ LogicalResult ShapeOfOpConversion::matchAndRewrite(
503503
if (op.getType().isa<ShapeType>())
504504
return failure();
505505

506-
// For ranked tensor arguments, lower to `tensor_from_elements`.
506+
// For ranked tensor arguments, lower to `tensor.from_elements`.
507507
auto loc = op.getLoc();
508508
ShapeOfOp::Adaptor transformed(operands);
509509
Value tensor = transformed.arg();
@@ -526,22 +526,22 @@ LogicalResult ShapeOfOpConversion::matchAndRewrite(
526526
}
527527

528528
// Materialize extent tensor.
529-
Value staticExtentTensor = rewriter.create<TensorFromElementsOp>(
529+
Value staticExtentTensor = rewriter.create<tensor::FromElementsOp>(
530530
loc, rewriter.getIndexType(), extentValues);
531531
rewriter.replaceOpWithNewOp<tensor::CastOp>(op, op.getType(),
532532
staticExtentTensor);
533533
return success();
534534
}
535535

536-
// Lower to `dynamic_tensor_from_elements` otherwise.
536+
// Lower to `tensor.generate` otherwise.
537537
auto *ctx = rewriter.getContext();
538538
Value rank = rewriter.create<mlir::RankOp>(loc, tensor);
539-
rewriter.replaceOpWithNewOp<DynamicTensorFromElementsOp>(
539+
rewriter.replaceOpWithNewOp<tensor::GenerateOp>(
540540
op, getExtentTensorType(ctx), ValueRange{rank},
541541
[&](OpBuilder &b, Location loc, ValueRange args) {
542542
Value dim = args.front();
543543
Value extent = b.create<DimOp>(loc, tensor, dim);
544-
b.create<mlir::YieldOp>(loc, extent);
544+
b.create<tensor::YieldOp>(loc, extent);
545545
});
546546

547547
return success();

0 commit comments

Comments
 (0)