Skip to content

Commit

Permalink
[mlir][EmitC] Add logical operators (llvm#83123)
Browse files Browse the repository at this point in the history
This adds operations for the logical operators AND, NOT and OR.
  • Loading branch information
marbre committed Feb 28, 2024
1 parent 21c7bc5 commit b81bb0e
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 1 deletion.
64 changes: 64 additions & 0 deletions mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,70 @@ def EmitC_LiteralOp : EmitC_Op<"literal", [Pure]> {
let assemblyFormat = "$value attr-dict `:` type($result)";
}

def EmitC_LogicalAndOp : EmitC_BinaryOp<"logical_and", []> {
let summary = "Logical and operation";
let description = [{
With the `logical_and` operation the logical operator && (and) can
be applied.

Example:

```mlir
%0 = emitc.logical_and %arg0, %arg1 : i32, i32
```
```c++
// Code emitted for the operation above.
bool v3 = v1 && v2;
```
}];

let results = (outs I1);
let assemblyFormat = "operands attr-dict `:` type(operands)";
}

def EmitC_LogicalNotOp : EmitC_Op<"logical_not", []> {
let summary = "Logical not operation";
let description = [{
With the `logical_not` operation the logical operator ! (negation) can
be applied.

Example:

```mlir
%0 = emitc.logical_not %arg0 : i32
```
```c++
// Code emitted for the operation above.
bool v2 = !v1;
```
}];

let arguments = (ins AnyType);
let results = (outs I1);
let assemblyFormat = "operands attr-dict `:` type(operands)";
}

def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", []> {
let summary = "Logical or operation";
let description = [{
With the `logical_or` operation the logical operator || (inclusive or)
can be applied.

Example:

```mlir
%0 = emitc.logical_or %arg0, %arg1 : i32, i32
```
```c++
// Code emitted for the operation above.
bool v3 = v1 || v2;
```
}];

let results = (outs I1);
let assemblyFormat = "operands attr-dict `:` type(operands)";
}

def EmitC_MulOp : EmitC_BinaryOp<"mul", []> {
let summary = "Multiplication operation";
let description = [{
Expand Down
30 changes: 29 additions & 1 deletion mlir/lib/Target/Cpp/TranslateToCpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,33 @@ static LogicalResult printOperation(CppEmitter &emitter,
return success();
}

static LogicalResult printOperation(CppEmitter &emitter,
emitc::LogicalAndOp logicalAndOp) {
Operation *operation = logicalAndOp.getOperation();
return printBinaryOperation(emitter, operation, "&&");
}

static LogicalResult printOperation(CppEmitter &emitter,
emitc::LogicalNotOp logicalNotOp) {
raw_ostream &os = emitter.ostream();

if (failed(emitter.emitAssignPrefix(*logicalNotOp.getOperation())))
return failure();

os << "!";

if (failed(emitter.emitOperand(logicalNotOp.getOperand())))
return failure();

return success();
}

static LogicalResult printOperation(CppEmitter &emitter,
emitc::LogicalOrOp logicalOrOp) {
Operation *operation = logicalOrOp.getOperation();
return printBinaryOperation(emitter, operation, "||");
}

static LogicalResult printOperation(CppEmitter &emitter, emitc::ForOp forOp) {

raw_indented_ostream &os = emitter.ostream();
Expand Down Expand Up @@ -1284,7 +1311,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
emitc::ConstantOp, emitc::DeclareFuncOp, emitc::DivOp,
emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp, emitc::IfOp,
emitc::IncludeOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp,
emitc::IncludeOp, emitc::LogicalAndOp, emitc::LogicalNotOp,
emitc::LogicalOrOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp,
emitc::SubOp, emitc::VariableOp, emitc::VerbatimOp>(
[&](auto op) { return printOperation(*this, op); })
// Func ops.
Expand Down
24 changes: 24 additions & 0 deletions mlir/test/Dialect/EmitC/invalid_ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,27 @@ emitc.declare_func @bar

// expected-error@+1 {{'emitc.declare_func' op requires attribute 'sym_name'}}
"emitc.declare_func"() : () -> ()

// -----

func.func @logical_and_resulterror(%arg0: i32, %arg1: i32) {
// expected-error @+1 {{'emitc.logical_and' op result #0 must be 1-bit signless integer, but got 'i32'}}
%0 = "emitc.logical_and"(%arg0, %arg1) : (i32, i32) -> i32
return
}

// -----

func.func @logical_not_resulterror(%arg0: i32) {
// expected-error @+1 {{'emitc.logical_not' op result #0 must be 1-bit signless integer, but got 'i32'}}
%0 = "emitc.logical_not"(%arg0) : (i32) -> i32
return
}

// -----

func.func @logical_or_resulterror(%arg0: i32, %arg1: i32) {
// expected-error @+1 {{'emitc.logical_or' op result #0 must be 1-bit signless integer, but got 'i32'}}
%0 = "emitc.logical_or"(%arg0, %arg1) : (i32, i32) -> i32
return
}
7 changes: 7 additions & 0 deletions mlir/test/Dialect/EmitC/ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ func.func @cmp(%arg0 : i32, %arg1 : f32, %arg2 : i64, %arg3 : f64, %arg4 : !emit
return
}

func.func @logical(%arg0: i32, %arg1: i32) {
%0 = emitc.logical_and %arg0, %arg1 : i32, i32
%1 = emitc.logical_not %arg0 : i32
%2 = emitc.logical_or %arg0, %arg1 : i32, i32
return
}

func.func @test_if(%arg0: i1, %arg1: f32) {
emitc.if %arg0 {
%0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
Expand Down
14 changes: 14 additions & 0 deletions mlir/test/Target/Cpp/logical_operators.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s

func.func @logical(%arg0: i32, %arg1: i32) -> () {
%0 = emitc.logical_and %arg0, %arg1 : i32, i32
%1 = emitc.logical_not %arg0 : i32
%2 = emitc.logical_or %arg0, %arg1 : i32, i32

return
}

// CHECK-LABEL: void logical
// CHECK-NEXT: bool [[V2:[^ ]*]] = [[V0:[^ ]*]] && [[V1:[^ ]*]];
// CHECK-NEXT: bool [[V3:[^ ]*]] = ![[V0]];
// CHECK-NEXT: bool [[V4:[^ ]*]] = [[V0]] || [[V1]];

0 comments on commit b81bb0e

Please sign in to comment.