Unverified Commit c4fd1fd6 authored by Marius Brehler's avatar Marius Brehler Committed by GitHub
Browse files

[mlir][emitc] Rename `call` op to `call_opaque` (#72494)

This renames the `emitc.call` op to `emitc.call_opaque` as the existing
call op does not refer to the callee by symbol. The rename allows to
introduce a new call op alongside with a future `emitc.func` op to model
and facilitate functions and function calls.
parent 76a441a6
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -3,12 +3,12 @@ ops. Those can be translated to C/C++ via the Cpp emitter.

The following convention is followed:

*   If template arguments are passed to an `emitc.call` operation, C++ is
*   If template arguments are passed to an `emitc.call_opaque` operation, C++ is
    generated.
*   If tensors are used, C++ is generated.
*   If multiple return values are used within in a functions or an `emitc.call`
    operation, C++11 is required.
*   If floating-point type template arguments are passed to an `emitc.call`
*   If multiple return values are used within in a functions or an
    `emitc.call_opaque` operation, C++11 is required.
*   If floating-point type template arguments are passed to an `emitc.call_opaque`
    operation, C++20 is required.
*   Else the generated code is compatible with C99.

+10 −8
Original line number Diff line number Diff line
@@ -92,11 +92,12 @@ def EmitC_ApplyOp : EmitC_Op<"apply", []> {
  let hasVerifier = 1;
}

def EmitC_CallOp : EmitC_Op<"call", []> {
  let summary = "Call operation";
def EmitC_CallOpaqueOp : EmitC_Op<"call_opaque", []> {
  let summary = "Opaque call operation";
  let description = [{
    The `call` operation represents a C++ function call. The call allows
    specifying order of operands and attributes in the call as follows:
    The `call_opaque` operation represents a C++ function call. The callee
    can be an arbitrary non-empty string. The call allows specifying order
    of operands and attributes in the call as follows:

    - integer value of index type refers to an operand;
    - attribute which will get lowered to constant value in call;
@@ -105,10 +106,10 @@ def EmitC_CallOp : EmitC_Op<"call", []> {

    ```mlir
    // Custom form defining a call to `foo()`.
    %0 = emitc.call "foo" () : () -> i32
    %0 = emitc.call_opaque "foo" () : () -> i32

    // Generic form of the same operation.
    %0 = "emitc.call"() {callee = "foo"} : () -> i32
    %0 = "emitc.call_opaque"() {callee = "foo"} : () -> i32
    ```
  }];
  let arguments = (ins
@@ -454,7 +455,8 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
    %1 = "emitc.variable"() {value = 0 : i32} : () -> i32
    %2 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
    %3 = emitc.apply "&"(%1) : (i32) -> !emitc.ptr<i32>
    emitc.call "write"(%2, %3) : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
    emitc.call_opaque "write"(%2, %3)
      : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
    ```
  }];

@@ -477,7 +479,7 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
    ```mlir
    // Integer variable
    %0 = "emitc.variable"(){value = 42 : i32} : () -> i32
    %1 = emitc.call "foo"() : () -> (i32)
    %1 = emitc.call_opaque "foo"() : () -> (i32)

    // Assign emitted as `... = ...;`
    "emitc.assign"(%0, %1) : (i32, i32) -> ()
+1 −1
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ bool CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
// CallOp
//===----------------------------------------------------------------------===//

LogicalResult emitc::CallOp::verify() {
LogicalResult emitc::CallOpaqueOp::verify() {
  // Callee must not be empty.
  if (getCallee().empty())
    return emitOpError("callee must not be empty");
+14 −12
Original line number Diff line number Diff line
@@ -412,13 +412,14 @@ static LogicalResult printOperation(CppEmitter &emitter, func::CallOp callOp) {
  return success();
}

static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
static LogicalResult printOperation(CppEmitter &emitter,
                                    emitc::CallOpaqueOp callOpaqueOp) {
  raw_ostream &os = emitter.ostream();
  Operation &op = *callOp.getOperation();
  Operation &op = *callOpaqueOp.getOperation();

  if (failed(emitter.emitAssignPrefix(op)))
    return failure();
  os << callOp.getCallee();
  os << callOpaqueOp.getCallee();

  auto emitArgs = [&](Attribute attr) -> LogicalResult {
    if (auto t = dyn_cast<IntegerAttr>(attr)) {
@@ -441,10 +442,10 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
    return success();
  };

  if (callOp.getTemplateArgs()) {
  if (callOpaqueOp.getTemplateArgs()) {
    os << "<";
    if (failed(
            interleaveCommaWithError(*callOp.getTemplateArgs(), os, emitArgs)))
    if (failed(interleaveCommaWithError(*callOpaqueOp.getTemplateArgs(), os,
                                        emitArgs)))
      return failure();
    os << ">";
  }
@@ -452,8 +453,8 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::CallOp callOp) {
  os << "(";

  LogicalResult emittedArgs =
      callOp.getArgs()
          ? interleaveCommaWithError(*callOp.getArgs(), os, emitArgs)
      callOpaqueOp.getArgs()
          ? interleaveCommaWithError(*callOpaqueOp.getArgs(), os, emitArgs)
          : emitter.emitOperands(op);
  if (failed(emittedArgs))
    return failure();
@@ -949,10 +950,11 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
          .Case<cf::BranchOp, cf::CondBranchOp>(
              [&](auto op) { return printOperation(*this, op); })
          // EmitC ops.
          .Case<emitc::AddOp, emitc::ApplyOp, emitc::AssignOp, emitc::CallOp,
                emitc::CastOp, emitc::CmpOp, emitc::ConstantOp, emitc::DivOp,
                emitc::ForOp, emitc::IfOp, emitc::IncludeOp, emitc::MulOp,
                emitc::RemOp, emitc::SubOp, emitc::VariableOp>(
          .Case<emitc::AddOp, emitc::ApplyOp, emitc::AssignOp,
                emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
                emitc::ConstantOp, emitc::DivOp, emitc::ForOp, emitc::IfOp,
                emitc::IncludeOp, emitc::MulOp, emitc::RemOp, emitc::SubOp,
                emitc::VariableOp>(
              [&](auto op) { return printOperation(*this, op); })
          // Func ops.
          .Case<func::CallOp, func::ConstantOp, func::FuncOp, func::ReturnOp>(
+14 −14
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

func.func @test_if(%arg0: i1, %arg1: f32) {
  scf.if %arg0 {
     %0 = emitc.call "func_const"(%arg1) : (f32) -> i32
     %0 = emitc.call_opaque "func_const"(%arg1) : (f32) -> i32
  }
  return
}
@@ -10,7 +10,7 @@ func.func @test_if(%arg0: i1, %arg1: f32) {
// CHECK-SAME:                     %[[VAL_0:.*]]: i1,
// CHECK-SAME:                     %[[VAL_1:.*]]: f32) {
// CHECK-NEXT:    emitc.if %[[VAL_0]] {
// CHECK-NEXT:      %[[VAL_2:.*]] = emitc.call "func_const"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_2:.*]] = emitc.call_opaque "func_const"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:    }
// CHECK-NEXT:    return
// CHECK-NEXT:  }
@@ -18,9 +18,9 @@ func.func @test_if(%arg0: i1, %arg1: f32) {

func.func @test_if_else(%arg0: i1, %arg1: f32) {
  scf.if %arg0 {
    %0 = emitc.call "func_true"(%arg1) : (f32) -> i32
    %0 = emitc.call_opaque "func_true"(%arg1) : (f32) -> i32
  } else {
    %0 = emitc.call "func_false"(%arg1) : (f32) -> i32
    %0 = emitc.call_opaque "func_false"(%arg1) : (f32) -> i32
  }
  return
}
@@ -28,9 +28,9 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
// CHECK-SAME:                          %[[VAL_0:.*]]: i1,
// CHECK-SAME:                          %[[VAL_1:.*]]: f32) {
// CHECK-NEXT:    emitc.if %[[VAL_0]] {
// CHECK-NEXT:      %[[VAL_2:.*]] = emitc.call "func_true"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_2:.*]] = emitc.call_opaque "func_true"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:    } else {
// CHECK-NEXT:      %[[VAL_3:.*]] = emitc.call "func_false"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_3:.*]] = emitc.call_opaque "func_false"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:    }
// CHECK-NEXT:    return
// CHECK-NEXT:  }
@@ -39,12 +39,12 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
func.func @test_if_yield(%arg0: i1, %arg1: f32) {
  %0 = arith.constant 0 : i8
  %x, %y = scf.if %arg0 -> (i32, f64) {
    %1 = emitc.call "func_true_1"(%arg1) : (f32) -> i32
    %2 = emitc.call "func_true_2"(%arg1) : (f32) -> f64
    %1 = emitc.call_opaque "func_true_1"(%arg1) : (f32) -> i32
    %2 = emitc.call_opaque "func_true_2"(%arg1) : (f32) -> f64
    scf.yield %1, %2 : i32, f64
  } else {
    %1 = emitc.call "func_false_1"(%arg1) : (f32) -> i32
    %2 = emitc.call "func_false_2"(%arg1) : (f32) -> f64
    %1 = emitc.call_opaque "func_false_1"(%arg1) : (f32) -> i32
    %2 = emitc.call_opaque "func_false_2"(%arg1) : (f32) -> f64
    scf.yield %1, %2 : i32, f64
  }
  return
@@ -56,13 +56,13 @@ func.func @test_if_yield(%arg0: i1, %arg1: f32) {
// CHECK-NEXT:    %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
// CHECK-NEXT:    %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f64
// CHECK-NEXT:    emitc.if %[[VAL_0]] {
// CHECK-NEXT:      %[[VAL_5:.*]] = emitc.call "func_true_1"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_6:.*]] = emitc.call "func_true_2"(%[[VAL_1]]) : (f32) -> f64
// CHECK-NEXT:      %[[VAL_5:.*]] = emitc.call_opaque "func_true_1"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_6:.*]] = emitc.call_opaque "func_true_2"(%[[VAL_1]]) : (f32) -> f64
// CHECK-NEXT:      emitc.assign %[[VAL_5]] : i32 to %[[VAL_3]] : i32
// CHECK-NEXT:      emitc.assign %[[VAL_6]] : f64 to %[[VAL_4]] : f64
// CHECK-NEXT:    } else {
// CHECK-NEXT:      %[[VAL_7:.*]] = emitc.call "func_false_1"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_8:.*]] = emitc.call "func_false_2"(%[[VAL_1]]) : (f32) -> f64
// CHECK-NEXT:      %[[VAL_7:.*]] = emitc.call_opaque "func_false_1"(%[[VAL_1]]) : (f32) -> i32
// CHECK-NEXT:      %[[VAL_8:.*]] = emitc.call_opaque "func_false_2"(%[[VAL_1]]) : (f32) -> f64
// CHECK-NEXT:      emitc.assign %[[VAL_7]] : i32 to %[[VAL_3]] : i32
// CHECK-NEXT:      emitc.assign %[[VAL_8]] : f64 to %[[VAL_4]] : f64
// CHECK-NEXT:    }
Loading