[Mlir-commits] [mlir] 1477a67 - [mlir][emitc] Isolate expressions from above (#155641)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Sep 1 05:10:21 PDT 2025
Author: Gil Rapaport
Date: 2025-09-01T15:10:17+03:00
New Revision: 1477a67dceb99e3bac01e793ecaf18e36a01f33d
URL: https://github.com/llvm/llvm-project/commit/1477a67dceb99e3bac01e793ecaf18e36a01f33d
DIFF: https://github.com/llvm/llvm-project/commit/1477a67dceb99e3bac01e793ecaf18e36a01f33d.diff
LOG: [mlir][emitc] Isolate expressions from above (#155641)
The expression op is currently not isolated from above. This served its
original usage as an optional, translation-oriented op, but is becoming
less convenient now that expressions appear earlier in the emitc
compilation flow and are gaining use as components of other emitc ops.
This patch therefore adds the isolated-from-above trait to expressions.
Syntactically, the only change is in the expression's signature which
now includes the values being used in the expression as arguments and
their types. The region's argument's names shadow the used values to
keep the def-use relations clear.
Added:
Modified:
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
mlir/lib/Dialect/EmitC/IR/EmitC.cpp
mlir/lib/Dialect/EmitC/Transforms/Transforms.cpp
mlir/lib/Target/Cpp/TranslateToCpp.cpp
mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
mlir/test/Dialect/EmitC/form-expressions.mlir
mlir/test/Dialect/EmitC/invalid_ops.mlir
mlir/test/Dialect/EmitC/ops.mlir
mlir/test/Target/Cpp/control_flow.mlir
mlir/test/Target/Cpp/expressions.mlir
mlir/test/Target/Cpp/for.mlir
mlir/test/Target/Cpp/switch.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 44265e4c12be2..fb7a108b39fc0 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -455,9 +455,11 @@ def EmitC_DivOp : EmitC_BinaryOp<"div", []> {
let results = (outs FloatIntegerIndexOrOpaqueType);
}
-def EmitC_ExpressionOp : EmitC_Op<"expression",
- [HasOnlyGraphRegion, OpAsmOpInterface,
- SingleBlockImplicitTerminator<"emitc::YieldOp">, NoRegionArguments]> {
+def EmitC_ExpressionOp
+ : EmitC_Op<
+ "expression", [HasOnlyGraphRegion, OpAsmOpInterface,
+ IsolatedFromAbove,
+ SingleBlockImplicitTerminator<"emitc::YieldOp">]> {
let summary = "Expression operation";
let description = [{
The `emitc.expression` operation returns a single SSA value which is yielded by
@@ -494,12 +496,13 @@ def EmitC_ExpressionOp : EmitC_Op<"expression",
at its use.
}];
- let arguments = (ins UnitAttr:$do_not_inline);
+ let arguments = (ins Variadic<AnyTypeOf<[EmitCType, EmitC_LValueType]>>:$defs,
+ UnitAttr:$do_not_inline);
let results = (outs EmitCType:$result);
let regions = (region SizedRegion<1>:$region);
let hasVerifier = 1;
- let assemblyFormat = "attr-dict (`noinline` $do_not_inline^)? `:` type($result) $region";
+ let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
bool hasSideEffects() {
@@ -510,6 +513,13 @@ def EmitC_ExpressionOp : EmitC_Op<"expression",
return llvm::any_of(getRegion().front().without_terminator(), predicate);
};
Operation *getRootOp();
+ Block &createBody() {
+ assert(getRegion().empty() && "expression already has a body");
+ Block &block = getRegion().emplaceBlock();
+ for (auto operand : getOperands())
+ block.addArgument(operand.getType(), operand.getLoc());
+ return block;
+ }
//===------------------------------------------------------------------===//
// OpAsmOpInterface Methods
diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
index 515fe5c9980c6..b68933d0fb0a0 100644
--- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
+++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
@@ -610,16 +610,19 @@ class ShiftOpConversion : public OpConversionPattern<ArithOp> {
? rewriter.getIntegerAttr(arithmeticType, 0)
: rewriter.getIndexAttr(0)));
- emitc::ExpressionOp ternary = emitc::ExpressionOp::create(
- rewriter, op.getLoc(), arithmeticType, /*do_not_inline=*/false);
- Block &bodyBlock = ternary.getBodyRegion().emplaceBlock();
+ emitc::ExpressionOp ternary =
+ emitc::ExpressionOp::create(rewriter, op.getLoc(), arithmeticType,
+ ValueRange({lhs, rhs, excessCheck, poison}),
+ /*do_not_inline=*/false);
+ Block &bodyBlock = ternary.createBody();
auto currentPoint = rewriter.getInsertionPoint();
rewriter.setInsertionPointToStart(&bodyBlock);
Value arithmeticResult =
- EmitCOp::create(rewriter, op.getLoc(), arithmeticType, lhs, rhs);
- Value resultOrPoison =
- emitc::ConditionalOp::create(rewriter, op.getLoc(), arithmeticType,
- excessCheck, arithmeticResult, poison);
+ EmitCOp::create(rewriter, op.getLoc(), arithmeticType,
+ bodyBlock.getArgument(0), bodyBlock.getArgument(1));
+ Value resultOrPoison = emitc::ConditionalOp::create(
+ rewriter, op.getLoc(), arithmeticType, bodyBlock.getArgument(2),
+ arithmeticResult, bodyBlock.getArgument(3));
emitc::YieldOp::create(rewriter, op.getLoc(), resultOrPoison);
rewriter.setInsertionPoint(op->getBlock(), currentPoint);
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 58aba59278f2a..00ce3b59bf870 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -381,6 +381,52 @@ OpFoldResult emitc::ConstantOp::fold(FoldAdaptor adaptor) { return getValue(); }
// ExpressionOp
//===----------------------------------------------------------------------===//
+ParseResult ExpressionOp::parse(OpAsmParser &parser, OperationState &result) {
+ SmallVector<OpAsmParser::UnresolvedOperand> operands;
+ if (parser.parseOperandList(operands))
+ return parser.emitError(parser.getCurrentLocation()) << "expected operands";
+ if (succeeded(parser.parseOptionalKeyword("noinline")))
+ result.addAttribute(ExpressionOp::getDoNotInlineAttrName(result.name),
+ parser.getBuilder().getUnitAttr());
+ Type type;
+ if (parser.parseColonType(type))
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected function type");
+ auto fnType = llvm::dyn_cast<FunctionType>(type);
+ if (!fnType)
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected function type");
+ if (parser.resolveOperands(operands, fnType.getInputs(),
+ parser.getCurrentLocation(), result.operands))
+ return failure();
+ if (fnType.getNumResults() != 1)
+ return parser.emitError(parser.getCurrentLocation(),
+ "expected single return type");
+ result.addTypes(fnType.getResults());
+ Region *body = result.addRegion();
+ SmallVector<OpAsmParser::Argument> argsInfo;
+ for (auto [unresolvedOperand, operandType] :
+ llvm::zip(operands, fnType.getInputs())) {
+ OpAsmParser::Argument argInfo;
+ argInfo.ssaName = unresolvedOperand;
+ argInfo.type = operandType;
+ argsInfo.push_back(argInfo);
+ }
+ if (parser.parseRegion(*body, argsInfo, /*enableNameShadowing=*/true))
+ return failure();
+ return success();
+}
+
+void emitc::ExpressionOp::print(OpAsmPrinter &p) {
+ p << ' ';
+ p.printOperands(getDefs());
+ p << " : ";
+ p.printFunctionalType(getOperation());
+ p.shadowRegionArgs(getRegion(), getDefs());
+ p << ' ';
+ p.printRegion(getRegion(), /*printEntryBlockArgs=*/false);
+}
+
Operation *ExpressionOp::getRootOp() {
auto yieldOp = cast<YieldOp>(getBody()->getTerminator());
Value yieldedValue = yieldOp.getResult();
diff --git a/mlir/lib/Dialect/EmitC/Transforms/Transforms.cpp b/mlir/lib/Dialect/EmitC/Transforms/Transforms.cpp
index 3f0690c3b07ad..f8469b8f0ed67 100644
--- a/mlir/lib/Dialect/EmitC/Transforms/Transforms.cpp
+++ b/mlir/lib/Dialect/EmitC/Transforms/Transforms.cpp
@@ -9,7 +9,9 @@
#include "mlir/Dialect/EmitC/Transforms/Transforms.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/IR/IRMapping.h"
+#include "mlir/IR/Location.h"
#include "mlir/IR/PatternMatch.h"
+#include "llvm/ADT/STLExtras.h"
namespace mlir {
namespace emitc {
@@ -24,20 +26,24 @@ ExpressionOp createExpression(Operation *op, OpBuilder &builder) {
Location loc = op->getLoc();
builder.setInsertionPointAfter(op);
- auto expressionOp = emitc::ExpressionOp::create(builder, loc, resultType);
+ auto expressionOp =
+ emitc::ExpressionOp::create(builder, loc, resultType, op->getOperands());
// Replace all op's uses with the new expression's result.
result.replaceAllUsesWith(expressionOp.getResult());
- // Create an op to yield op's value.
- Region ®ion = expressionOp.getRegion();
- Block &block = region.emplaceBlock();
+ Block &block = expressionOp.createBody();
+ IRMapping mapper;
+ for (auto [operand, arg] :
+ llvm::zip(expressionOp.getOperands(), block.getArguments()))
+ mapper.map(operand, arg);
builder.setInsertionPointToEnd(&block);
- auto yieldOp = emitc::YieldOp::create(builder, loc, result);
- // Move op into the new expression.
- op->moveBefore(yieldOp);
+ Operation *rootOp = builder.clone(*op, mapper);
+ op->erase();
+ // Create an op to yield op's value.
+ emitc::YieldOp::create(builder, loc, rootOp->getResults()[0]);
return expressionOp;
}
@@ -53,51 +59,93 @@ struct FoldExpressionOp : public OpRewritePattern<ExpressionOp> {
using OpRewritePattern<ExpressionOp>::OpRewritePattern;
LogicalResult matchAndRewrite(ExpressionOp expressionOp,
PatternRewriter &rewriter) const override {
- bool anythingFolded = false;
- for (Operation &op : llvm::make_early_inc_range(
- expressionOp.getBody()->without_terminator())) {
- // Don't fold expressions whose result value has its address taken.
- auto applyOp = dyn_cast<emitc::ApplyOp>(op);
- if (applyOp && applyOp.getApplicableOperator() == "&")
- continue;
-
- for (Value operand : op.getOperands()) {
- auto usedExpression = operand.getDefiningOp<ExpressionOp>();
- if (!usedExpression)
- continue;
-
- // Don't fold expressions with multiple users: assume any
- // re-materialization was done separately.
- if (!usedExpression.getResult().hasOneUse())
- continue;
-
- // Don't fold expressions with side effects.
- if (usedExpression.hasSideEffects())
- continue;
-
- // Fold the used expression into this expression by cloning all
- // instructions in the used expression just before the operation using
- // its value.
- rewriter.setInsertionPoint(&op);
- IRMapping mapper;
- for (Operation &opToClone :
- usedExpression.getBody()->without_terminator()) {
- Operation *clone = rewriter.clone(opToClone, mapper);
- mapper.map(&opToClone, clone);
- }
-
- Operation *expressionRoot = usedExpression.getRootOp();
- Operation *clonedExpressionRootOp = mapper.lookup(expressionRoot);
- assert(clonedExpressionRootOp &&
- "Expected cloned expression root to be in mapper");
- assert(clonedExpressionRootOp->getNumResults() == 1 &&
- "Expected cloned root to have a single result");
-
- rewriter.replaceOp(usedExpression, clonedExpressionRootOp);
- anythingFolded = true;
- }
+ Block *expressionBody = expressionOp.getBody();
+ ExpressionOp usedExpression;
+ SetVector<Value> foldedOperands;
+
+ auto takesItsOperandsAddress = [](Operation *user) {
+ auto applyOp = dyn_cast<emitc::ApplyOp>(user);
+ return applyOp && applyOp.getApplicableOperator() == "&";
+ };
+
+ // Select as expression to fold the first operand expression that
+ // - doesn't have its result value's address taken,
+ // - has a single user: assume any re-materialization was done separately,
+ // - has no side effects,
+ // and save all other operands to be used later as operands in the folded
+ // expression.
+ for (auto [operand, arg] : llvm::zip(expressionOp.getOperands(),
+ expressionBody->getArguments())) {
+ ExpressionOp operandExpression = operand.getDefiningOp<ExpressionOp>();
+ if (usedExpression || !operandExpression ||
+ llvm::any_of(arg.getUsers(), takesItsOperandsAddress) ||
+ !operandExpression.getResult().hasOneUse() ||
+ operandExpression.hasSideEffects())
+ foldedOperands.insert(operand);
+ else
+ usedExpression = operandExpression;
}
- return anythingFolded ? success() : failure();
+
+ // If no operand expression was selected, bail out.
+ if (!usedExpression)
+ return failure();
+
+ // Collect additional operands from the folded expression.
+ for (Value operand : usedExpression.getOperands())
+ foldedOperands.insert(operand);
+
+ // Create a new expression to hold the folding result.
+ rewriter.setInsertionPointAfter(expressionOp);
+ auto foldedExpression = emitc::ExpressionOp::create(
+ rewriter, expressionOp.getLoc(), expressionOp.getResult().getType(),
+ foldedOperands.getArrayRef(), expressionOp.getDoNotInline());
+ Block &foldedExpressionBody = foldedExpression.createBody();
+
+ // Map each operand of the new expression to its matching block argument.
+ IRMapping mapper;
+ for (auto [operand, arg] : llvm::zip(foldedExpression.getOperands(),
+ foldedExpressionBody.getArguments()))
+ mapper.map(operand, arg);
+
+ // Prepare to fold the used expression and the matched expression into the
+ // newly created folded expression.
+ auto foldExpression = [&rewriter, &mapper](ExpressionOp expressionToFold,
+ bool withTerminator) {
+ Block *expressionToFoldBody = expressionToFold.getBody();
+ for (auto [operand, arg] :
+ llvm::zip(expressionToFold.getOperands(),
+ expressionToFoldBody->getArguments())) {
+ mapper.map(arg, mapper.lookup(operand));
+ }
+
+ for (Operation &opToClone : expressionToFoldBody->without_terminator())
+ rewriter.clone(opToClone, mapper);
+
+ if (withTerminator)
+ rewriter.clone(*expressionToFoldBody->getTerminator(), mapper);
+ };
+ rewriter.setInsertionPointToStart(&foldedExpressionBody);
+
+ // First, fold the used expression into the new expression and map its
+ // result to the clone of its root operation within the new expression.
+ foldExpression(usedExpression, /*withTerminator=*/false);
+ Operation *expressionRoot = usedExpression.getRootOp();
+ Operation *clonedExpressionRootOp = mapper.lookup(expressionRoot);
+ assert(clonedExpressionRootOp &&
+ "Expected cloned expression root to be in mapper");
+ assert(clonedExpressionRootOp->getNumResults() == 1 &&
+ "Expected cloned root to have a single result");
+ mapper.map(usedExpression.getResult(),
+ clonedExpressionRootOp->getResults()[0]);
+
+ // Now fold the matched expression into the new expression.
+ foldExpression(expressionOp, /*withTerminator=*/true);
+
+ // Complete the rewrite.
+ rewriter.replaceOp(expressionOp, foldedExpression);
+ rewriter.eraseOp(usedExpression);
+
+ return success();
}
};
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 68830a1b8da2b..570f38c60020b 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -14,6 +14,7 @@
#include "mlir/IR/Dialect.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/SymbolTable.h"
+#include "mlir/IR/Value.h"
#include "mlir/Support/IndentedOstream.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Target/Cpp/CppEmitter.h"
@@ -364,9 +365,10 @@ static bool shouldBeInlined(ExpressionOp expressionOp) {
if (hasDeferredEmission(user))
return false;
- // Do not inline expressions used by ops with the CExpressionInterface. If
- // this was intended, the user could have been merged into the expression op.
- return !isa<emitc::CExpressionInterface>(*user);
+ // Do not inline expressions used by other expressions or by ops with the
+ // CExpressionInterface. If this was intended, the user could have been merged
+ // into the expression op.
+ return !isa<emitc::ExpressionOp, emitc::CExpressionInterface>(*user);
}
static LogicalResult printConstantOp(CppEmitter &emitter, Operation *operation,
@@ -1532,6 +1534,20 @@ LogicalResult CppEmitter::emitOperand(Value value) {
if (expressionOp && shouldBeInlined(expressionOp))
return emitExpression(expressionOp);
+ if (BlockArgument arg = dyn_cast<BlockArgument>(value)) {
+ // If this operand is a block argument of an expression, emit instead the
+ // matching expression parameter.
+ Operation *argOp = arg.getParentBlock()->getParentOp();
+ if (auto expressionOp = dyn_cast<ExpressionOp>(argOp)) {
+ // This scenario is only expected when one of the operations within the
+ // expression being emitted references one of the expression's block
+ // arguments.
+ assert(expressionOp == emittedExpression &&
+ "Expected expression being emitted");
+ value = expressionOp->getOperand(arg.getArgNumber());
+ }
+ }
+
os << getOrCreateName(value);
return success();
}
diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
index 1382f3cc13a3b..319dfc31ab637 100644
--- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
+++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir
@@ -153,7 +153,7 @@ func.func @arith_shift_left(%arg0: i32, %arg1: i32) {
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = "emitc.constant"{{.*}}value = 32
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[C2]], %[[SizeConstant]] : (ui32, ui32) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0
- // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : ui32 {
+ // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression %[[C1]], %[[C2]], %[[CmpNoExcess]], %[[Zero]] : (ui32, ui32, i1, ui32) -> ui32 {
// CHECK-NEXT: %[[SHL:[^ ]*]] = bitwise_left_shift %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK-NEXT: %[[Ternary:[^ ]*]] = conditional %[[CmpNoExcess]], %[[SHL]], %[[Zero]] : ui32
// CHECK-NEXT: yield %[[Ternary]] : ui32
@@ -173,7 +173,7 @@ func.func @arith_shift_right(%arg0: i32, %arg1: i32) {
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = "emitc.constant"{{.*}}value = 32{{.*}}ui32
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[C2]], %[[SizeConstant]] : (ui32, ui32) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}ui32
- // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : ui32 {
+ // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression %[[C1]], %[[C2]], %[[CmpNoExcess]], %[[Zero]] : (ui32, ui32, i1, ui32) -> ui32 {
// CHECK-NEXT: %[[SHR:[^ ]*]] = bitwise_right_shift %[[C1]], %[[C2]] : (ui32, ui32) -> ui32
// CHECK-NEXT: %[[Ternary:[^ ]*]] = conditional %[[CmpNoExcess]], %[[SHR]], %[[Zero]] : ui32
// CHECK-NEXT: yield %[[Ternary]] : ui32
@@ -185,7 +185,7 @@ func.func @arith_shift_right(%arg0: i32, %arg1: i32) {
// CHECK-DAG: %[[SSizeConstant:[^ ]*]] = "emitc.constant"{{.*}}value = 32{{.*}}ui32
// CHECK-DAG: %[[SCmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[SC2]], %[[SSizeConstant]] : (ui32, ui32) -> i1
// CHECK-DAG: %[[SZero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}i32
- // CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression : i32 {
+ // CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression %[[ARG0]], %[[SC2]], %[[SCmpNoExcess]], %[[SZero]] : (i32, ui32, i1, i32) -> i32 {
// CHECK-NEXT: %[[SHRSI:[^ ]*]] = bitwise_right_shift %[[ARG0]], %[[SC2]] : (i32, ui32) -> i32
// CHECK-NEXT: %[[STernary:[^ ]*]] = conditional %[[SCmpNoExcess]], %[[SHRSI]], %[[SZero]] : i32
// CHECK-NEXT: yield %[[STernary]] : i32
@@ -210,7 +210,7 @@ func.func @arith_shift_left_index(%amount: i32) {
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = emitc.mul %[[Byte]], %[[SizeOf]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[AmountIdx]], %[[SizeConstant]] : (!emitc.size_t, !emitc.size_t) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0
- // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : !emitc.size_t {
+ // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression %[[C1]], %[[AmountIdx]], %[[CmpNoExcess]], %[[Zero]] : (!emitc.size_t, !emitc.size_t, i1, !emitc.size_t) -> !emitc.size_t {
// CHECK-NEXT: %[[SHL:[^ ]*]] = bitwise_left_shift %[[C1]], %[[AmountIdx]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-NEXT: %[[Ternary:[^ ]*]] = conditional %[[CmpNoExcess]], %[[SHL]], %[[Zero]] : !emitc.size_t
// CHECK-NEXT: yield %[[Ternary]] : !emitc.size_t
@@ -235,7 +235,7 @@ func.func @arith_shift_right_index(%amount: i32) {
// CHECK-DAG: %[[SizeConstant:[^ ]*]] = emitc.mul %[[Byte]], %[[SizeOf]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[CmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[AmountIdx]], %[[SizeConstant]] : (!emitc.size_t, !emitc.size_t) -> i1
// CHECK-DAG: %[[Zero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}!emitc.size_t
- // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression : !emitc.size_t {
+ // CHECK: %[[ShiftRes:[^ ]*]] = emitc.expression %[[C1]], %[[AmountIdx]], %[[CmpNoExcess]], %[[Zero]] : (!emitc.size_t, !emitc.size_t, i1, !emitc.size_t) -> !emitc.size_t {
// CHECK-NEXT: %[[SHR:[^ ]*]] = bitwise_right_shift %[[C1]], %[[AmountIdx]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-NEXT: %[[Ternary:[^ ]*]] = conditional %[[CmpNoExcess]], %[[SHR]], %[[Zero]] : !emitc.size_t
// CHECK-NEXT: yield %[[Ternary]] : !emitc.size_t
@@ -248,7 +248,7 @@ func.func @arith_shift_right_index(%amount: i32) {
// CHECK-DAG: %[[SSizeConstant:[^ ]*]] = emitc.mul %[[SByte]], %[[SSizeOf]] : (!emitc.size_t, !emitc.size_t) -> !emitc.size_t
// CHECK-DAG: %[[SCmpNoExcess:[^ ]*]] = emitc.cmp lt, %[[AmountIdx]], %[[SSizeConstant]] : (!emitc.size_t, !emitc.size_t) -> i1
// CHECK-DAG: %[[SZero:[^ ]*]] = "emitc.constant"{{.*}}value = 0{{.*}}!emitc.ptr
diff _t
- // CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression : !emitc.ptr
diff _t {
+ // CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression %[[SC1]], %[[AmountIdx]], %[[SCmpNoExcess]], %[[SZero]] : (!emitc.ptr
diff _t, !emitc.size_t, i1, !emitc.ptr
diff _t) -> !emitc.ptr
diff _t {
// CHECK-NEXT: %[[SHRSI:[^ ]*]] = bitwise_right_shift %[[SC1]], %[[AmountIdx]] : (!emitc.ptr
diff _t, !emitc.size_t) -> !emitc.ptr
diff _t
// CHECK-NEXT: %[[STernary:[^ ]*]] = conditional %[[SCmpNoExcess]], %[[SHRSI]], %[[SZero]] : !emitc.ptr
diff _t
// CHECK-NEXT: yield %[[STernary]] : !emitc.ptr
diff _t
diff --git a/mlir/test/Dialect/EmitC/form-expressions.mlir b/mlir/test/Dialect/EmitC/form-expressions.mlir
index c8dbf0416837e..67cd6fddba638 100644
--- a/mlir/test/Dialect/EmitC/form-expressions.mlir
+++ b/mlir/test/Dialect/EmitC/form-expressions.mlir
@@ -3,7 +3,7 @@
// CHECK-LABEL: func.func @single_expression(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i32) -> i1 {
// CHECK: %[[VAL_4:.*]] = "emitc.constant"() <{value = 42 : i32}> : () -> i32
-// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_5:.*]] = emitc.expression %[[VAL_3]], %[[VAL_2]], %[[VAL_0]], %[[VAL_4]] : (i32, i32, i32, i32) -> i1 {
// CHECK: %[[VAL_6:.*]] = mul %[[VAL_0]], %[[VAL_4]] : (i32, i32) -> i32
// CHECK: %[[VAL_7:.*]] = sub %[[VAL_6]], %[[VAL_2]] : (i32, i32) -> i32
// CHECK: %[[VAL_8:.*]] = cmp lt, %[[VAL_7]], %[[VAL_3]] : (i32, i32) -> i1
@@ -22,12 +22,12 @@ func.func @single_expression(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) ->
// CHECK-LABEL: func.func @multiple_expressions(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i32) -> (i32, i32) {
-// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 {
+// CHECK: %[[VAL_4:.*]] = emitc.expression %[[VAL_2]], %[[VAL_0]], %[[VAL_1]] : (i32, i32, i32) -> i32 {
// CHECK: %[[VAL_5:.*]] = mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32
// CHECK: %[[VAL_6:.*]] = sub %[[VAL_5]], %[[VAL_2]] : (i32, i32) -> i32
// CHECK: yield %[[VAL_6]] : i32
// CHECK: }
-// CHECK: %[[VAL_7:.*]] = emitc.expression : i32 {
+// CHECK: %[[VAL_7:.*]] = emitc.expression %[[VAL_2]], %[[VAL_1]], %[[VAL_3]] : (i32, i32, i32) -> i32 {
// CHECK: %[[VAL_8:.*]] = add %[[VAL_1]], %[[VAL_3]] : (i32, i32) -> i32
// CHECK: %[[VAL_9:.*]] = div %[[VAL_8]], %[[VAL_2]] : (i32, i32) -> i32
// CHECK: yield %[[VAL_9]] : i32
@@ -45,12 +45,12 @@ func.func @multiple_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
// CHECK-LABEL: func.func @expression_with_call(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: i32, %[[VAL_3:.*]]: i32) -> i1 {
-// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 {
+// CHECK: %[[VAL_4:.*]] = emitc.expression %[[VAL_2]], %[[VAL_0]], %[[VAL_1]] : (i32, i32, i32) -> i32 {
// CHECK: %[[VAL_5:.*]] = mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32
// CHECK: %[[VAL_6:.*]] = call_opaque "foo"(%[[VAL_5]], %[[VAL_2]]) : (i32, i32) -> i32
// CHECK: yield %[[VAL_6]] : i32
// CHECK: }
-// CHECK: %[[VAL_7:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_7:.*]] = emitc.expression %[[VAL_4]], %[[VAL_1]] : (i32, i32) -> i1 {
// CHECK: %[[VAL_8:.*]] = cmp lt, %[[VAL_4]], %[[VAL_1]] : (i32, i32) -> i1
// CHECK: yield %[[VAL_8]] : i1
// CHECK: }
@@ -66,11 +66,11 @@ func.func @expression_with_call(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
// CHECK-LABEL: func.func @expression_with_dereference(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: !emitc.ptr<i32>) -> i1 {
-// CHECK: %[[VAL_3:.*]] = emitc.expression : i32 {
+// CHECK: %[[VAL_3:.*]] = emitc.expression %[[VAL_2]] : (!emitc.ptr<i32>) -> i32 {
// CHECK: %[[VAL_4:.*]] = apply "*"(%[[VAL_2]]) : (!emitc.ptr<i32>) -> i32
// CHECK: yield %[[VAL_4]] : i32
// CHECK: }
-// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_5:.*]] = emitc.expression %[[VAL_3]], %[[VAL_0]], %[[VAL_1]] : (i32, i32, i32) -> i1 {
// CHECK: %[[VAL_6:.*]] = mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32
// CHECK: %[[VAL_7:.*]] = cmp lt, %[[VAL_6]], %[[VAL_3]] : (i32, i32) -> i1
// CHECK: return %[[VAL_5]] : i1
@@ -86,7 +86,7 @@ func.func @expression_with_dereference(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr
// CHECK-LABEL: func.func @expression_with_address_taken(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: !emitc.ptr<i32>) -> i1 {
// CHECK: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
-// CHECK: %[[VAL_4:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_4:.*]] = emitc.expression %[[VAL_2]], %[[VAL_1]], %[[VAL_3]] : (!emitc.ptr<i32>, i32, !emitc.lvalue<i32>) -> i1 {
// CHECK: %[[VAL_5:.*]] = apply "&"(%[[VAL_3]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
// CHECK: %[[VAL_6:.*]] = add %[[VAL_5]], %[[VAL_1]] : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
// CHECK: %[[VAL_7:.*]] = cmp lt, %[[VAL_6]], %[[VAL_2]] : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
@@ -105,7 +105,7 @@ func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.p
// CHECK-LABEL: func.func @no_nested_expression(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32) -> i1 {
-// CHECK: %[[VAL_2:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_2:.*]] = emitc.expression %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i1 {
// CHECK: %[[VAL_3:.*]] = cmp lt, %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i1
// CHECK: yield %[[VAL_3]] : i1
// CHECK: }
@@ -113,7 +113,7 @@ func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.p
// CHECK: }
func.func @no_nested_expression(%arg0: i32, %arg1: i32) -> i1 {
- %a = emitc.expression : i1 {
+ %a = emitc.expression %arg0, %arg1 :(i32, i32) -> i1 {
%b = emitc.cmp lt, %arg0, %arg1 :(i32, i32) -> i1
emitc.yield %b : i1
}
@@ -133,16 +133,16 @@ func.func @single_result_requirement() -> (i32, i32) {
// CHECK-SAME: %[[VAL_1:.*]]: !emitc.ptr<i32>) -> i1 {
// CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64
// CHECK: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue<i32>
-// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 {
+// CHECK: %[[VAL_4:.*]] = emitc.expression %[[VAL_3]] : (!emitc.lvalue<i32>) -> i32 {
// CHECK: %[[VAL_5:.*]] = load %[[VAL_3]] : <i32>
// CHECK: yield %[[VAL_5]] : i32
// CHECK: }
// CHECK: %[[VAL_6:.*]] = emitc.subscript %[[VAL_1]]{{\[}}%[[VAL_2]]] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
-// CHECK: %[[VAL_7:.*]] = emitc.expression : i32 {
+// CHECK: %[[VAL_7:.*]] = emitc.expression %[[VAL_6]] : (!emitc.lvalue<i32>) -> i32 {
// CHECK: %[[VAL_8:.*]] = load %[[VAL_6]] : <i32>
// CHECK: yield %[[VAL_8]] : i32
// CHECK: }
-// CHECK: %[[VAL_9:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_9:.*]] = emitc.expression %[[VAL_0]], %[[VAL_4]], %[[VAL_7]] : (i32, i32, i32) -> i1 {
// CHECK: %[[VAL_10:.*]] = add %[[VAL_4]], %[[VAL_7]] : (i32, i32) -> i32
// CHECK: %[[VAL_11:.*]] = cmp lt, %[[VAL_10]], %[[VAL_0]] : (i32, i32) -> i1
// CHECK: yield %[[VAL_11]] : i1
@@ -163,12 +163,12 @@ func.func @expression_with_load(%arg0: i32, %arg1: !emitc.ptr<i32>) -> i1 {
// CHECK-LABEL: func.func @opaque_type_expression(%arg0: i32, %arg1: !emitc.opaque<"T0">, %arg2: i32) -> i1 {
// CHECK: %0 = "emitc.constant"() <{value = 42 : i32}> : () -> i32
-// CHECK: %1 = emitc.expression : i32 {
+// CHECK: %1 = emitc.expression %arg1, %arg0, %0 : (!emitc.opaque<"T0">, i32, i32) -> i32 {
// CHECK: %3 = mul %arg0, %0 : (i32, i32) -> i32
// CHECK: %4 = sub %3, %arg1 : (i32, !emitc.opaque<"T0">) -> i32
// CHECK: yield %4 : i32
// CHECK: }
-// CHECK: %2 = emitc.expression : i1 {
+// CHECK: %2 = emitc.expression %1, %arg2 : (i32, i32) -> i1 {
// CHECK: %3 = cmp lt, %1, %arg2 : (i32, i32) -> i1
// CHECK: yield %3 : i1
// CHECK: }
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 6d7f79ead2974..fdfb0eb46f7c5 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -290,7 +290,7 @@ func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) {
func.func @test_expression_no_yield() -> i32 {
// expected-error @+1 {{'emitc.expression' op must yield a value at termination}}
- %r = emitc.expression : i32 {
+ %r = emitc.expression : () -> i32 {
%c7 = "emitc.constant"(){value = 7 : i32} : () -> i32
}
return %r : i32
@@ -300,7 +300,7 @@ func.func @test_expression_no_yield() -> i32 {
func.func @test_expression_illegal_op(%arg0 : i1) -> i32 {
// expected-error @+1 {{'emitc.expression' op contains an unsupported operation}}
- %r = emitc.expression : i32 {
+ %r = emitc.expression : () -> i32 {
%x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
%y = emitc.load %x : <i32>
emitc.yield %y : i32
@@ -312,7 +312,7 @@ func.func @test_expression_illegal_op(%arg0 : i1) -> i32 {
func.func @test_expression_no_use(%arg0: i32, %arg1: i32) -> i32 {
// expected-error @+1 {{'emitc.expression' op requires exactly one use for each operation}}
- %r = emitc.expression : i32 {
+ %r = emitc.expression %arg0, %arg1 : (i32, i32) -> i32 {
%a = emitc.add %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.rem %arg0, %arg1 : (i32, i32) -> i32
emitc.yield %a : i32
@@ -324,7 +324,7 @@ func.func @test_expression_no_use(%arg0: i32, %arg1: i32) -> i32 {
func.func @test_expression_multiple_uses(%arg0: i32, %arg1: i32) -> i32 {
// expected-error @+1 {{'emitc.expression' op requires exactly one use for each operation}}
- %r = emitc.expression : i32 {
+ %r = emitc.expression %arg0, %arg1 : (i32, i32) -> i32 {
%a = emitc.rem %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.add %a, %arg0 : (i32, i32) -> i32
%c = emitc.mul %arg1, %a : (i32, i32) -> i32
@@ -337,7 +337,7 @@ func.func @test_expression_multiple_uses(%arg0: i32, %arg1: i32) -> i32 {
func.func @test_expression_multiple_results(%arg0: i32) -> i32 {
// expected-error @+1 {{'emitc.expression' op requires exactly one result for each operation}}
- %r = emitc.expression : i32 {
+ %r = emitc.expression %arg0 : (i32) -> i32 {
%a:2 = emitc.call_opaque "bar" (%arg0) : (i32) -> (i32, i32)
emitc.yield %a : i32
}
@@ -348,7 +348,7 @@ func.func @test_expression_multiple_results(%arg0: i32) -> i32 {
emitc.func @test_expression_no_defining_op(%a : i32) {
// expected-error @+1 {{'emitc.expression' op yielded value has no defining op}}
- %res = emitc.expression : i32 {
+ %res = emitc.expression %a : (i32) -> i32 {
emitc.yield %a : i32
}
@@ -357,10 +357,21 @@ emitc.func @test_expression_no_defining_op(%a : i32) {
// -----
+emitc.func @test_expression_no_defining_op() {
+ %cond = literal "true" : i1
+ // expected-error @+1 {{'emitc.expression' op yielded value has no defining op}}
+ %res = emitc.expression %cond : (i1) -> i1 {
+ emitc.yield %cond : i1
+ }
+ return
+}
+
+// -----
+
emitc.func @test_expression_op_outside_expression() {
%cond = literal "true" : i1
- // expected-error @+1 {{'emitc.expression' op yielded value not defined within expression}}
- %res = emitc.expression : i1 {
+ %res = emitc.expression : () -> i1 {
+ // expected-error @+1 {{use of undeclared SSA value name}}
emitc.yield %cond : i1
}
return
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index fec8431262f37..e890f77173de7 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -188,11 +188,11 @@ func.func @test_assign(%arg1: f32) {
func.func @test_expression(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: f32, %arg4: f32) -> i32 {
%c7 = "emitc.constant"() {value = 7 : i32} : () -> i32
- %q = emitc.expression : i32 {
+ %q = emitc.expression %arg1, %c7 : (i32, i32) -> i32 {
%a = emitc.rem %arg1, %c7 : (i32, i32) -> i32
emitc.yield %a : i32
}
- %r = emitc.expression noinline : i32 {
+ %r = emitc.expression %arg0, %arg1, %arg2, %arg3, %arg4, %q noinline : (i32, i32, i32, f32, f32, i32) -> i32 {
%a = emitc.add %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.call_opaque "bar" (%a, %arg2, %q) : (i32, i32, i32) -> (i32)
%c = emitc.mul %arg3, %arg4 : (f32, f32) -> f32
diff --git a/mlir/test/Target/Cpp/control_flow.mlir b/mlir/test/Target/Cpp/control_flow.mlir
index 101b30c2521c9..ce9a0ee7f9b66 100644
--- a/mlir/test/Target/Cpp/control_flow.mlir
+++ b/mlir/test/Target/Cpp/control_flow.mlir
@@ -70,7 +70,7 @@ func.func @block_labels1() {
// CPP-DECLTOP-NEXT: }
emitc.func @expression_inlining(%0 : i32, %1 : i32) {
- %2 = expression : i1 {
+ %2 = expression %0, %1 : (i32, i32) -> i1 {
%3 = cmp lt, %0, %1 : (i32, i32) -> i1
yield %3 : i1
}
diff --git a/mlir/test/Target/Cpp/expressions.mlir b/mlir/test/Target/Cpp/expressions.mlir
index 5057d6ca0c4cf..433a67ccb3f39 100644
--- a/mlir/test/Target/Cpp/expressions.mlir
+++ b/mlir/test/Target/Cpp/expressions.mlir
@@ -30,7 +30,7 @@
func.func @single_use(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
%p0 = emitc.literal "M_PI" : i32
- %e = emitc.expression : i1 {
+ %e = emitc.expression %arg0, %arg1, %arg2, %arg3, %p0 : (i32, i32, i32, i32, i32) -> i1 {
%a = emitc.mul %arg0, %p0 : (i32, i32) -> i32
%b = emitc.call_opaque "bar" (%a, %arg2) : (i32, i32) -> (i32)
%c = emitc.sub %b, %arg3 : (i32, i32) -> i32
@@ -61,7 +61,7 @@ func.func @single_use(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
// CPP-DECLTOP-NEXT:}
func.func @do_not_inline(%arg0: i32, %arg1: i32, %arg2 : i32) -> i32 {
- %e = emitc.expression noinline : i32 {
+ %e = emitc.expression %arg0, %arg1, %arg2 noinline : (i32, i32, i32) -> i32 {
%a = emitc.add %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.mul %a, %arg2 : (i32, i32) -> i32
emitc.yield %b : i32
@@ -78,7 +78,7 @@ func.func @do_not_inline(%arg0: i32, %arg1: i32, %arg2 : i32) -> i32 {
// CPP-DECLTOP-NEXT: }
func.func @parentheses_for_low_precedence(%arg0: i32, %arg1: i32, %arg2: i32) -> f32 {
- %e = emitc.expression : f32 {
+ %e = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> f32 {
%a = emitc.add %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.mul %a, %arg2 : (i32, i32) -> i32
%d = emitc.cast %b : i32 to f32
@@ -95,7 +95,7 @@ func.func @parentheses_for_low_precedence(%arg0: i32, %arg1: i32, %arg2: i32) ->
// CPP-DECLTOP-NEXT: return [[VAL_3]] / ([[VAL_1]] * [[VAL_2]]);
// CPP-DECLTOP-NEXT: }
func.func @parentheses_for_same_precedence(%arg0: i32, %arg1: i32, %arg2: i32) -> i32 {
- %e = emitc.expression : i32 {
+ %e = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
@@ -145,32 +145,32 @@ func.func @parentheses_for_same_precedence(%arg0: i32, %arg1: i32, %arg2: i32) -
// CPP-DECLTOP-NEXT: }
func.func @user_with_expression_trait(%arg0: i32, %arg1: i32, %arg2: i32) -> i32 {
%c0 = "emitc.constant"() {value = 0 : i32} : () -> i32
- %e0 = emitc.expression : i32 {
+ %e0 = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
}
- %e1 = emitc.expression : i32 {
+ %e1 = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
}
- %e2 = emitc.expression : i32 {
+ %e2 = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
}
- %e3 = emitc.expression : i32 {
+ %e3 = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
}
- %e4 = emitc.expression : i32 {
+ %e4 = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
}
- %e5 = emitc.expression : i32 {
+ %e5 = emitc.expression %arg0, %arg1, %arg2 : (i32, i32, i32) -> i32 {
%0 = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%1 = emitc.div %arg2, %0 : (i32, i32) -> i32
emitc.yield %1 : i32
@@ -217,7 +217,7 @@ func.func @user_with_expression_trait(%arg0: i32, %arg1: i32, %arg2: i32) -> i32
// CPP-DECLTOP-NEXT: }
func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
- %e = emitc.expression : i1 {
+ %e = emitc.expression %arg0, %arg1, %arg2, %arg3 : (i32, i32, i32, i32) -> i1 {
%a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.call_opaque "bar" (%a, %arg2) : (i32, i32) -> (i32)
%c = emitc.sub %b, %arg3 : (i32, i32) -> i32
@@ -269,16 +269,16 @@ func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32
// CPP-DECLTOP-NEXT: }
func.func @
diff erent_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
- %e1 = emitc.expression : i32 {
+ %e1 = emitc.expression %arg2, %arg3 : (i32, i32) -> i32 {
%a = emitc.rem %arg2, %arg3 : (i32, i32) -> i32
emitc.yield %a : i32
}
- %e2 = emitc.expression : i32 {
+ %e2 = emitc.expression %arg0, %arg1, %e1 : (i32, i32, i32) -> i32 {
%a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
%b = emitc.call_opaque "bar" (%e1, %a) : (i32, i32) -> (i32)
emitc.yield %b : i32
}
- %e3 = emitc.expression : i1 {
+ %e3 = emitc.expression %arg1, %e2, %arg3 : (i32, i32, i32) -> i1 {
%c = emitc.sub %e2, %arg3 : (i32, i32) -> i32
%d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
emitc.yield %d : i1
@@ -306,7 +306,7 @@ func.func @
diff erent_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
// CPP-DECLTOP-NEXT: return [[VAL_3]];
// CPP-DECLTOP-NEXT: }
func.func @expression_with_dereference(%arg1: i32, %arg2: !emitc.ptr<i32>) -> i32 {
- %c = emitc.expression : i32 {
+ %c = emitc.expression %arg1, %arg2 : (i32, !emitc.ptr<i32>) -> i32 {
%e = emitc.sub %arg2, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
%d = emitc.apply "*"(%e) : (!emitc.ptr<i32>) -> i32
emitc.yield %d : i32
@@ -327,7 +327,7 @@ func.func @expression_with_dereference(%arg1: i32, %arg2: !emitc.ptr<i32>) -> i3
func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
%a = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue<i32>
- %c = emitc.expression : i1 {
+ %c = emitc.expression %arg1, %arg2, %a : (i32, !emitc.ptr<i32>, !emitc.lvalue<i32>) -> i1 {
%d = emitc.apply "&"(%a) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
%e = emitc.sub %d, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
%f = emitc.cmp lt, %e, %arg2 : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
@@ -353,7 +353,7 @@ func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.p
func.func @expression_with_subscript_user(%arg0: !emitc.ptr<!emitc.opaque<"void">>) -> i32 {
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
- %0 = emitc.expression : !emitc.ptr<i32> {
+ %0 = emitc.expression %arg0 : (!emitc.ptr<!emitc.opaque<"void">>) -> !emitc.ptr<i32> {
%0 = emitc.cast %arg0 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
emitc.yield %0 : !emitc.ptr<i32>
}
@@ -381,7 +381,7 @@ func.func @expression_with_load(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>)
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
%0 = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue<i32>
%ptr = emitc.subscript %arg2[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
- %result = emitc.expression : i1 {
+ %result = emitc.expression %arg0, %arg1, %0, %ptr : (i32, i32, !emitc.lvalue<i32>, !emitc.lvalue<i32>) -> i1 {
%a = emitc.load %0 : !emitc.lvalue<i32>
%b = emitc.add %a, %arg1 : (i32, i32) -> i32
%c = emitc.load %ptr : !emitc.lvalue<i32>
@@ -407,7 +407,7 @@ func.func @expression_with_load(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>)
func.func @expression_with_load_and_call(%arg0: !emitc.ptr<i32>) -> i1 {
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
%ptr = emitc.subscript %arg0[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
- %result = emitc.expression : i1 {
+ %result = emitc.expression %ptr : (!emitc.lvalue<i32>) -> i1 {
%a = emitc.load %ptr : !emitc.lvalue<i32>
%b = emitc.load %ptr : !emitc.lvalue<i32>
%c = emitc.load %ptr : !emitc.lvalue<i32>
@@ -432,7 +432,7 @@ func.func @expression_with_load_and_call(%arg0: !emitc.ptr<i32>) -> i1 {
// CPP-DECLTOP-NEXT: }
emitc.func @expression_with_call_opaque_with_args_array(%0 : i32, %1 : i32) {
- %2 = expression : i1 {
+ %2 = expression %0, %1 : (i32, i32) -> i1 {
%3 = cmp lt, %0, %1 : (i32, i32) -> i1
%4 = emitc.call_opaque "f"(%3) {"args" = [0: index]} : (i1) -> i1
yield %4 : i1
diff --git a/mlir/test/Target/Cpp/for.mlir b/mlir/test/Target/Cpp/for.mlir
index 7cd3d5d646da6..73375d57823de 100644
--- a/mlir/test/Target/Cpp/for.mlir
+++ b/mlir/test/Target/Cpp/for.mlir
@@ -2,15 +2,15 @@
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck --match-full-lines %s -check-prefix=CPP-DECLTOP
func.func @test_for(%arg0 : index, %arg1 : index, %arg2 : index) {
- %lb = emitc.expression : index {
+ %lb = emitc.expression %arg0, %arg1 : (index, index) -> index {
%a = emitc.add %arg0, %arg1 : (index, index) -> index
emitc.yield %a : index
}
- %ub = emitc.expression : index {
+ %ub = emitc.expression %arg1, %arg2 : (index, index) -> index {
%a = emitc.mul %arg1, %arg2 : (index, index) -> index
emitc.yield %a : index
}
- %step = emitc.expression : index {
+ %step = emitc.expression %arg0, %arg2 : (index, index) -> index {
%a = emitc.div %arg0, %arg2 : (index, index) -> index
emitc.yield %a : index
}
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 4e20c1fc6536a..87e4cb8715c90 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -907,7 +907,7 @@ func.func @emitc_switch_ui64() {
func.func @emitc_switch_expression() {
%x = "emitc.constant"(){value = 42 : i64} : () -> i64
- %0 = emitc.expression : i64 {
+ %0 = emitc.expression %x : (i64) -> i64 {
%a = emitc.unary_minus %x : (i64) -> i64
emitc.yield %a : i64
}
More information about the Mlir-commits
mailing list