Skip to content

Commit a2426eb

Browse files
committed
[mlir][emitc] Add div, mul and rem operators
This adds operations for binary multiplicative arithmetic operators to EmitC. The input and output arguments for the remainder operator are restricted to index (emitted as size_t), integers and the EmitC opaque types (as the operator can be overloaded for a custom type). The multiplication and division operator further support floating point numbers. Reviewed By: jpienaar Differential Revision: https://reviews.llvm.org/D154846
1 parent 60c9d29 commit a2426eb

File tree

5 files changed

+176
-4
lines changed

5 files changed

+176
-4
lines changed

mlir/include/mlir/Dialect/EmitC/IR/EmitC.td

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ class EmitC_BinaryArithOp<string mnemonic, list<Trait> traits = []> :
3333
let arguments = (ins AnyType:$lhs, AnyType:$rhs);
3434
let results = (outs AnyType);
3535
let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)";
36-
37-
let hasVerifier = 1;
3836
}
3937

38+
// Types only used in binary arithmetic operations.
39+
def IntegerIndexOrOpaqueType : AnyTypeOf<[AnyInteger, Index, EmitC_OpaqueType]>;
40+
def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[AnyFloat, IntegerIndexOrOpaqueType]>;
41+
4042
def EmitC_AddOp : EmitC_BinaryArithOp<"add", []> {
4143
let summary = "Addition operation";
4244
let description = [{
@@ -56,6 +58,8 @@ def EmitC_AddOp : EmitC_BinaryArithOp<"add", []> {
5658
float* v6 = v3 + v4;
5759
```
5860
}];
61+
62+
let hasVerifier = 1;
5963
}
6064

6165
def EmitC_ApplyOp : EmitC_Op<"apply", []> {
@@ -176,6 +180,30 @@ def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
176180
let hasVerifier = 1;
177181
}
178182

183+
def EmitC_DivOp : EmitC_BinaryArithOp<"div", []> {
184+
let summary = "Division operation";
185+
let description = [{
186+
With the `div` operation the arithmetic operator / (division) can
187+
be applied.
188+
189+
Example:
190+
191+
```mlir
192+
// Custom form of the division operation.
193+
%0 = emitc.div %arg0, %arg1 : (i32, i32) -> i32
194+
%1 = emitc.div %arg2, %arg3 : (f32, f32) -> f32
195+
```
196+
```c++
197+
// Code emitted for the operations above.
198+
int32_t v5 = v1 / v2;
199+
float v6 = v3 / v4;
200+
```
201+
}];
202+
203+
let arguments = (ins FloatIntegerIndexOrOpaqueType, FloatIntegerIndexOrOpaqueType);
204+
let results = (outs FloatIntegerIndexOrOpaqueType);
205+
}
206+
179207
def EmitC_IncludeOp
180208
: EmitC_Op<"include", [HasParent<"ModuleOp">]> {
181209
let summary = "Include operation";
@@ -206,6 +234,52 @@ def EmitC_IncludeOp
206234
let hasCustomAssemblyFormat = 1;
207235
}
208236

237+
def EmitC_MulOp : EmitC_BinaryArithOp<"mul", []> {
238+
let summary = "Multiplication operation";
239+
let description = [{
240+
With the `mul` operation the arithmetic operator * (multiplication) can
241+
be applied.
242+
243+
Example:
244+
245+
```mlir
246+
// Custom form of the multiplication operation.
247+
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
248+
%1 = emitc.mul %arg2, %arg3 : (f32, f32) -> f32
249+
```
250+
```c++
251+
// Code emitted for the operations above.
252+
int32_t v5 = v1 * v2;
253+
float v6 = v3 * v4;
254+
```
255+
}];
256+
257+
let arguments = (ins FloatIntegerIndexOrOpaqueType, FloatIntegerIndexOrOpaqueType);
258+
let results = (outs FloatIntegerIndexOrOpaqueType);
259+
}
260+
261+
def EmitC_RemOp : EmitC_BinaryArithOp<"rem", []> {
262+
let summary = "Remainder operation";
263+
let description = [{
264+
With the `rem` operation the arithmetic operator % (remainder) can
265+
be applied.
266+
267+
Example:
268+
269+
```mlir
270+
// Custom form of the remainder operation.
271+
%0 = emitc.rem %arg0, %arg1 : (i32, i32) -> i32
272+
```
273+
```c++
274+
// Code emitted for the operation above.
275+
int32_t v5 = v1 % v2;
276+
```
277+
}];
278+
279+
let arguments = (ins IntegerIndexOrOpaqueType, IntegerIndexOrOpaqueType);
280+
let results = (outs IntegerIndexOrOpaqueType);
281+
}
282+
209283
def EmitC_SubOp : EmitC_BinaryArithOp<"sub", []> {
210284
let summary = "Subtraction operation";
211285
let description = [{
@@ -228,6 +302,8 @@ def EmitC_SubOp : EmitC_BinaryArithOp<"sub", []> {
228302
ptrdiff_t v9 = v5 - v6;
229303
```
230304
}];
305+
306+
let hasVerifier = 1;
231307
}
232308

233309
def EmitC_VariableOp : EmitC_Op<"variable", []> {

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,24 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::AddOp addOp) {
266266
return printBinaryArithOperation(emitter, operation, "+");
267267
}
268268

269+
static LogicalResult printOperation(CppEmitter &emitter, emitc::DivOp divOp) {
270+
Operation *operation = divOp.getOperation();
271+
272+
return printBinaryArithOperation(emitter, operation, "/");
273+
}
274+
275+
static LogicalResult printOperation(CppEmitter &emitter, emitc::MulOp mulOp) {
276+
Operation *operation = mulOp.getOperation();
277+
278+
return printBinaryArithOperation(emitter, operation, "*");
279+
}
280+
281+
static LogicalResult printOperation(CppEmitter &emitter, emitc::RemOp remOp) {
282+
Operation *operation = remOp.getOperation();
283+
284+
return printBinaryArithOperation(emitter, operation, "%");
285+
}
286+
269287
static LogicalResult printOperation(CppEmitter &emitter, emitc::SubOp subOp) {
270288
Operation *operation = subOp.getOperation();
271289

@@ -957,8 +975,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
957975
[&](auto op) { return printOperation(*this, op); })
958976
// EmitC ops.
959977
.Case<emitc::AddOp, emitc::ApplyOp, emitc::CallOp, emitc::CastOp,
960-
emitc::ConstantOp, emitc::IncludeOp, emitc::SubOp,
961-
emitc::VariableOp>(
978+
emitc::ConstantOp, emitc::DivOp, emitc::IncludeOp, emitc::MulOp,
979+
emitc::RemOp, emitc::SubOp, emitc::VariableOp>(
962980
[&](auto op) { return printOperation(*this, op); })
963981
// Func ops.
964982
.Case<func::CallOp, func::ConstantOp, func::FuncOp, func::ReturnOp>(

mlir/test/Dialect/EmitC/invalid_ops.mlir

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,38 @@ func.func @add_float_pointer(%arg0: f32, %arg1: !emitc.ptr<f32>) {
145145

146146
// -----
147147

148+
func.func @div_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) {
149+
// expected-error @+1 {{'emitc.div' op operand #0 must be floating-point or integer or index or EmitC opaque type, but got 'tensor<i32>'}}
150+
%1 = "emitc.div" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
151+
return
152+
}
153+
154+
// -----
155+
156+
func.func @mul_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) {
157+
// expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point or integer or index or EmitC opaque type, but got 'tensor<i32>'}}
158+
%1 = "emitc.mul" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
159+
return
160+
}
161+
162+
// -----
163+
164+
func.func @rem_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) {
165+
// expected-error @+1 {{'emitc.rem' op operand #0 must be integer or index or EmitC opaque type, but got 'tensor<i32>'}}
166+
%1 = "emitc.rem" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
167+
return
168+
}
169+
170+
// -----
171+
172+
func.func @rem_float(%arg0: f32, %arg1: f32) {
173+
// expected-error @+1 {{'emitc.rem' op operand #0 must be integer or index or EmitC opaque type, but got 'f32'}}
174+
%1 = "emitc.rem" (%arg0, %arg1) : (f32, f32) -> f32
175+
return
176+
}
177+
178+
// -----
179+
148180
func.func @sub_int_pointer(%arg0: i32, %arg1: !emitc.ptr<f32>) {
149181
// expected-error @+1 {{'emitc.sub' op rhs can only be a pointer if lhs is a pointer}}
150182
%1 = "emitc.sub" (%arg0, %arg1) : (i32, !emitc.ptr<f32>) -> !emitc.ptr<f32>

mlir/test/Dialect/EmitC/ops.mlir

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,31 @@ func.func @add_pointer(%arg0: !emitc.ptr<f32>, %arg1: i32, %arg2: !emitc.opaque<
4242
return
4343
}
4444

45+
func.func @div_int(%arg0: i32, %arg1: i32) {
46+
%1 = "emitc.div" (%arg0, %arg1) : (i32, i32) -> i32
47+
return
48+
}
49+
50+
func.func @div_float(%arg0: f32, %arg1: f32) {
51+
%1 = "emitc.div" (%arg0, %arg1) : (f32, f32) -> f32
52+
return
53+
}
54+
55+
func.func @mul_int(%arg0: i32, %arg1: i32) {
56+
%1 = "emitc.mul" (%arg0, %arg1) : (i32, i32) -> i32
57+
return
58+
}
59+
60+
func.func @mul_float(%arg0: f32, %arg1: f32) {
61+
%1 = "emitc.mul" (%arg0, %arg1) : (f32, f32) -> f32
62+
return
63+
}
64+
65+
func.func @rem(%arg0: i32, %arg1: i32) {
66+
%1 = "emitc.rem" (%arg0, %arg1) : (i32, i32) -> i32
67+
return
68+
}
69+
4570
func.func @sub_int(%arg0: i32, %arg1: i32) {
4671
%1 = "emitc.sub" (%arg0, %arg1) : (i32, i32) -> i32
4772
return

mlir/test/Target/Cpp/arithmetic_operators.mlir

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,27 @@ func.func @add_pointer(%arg0: !emitc.ptr<f32>, %arg1: i32) {
1414
// CHECK-LABEL: void add_pointer
1515
// CHECK-NEXT: float* [[V2:[^ ]*]] = [[V0:[^ ]*]] + [[V1:[^ ]*]]
1616

17+
func.func @div_int(%arg0: i32, %arg1: i32) {
18+
%1 = "emitc.div" (%arg0, %arg1) : (i32, i32) -> i32
19+
return
20+
}
21+
// CHECK-LABEL: void div_int
22+
// CHECK-NEXT: int32_t [[V2:[^ ]*]] = [[V0:[^ ]*]] / [[V1:[^ ]*]]
23+
24+
func.func @mul_int(%arg0: i32, %arg1: i32) {
25+
%1 = "emitc.mul" (%arg0, %arg1) : (i32, i32) -> i32
26+
return
27+
}
28+
// CHECK-LABEL: void mul_int
29+
// CHECK-NEXT: int32_t [[V2:[^ ]*]] = [[V0:[^ ]*]] * [[V1:[^ ]*]]
30+
31+
func.func @rem(%arg0: i32, %arg1: i32) {
32+
%1 = "emitc.rem" (%arg0, %arg1) : (i32, i32) -> i32
33+
return
34+
}
35+
// CHECK-LABEL: void rem
36+
// CHECK-NEXT: int32_t [[V2:[^ ]*]] = [[V0:[^ ]*]] % [[V1:[^ ]*]]
37+
1738
func.func @sub_int(%arg0: i32, %arg1: i32) {
1839
%1 = "emitc.sub" (%arg0, %arg1) : (i32, i32) -> i32
1940
return

0 commit comments

Comments
 (0)