Skip to content
This repository was archived by the owner on Apr 23, 2021. It is now read-only.

Commit 67c7ea4

Browse files
Add vector.insertelement op
This is the counterpart of vector.extractelement op and has the same limitations at the moment (static I64IntegerArrayAttr to express position). This restriction will be filterd in the future. LLVM lowering will be added in a subsequent commit. PiperOrigin-RevId: 282365760
1 parent 970dd6b commit 67c7ea4

5 files changed

Lines changed: 161 additions & 5 deletions

File tree

include/mlir/Dialect/VectorOps/VectorOps.td

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,40 @@ def Vector_ExtractElementOp :
169169
}];
170170
}
171171

172+
def Vector_InsertElementOp :
173+
Vector_Op<"insertelement", [NoSideEffect,
174+
PredOpTrait<"source operand and result have same element type",
175+
TCresVTEtIsSameAsOpBase<0, 0>>,
176+
PredOpTrait<"dest operand and result have same type",
177+
TCresIsSameAsOpBase<0, 1>>]>,
178+
Arguments<(ins AnyType:$source, AnyVector:$dest, I32ArrayAttr:$position)>,
179+
Results<(outs AnyVector)> {
180+
let summary = "insertelement operation";
181+
let description = [{
182+
Takes an n-D source vector, an (n+k)-D destination vector and a k-D position
183+
and inserts the n-D source into the (n+k)-D destination at the proper
184+
position. Degenerates to a scalar source type when n = 0.
185+
186+
Examples:
187+
```
188+
%2 = vector.insertelement %0, %1[3 : i32]:
189+
vector<8x16xf32> into vector<4x8x16xf32>
190+
%5 = vector.insertelement %3, %4[3 : i32, 3 : i32, 3 : i32]:
191+
f32 into vector<4x8x16xf32>
192+
```
193+
}];
194+
let builders = [OpBuilder<
195+
"Builder *builder, OperationState &result, Value *source, " #
196+
"Value *dest, ArrayRef<int32_t>">];
197+
let extraClassDeclaration = [{
198+
static StringRef getPositionAttrName() { return "position"; }
199+
Type getSourceType() { return source()->getType(); }
200+
VectorType getDestVectorType() {
201+
return dest()->getType().cast<VectorType>();
202+
}
203+
}];
204+
}
205+
172206
def Vector_StridedSliceOp :
173207
Vector_Op<"strided_slice", [NoSideEffect,
174208
PredOpTrait<"operand and result have same element type",

include/mlir/IR/OpBase.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,12 @@ class TCOpResIsShapedTypePred<int i, int j> : And<[
16681668
SubstLeaves<"$_self", "$_op.getOperand(" # j # ")->getType()",
16691669
IsShapedTypePred>]>;
16701670

1671+
// Predicate to verify that the i'th result and the j'th operand have the same
1672+
// type.
1673+
class TCresIsSameAsOpBase<int i, int j> :
1674+
CPred<"$_op.getResult(" # i # ")->getType() == "
1675+
"$_op.getOperand(" # j # ")->getType()">;
1676+
16711677
// Basic Predicate to verify that the i'th result and the j'th operand have the
16721678
// same elemental type.
16731679
class TCresVTEtIsSameAsOpBase<int i, int j> :

lib/Dialect/VectorOps/VectorOps.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,12 +291,84 @@ static LogicalResult verify(ExtractElementOp op) {
291291
attr.getInt() > op.getVectorType().getDimSize(en.index()))
292292
return op.emitOpError("expected position attribute #")
293293
<< (en.index() + 1)
294-
<< " to be a positive integer smaller than the corresponding "
294+
<< " to be a non-negative integer smaller than the corresponding "
295295
"vector dimension";
296296
}
297297
return success();
298298
}
299299

