[Mlir-commits] [mlir] [mlir][emitc] Add op modelling C expressions (PR #71631)
Simon Camphausen
llvmlistbot at llvm.org
Wed Nov 8 06:49:48 PST 2023
================
@@ -246,6 +247,85 @@ def EmitC_DivOp : EmitC_BinaryOp<"div", []> {
let results = (outs FloatIntegerIndexOrOpaqueType);
}
+def EmitC_ExpressionOp : EmitC_Op<"expression",
+ [HasOnlyGraphRegion, SingleBlockImplicitTerminator<"emitc::YieldOp">,
+ NoRegionArguments]> {
+ let summary = "Expression operation";
+ let description = [{
+ The `expression` operation returns a single SSA value which is yielded by
+ its single-basic-block region. The operation doesn't take any arguments.
+
+ As the operation is to be emitted as a C expression, the operations within
+ its body must form a single Def-Use tree of emitc ops whose result is
+ yielded by a terminating `yield`.
+
+ Example:
+
+ ```mlir
+ %r = emitc.expression : () -> i32 {
+ %0 = emitc.add %a, %b : (i32, i32) -> i32
+ %1 = emitc.call "foo"(%0) : () -> i32
+ %2 = emitc.add %c, %d : (i32, i32) -> i32
+ %3 = emitc.mul %1, %2 : (i32, i32) -> i32
+ yield %3
+ }
+ ```
+
+ May be emitted as
+
+ ```c++
+ int32_t v7 = foo(v1 + v2) * (v3 + v4);
+ ```
+
+ The operations allowed within expression body are emitc.add, emitc.apply,
+ emitc.call, emitc.cast, emitc.cmp, emitc.div, emitc.mul, emitc.rem and
+ emitc.sub.
+
+ When specified, the optional do_not_inline indicates that the expression is
+ to be emitted as seen above, i.e. as the rhs of an EmitC SSA value
+ definition. Otherwise, the expression may be emitted inline, i.e. directly
+ at its use.
+ }];
+
+ let arguments = (ins UnitAttr:$do_not_inline);
+ let results = (outs AnyType);
+ let regions = (region SizedRegion<1>:$region);
+
+ let hasVerifier = 1;
+ let hasCustomAssemblyFormat = 1;
+
+ let extraClassDeclaration = [{
+ static bool isCExpression(Operation &op) {
+ return isa<emitc::AddOp, emitc::ApplyOp, emitc::CallOp, emitc::CastOp,
+ emitc::CmpOp, emitc::DivOp, emitc::MulOp, emitc::RemOp,
+ emitc::SubOp>(op);
+ }
+ static bool hasSideEffects(Operation &op) {
+ assert(isCExpression(op) && "Expected a C operator");
+ // Conservatively assume calls to read and write memory.
+ if (isa<emitc::CallOp>(op))
+ return true;
+ // De-referencing reads modifiable memory.
+ auto applyOp = dyn_cast<emitc::ApplyOp>(op);
+ if (applyOp && applyOp.getApplicableOperator() == "*")
+ return true;
+ // Any operator using variables has a side effect of reading memory mutable by
+ // emitc::assign ops.
+ for (Value operand : op.getOperands()) {
+ Operation *def = operand.getDefiningOp();
+ if (def && isa<emitc::VariableOp>(def))
+ return true;
+ }
+ return false;
----------------
simon-camp wrote:
```suggestion
return llvm::any_of(op.getOperands(),
[](Value operand) { Operation *def = operand.getDefiningOp();
return def && isa<emitc::VariableOp>(def); });
```
https://github.com/llvm/llvm-project/pull/71631
More information about the Mlir-commits
mailing list