Skip to content

Commit b81bb0e

Browse files
authored
[mlir][EmitC] Add logical operators (#83123)
This adds operations for the logical operators AND, NOT and OR.
1 parent 21c7bc5 commit b81bb0e

File tree

5 files changed

+138
-1
lines changed

5 files changed

+138
-1
lines changed

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,70 @@ def EmitC_LiteralOp : EmitC_Op<"literal", [Pure]> {
658658
let assemblyFormat = "$value attr-dict `:` type($result)";
659659
}
660660

661+
def EmitC_LogicalAndOp : EmitC_BinaryOp<"logical_and", []> {
662+
let summary = "Logical and operation";
663+
let description = [{
664+
With the `logical_and` operation the logical operator && (and) can
665+
be applied.
666+
667+
Example:
668+
669+
```mlir
670+
%0 = emitc.logical_and %arg0, %arg1 : i32, i32
671+
```
672+
```c++
673+
// Code emitted for the operation above.
674+
bool v3 = v1 && v2;
675+
```
676+
}];
677+
678+
let results = (outs I1);
679+
let assemblyFormat = "operands attr-dict `:` type(operands)";
680+
}
681+
682+
def EmitC_LogicalNotOp : EmitC_Op<"logical_not", []> {
683+
let summary = "Logical not operation";
684+
let description = [{
685+
With the `logical_not` operation the logical operator ! (negation) can
686+
be applied.
687+
688+
Example:
689+
690+
```mlir
691+
%0 = emitc.logical_not %arg0 : i32
692+
```
693+
```c++
694+
// Code emitted for the operation above.
695+
bool v2 = !v1;
696+
```
697+
}];
698+
699+
let arguments = (ins AnyType);
700+
let results = (outs I1);
701+
let assemblyFormat = "operands attr-dict `:` type(operands)";
702+
}
703+
704+
def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", []> {
705+
let summary = "Logical or operation";
706+
let description = [{
707+
With the `logical_or` operation the logical operator || (inclusive or)
708+
can be applied.
709+
710+
Example:
711+
712+
```mlir
713+
%0 = emitc.logical_or %arg0, %arg1 : i32, i32
714+
```
715+
```c++
716+
// Code emitted for the operation above.
717+
bool v3 = v1 || v2;
718+
```
719+
}];
720+
721+
let results = (outs I1);
722+
let assemblyFormat = "operands attr-dict `:` type(operands)";
723+
}
724+
661725
def EmitC_MulOp : EmitC_BinaryOp<"mul", []> {
662726
let summary = "Multiplication operation";
663727
let description = [{

mlir/lib/Target/Cpp/TranslateToCpp.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,33 @@ static LogicalResult printOperation(CppEmitter &emitter,
627627
return success();
628628
}
629629

630+
static LogicalResult printOperation(CppEmitter &emitter,
631+
emitc::LogicalAndOp logicalAndOp) {
632+
Operation *operation = logicalAndOp.getOperation();
633+
return printBinaryOperation(emitter, operation, "&&");
634+
}
635+
636+
static LogicalResult printOperation(CppEmitter &emitter,
637+
emitc::LogicalNotOp logicalNotOp) {
638+
raw_ostream &os = emitter.ostream();
639+
640+
if (failed(emitter.emitAssignPrefix(*logicalNotOp.getOperation())))
641+
return failure();
642+
643+
os << "!";
644+
645+
if (failed(emitter.emitOperand(logicalNotOp.getOperand())))
646+
return failure();
647+
648+
return success();
649+
}
650+
651+
static LogicalResult printOperation(CppEmitter &emitter,
652+
emitc::LogicalOrOp logicalOrOp) {
653+
Operation *operation = logicalOrOp.getOperation();
654+
return printBinaryOperation(emitter, operation, "||");
655+
}
656+
630657
static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {
631658

632659
raw_indented_ostream &os = emitter.ostream();
@@ -1284,7 +1311,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
12841311
emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
12851312
emitc::ConstantOp, emitc::DeclareFuncOp, emitc::DivOp,
12861313
emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp, emitc::IfOp,
1287-
emitc::IncludeOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp,
1314+
emitc::IncludeOp, emitc::LogicalAndOp, emitc::LogicalNotOp,
1315+
emitc::LogicalOrOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp,
12881316
emitc::SubOp, emitc::VariableOp, emitc::VerbatimOp>(
12891317
[&](auto op) { return printOperation(*this, op); })
12901318
// Func ops.

mlir/test/Dialect/EmitC/invalid_ops.mlir

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,27 @@ emitc.declare_func @bar
331331

332332
// expected-error@+1 {{'emitc.declare_func' op requires attribute 'sym_name'}}
333333
"emitc.declare_func"() : () -> ()
334+
335+
// -----
336+
337+
func.func @logical_and_resulterror(%arg0: i32, %arg1: i32) {
338+
// expected-error @+1 {{'emitc.logical_and' op result #0 must be 1-bit signless integer, but got 'i32'}}
339+
%0 = "emitc.logical_and"(%arg0, %arg1) : (i32, i32) -> i32
340+
return
341+
}
342+
343+
// -----
344+
345+
func.func @logical_not_resulterror(%arg0: i32) {
346+
// expected-error @+1 {{'emitc.logical_not' op result #0 must be 1-bit signless integer, but got 'i32'}}
347+
%0 = "emitc.logical_not"(%arg0) : (i32) -> i32
348+
return
349+
}
350+
351+
// -----
352+
353+
func.func @logical_or_resulterror(%arg0: i32, %arg1: i32) {
354+
// expected-error @+1 {{'emitc.logical_or' op result #0 must be 1-bit signless integer, but got 'i32'}}
355+
%0 = "emitc.logical_or"(%arg0, %arg1) : (i32, i32) -> i32
356+
return
357+
}

mlir/test/Dialect/EmitC/ops.mlir

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ func.func @cmp(%arg0 : i32, %arg1 : f32, %arg2 : i64, %arg3 : f64, %arg4 : !emit
117117
return
118118
}
119119

120+
func.func @logical(%arg0: i32, %arg1: i32) {
121+
%0 = emitc.logical_and %arg0, %arg1 : i32, i32
122+
%1 = emitc.logical_not %arg0 : i32
123+
%2 = emitc.logical_or %arg0, %arg1 : i32, i32
124+
return
125+
}
126+
120127
func.func @test_if(%arg0: i1, %arg1: f32) {
121128
emitc.if %arg0 {
122129
%0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
2+
3+
func.func @logical(%arg0: i32, %arg1: i32) -> () {
4+
%0 = emitc.logical_and %arg0, %arg1 : i32, i32
5+
%1 = emitc.logical_not %arg0 : i32
6+
%2 = emitc.logical_or %arg0, %arg1 : i32, i32
7+
8+
return
9+
}
10+
11+
// CHECK-LABEL: void logical
12+
// CHECK-NEXT: bool [[V2:[^ ]*]] = [[V0:[^ ]*]] && [[V1:[^ ]*]];
13+
// CHECK-NEXT: bool [[V3:[^ ]*]] = ![[V0]];
14+
// CHECK-NEXT: bool [[V4:[^ ]*]] = [[V0]] || [[V1]];

0 commit comments

Comments
 (0)