300+
//===----------------------------------------------------------------------===//
301+
// InsertElementOp
302+
//===----------------------------------------------------------------------===//
303+
304+
void InsertElementOp::build(Builder *builder, OperationState &result,
305+
Value *source, Value *dest,
306+
ArrayRef<int32_t> position) {
307+
result.addOperands({source, dest});
308+
auto positionAttr = builder->getI32ArrayAttr(position);
309+
result.addTypes(dest->getType());
310+
result.addAttribute(getPositionAttrName(), positionAttr);
311+
}
312+
313+
static void print(OpAsmPrinter &p, InsertElementOp op) {
314+
p << op.getOperationName() << " " << *op.source() << ", " << *op.dest()
315+
<< op.position();
316+
p.printOptionalAttrDict(op.getAttrs(),
317+
{InsertElementOp::getPositionAttrName()});
318+
p << " : " << op.getSourceType();
319+
p << " into " << op.getDestVectorType();
320+
}
321+
322+
static ParseResult parseInsertElementOp(OpAsmParser &parser,
323+
OperationState &result) {
324+
SmallVector<NamedAttribute, 4> attrs;
325+
OpAsmParser::OperandType source, dest;
326+
Type sourceType;
327+
VectorType destType;
328+
Attribute attr;
329+
return failure(parser.parseOperand(source) || parser.parseComma() ||
330+
parser.parseOperand(dest) ||
331+
parser.parseAttribute(attr,
332+
InsertElementOp::getPositionAttrName(),
333+
result.attributes) ||
334+
parser.parseOptionalAttrDict(attrs) ||
335+
parser.parseColonType(sourceType) ||
336+
parser.parseKeywordType("into", destType) ||
337+
parser.resolveOperand(source, sourceType, result.operands) ||
338+
parser.resolveOperand(dest, destType, result.operands) ||
339+
parser.addTypeToList(destType, result.types));
340+
}
341+
342+
static LogicalResult verify(InsertElementOp op) {
343+
auto positionAttr = op.position().getValue();
344+
if (positionAttr.empty())
345+
return op.emitOpError("expected non-empty position attribute");
346+
auto destVectorType = op.getDestVectorType();
347+
if (positionAttr.size() > static_cast<unsigned>(destVectorType.getRank()))
348+
return op.emitOpError(
349+
"expected position attribute of rank smaller than dest vector rank");
350+
auto srcVectorType = op.getSourceType().dyn_cast<VectorType>();
351+
if (srcVectorType &&
352+
(static_cast<unsigned>(srcVectorType.getRank()) + positionAttr.size() !=
353+
static_cast<unsigned>(destVectorType.getRank())))
354+
return op.emitOpError("expected position attribute rank + source rank to "
355+
"match dest vector rank");
356+
else if (!srcVectorType && (positionAttr.size() !=
357+
static_cast<unsigned>(destVectorType.getRank())))
358+
return op.emitOpError(
359+
"expected position attribute rank to match the dest vector rank");
360+
for (auto en : llvm::enumerate(positionAttr)) {
361+
auto attr = en.value().dyn_cast<IntegerAttr>();
362+
if (!attr || attr.getInt() < 0 ||
363+
attr.getInt() > destVectorType.getDimSize(en.index()))
364+
return op.emitOpError("expected position attribute #")
365+
<< (en.index() + 1)
366+
<< " to be a non-negative integer smaller than the corresponding "
367+
"dest vector dimension";
368+
}
369+
return success();
370+
}
371+
300372
//===----------------------------------------------------------------------===//
301373
// StridedSliceOp
302374
//===----------------------------------------------------------------------===//

test/Dialect/VectorOps/invalid.mlir

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,54 @@ func @extractelement_position_rank_overflow_generic(%arg0: vector<4x8x16xf32>) {
3131
// -----
3232

3333
func @extractelement_position_overflow(%arg0: vector<4x8x16xf32>) {
34-
// expected-error@+1 {{expected position attribute #2 to be a positive integer smaller than the corresponding vector dimension}}
34+
// expected-error@+1 {{expected position attribute #2 to be a non-negative integer smaller than the corresponding vector dimension}}
3535
%1 = vector.extractelement %arg0[0 : i32, 43 : i32, 0 : i32] : vector<4x8x16xf32>
3636
}
3737

3838
// -----
3939

4040
func @extractelement_position_overflow(%arg0: vector<4x8x16xf32>) {
41-
// expected-error@+1 {{expected position attribute #3 to be a positive integer smaller than the corresponding vector dimension}}
41+
// expected-error@+1 {{expected position attribute #3 to be a non-negative integer smaller than the corresponding vector dimension}}
4242
%1 = vector.extractelement %arg0[0 : i32, 0 : i32, -1 : i32] : vector<4x8x16xf32>
4343
}
4444

4545
// -----
4646

47+
func @insert_element_vector_type(%a: f32, %b: vector<4x8x16xf32>) {
48+
// expected-error@+1 {{expected non-empty position attribute}}
49+
%1 = vector.insertelement %a, %b[] : f32 into vector<4x8x16xf32>
50+
}
51+
52+
// -----
53+
54+
func @insert_element_vector_type(%a: f32, %b: vector<4x8x16xf32>) {
55+
// expected-error@+1 {{expected position attribute of rank smaller than dest vector rank}}
56+
%1 = vector.insertelement %a, %b[3 : i32,3 : i32,3 : i32,3 : i32,3 : i32,3 : i32] : f32 into vector<4x8x16xf32>
57+
}
58+
59+
// -----
60+
61+
func @insert_element_vector_type(%a: vector<4xf32>, %b: vector<4x8x16xf32>) {
62+
// expected-error@+1 {{expected position attribute rank + source rank to match dest vector rank}}
63+
%1 = vector.insertelement %a, %b[3 : i32] : vector<4xf32> into vector<4x8x16xf32>
64+
}
65+
66+
// -----
67+
68+
func @insert_element_vector_type(%a: f32, %b: vector<4x8x16xf32>) {
69+
// expected-error@+1 {{expected position attribute rank to match the dest vector rank}}
70+
%1 = vector.insertelement %a, %b[3 : i32,3 : i32] : f32 into vector<4x8x16xf32>
71+
}
72+
73+
// -----
74+
75+
func @insertelement_position_overflow(%a: f32, %b: vector<4x8x16xf32>) {
76+
// expected-error@+1 {{expected position attribute #3 to be a non-negative integer smaller than the corresponding dest vector dimension}}
77+
%1 = vector.insertelement %a, %b[0 : i32, 0 : i32, -1 : i32] : f32 into vector<4x8x16xf32>
78+
}
79+
80+
// -----
81+
4782
func @outerproduct_num_operands(%arg0: f32) {
4883
// expected-error@+1 {{expected at least 2 operands}}
4984
%1 = vector.outerproduct %arg0 : f32, f32
@@ -369,5 +404,3 @@ func @contraction(%arg0: vector<7x8x16x15xf32>, %arg1: vector<8x16x7x5xf32>,
369404
: vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x15x5xf32>
370405
return
371406
}
372-
373-

test/Dialect/VectorOps/ops.mlir

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ func @extractelement(%arg0: vector<4x8x16xf32>) -> (vector<8x16xf32>, vector<16x
3333
return %1, %2, %3 : vector<8x16xf32>, vector<16xf32>, f32
3434
}
3535

36+
// CHECK-LABEL: insertelement
37+
func @insertelement(%a: f32, %b: vector<16xf32>, %c: vector<8x16xf32>, %res: vector<4x8x16xf32>) {
38+
// CHECK: vector.insertelement %{{.*}}, %{{.*}}[3 : i32] : vector<8x16xf32> into vector<4x8x16xf32>
39+
%1 = vector.insertelement %c, %res[3 : i32] : vector<8x16xf32> into vector<4x8x16xf32>
40+
// CHECK: vector.insertelement %{{.*}}, %{{.*}}[3 : i32, 3 : i32] : vector<16xf32> into vector<4x8x16xf32>
41+
%2 = vector.insertelement %b, %res[3 : i32, 3 : i32] : vector<16xf32> into vector<4x8x16xf32>
42+
// CHECK: vector.insertelement %{{.*}}, %{{.*}}[3 : i32, 3 : i32, 3 : i32] : f32 into vector<4x8x16xf32>
43+
%3 = vector.insertelement %a, %res[3 : i32, 3 : i32, 3 : i32] : f32 into vector<4x8x16xf32>
44+
return
45+
}
46+
3647
// CHECK-LABEL: outerproduct
3748
func @outerproduct(%arg0: vector<4xf32>, %arg1: vector<8xf32>, %arg2: vector<4x8xf32>) -> vector<4x8xf32> {
3849
// CHECK: vector.outerproduct {{.*}} : vector<4xf32>, vector<8xf32>

0 commit comments

Comments
 (0)