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>:$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 { ? 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 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(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 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(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 { using OpRewritePattern::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(op); - if (applyOp && applyOp.getApplicableOperator() == "&") - continue; - - for (Value operand : op.getOperands()) { - auto usedExpression = operand.getDefiningOp(); - 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 foldedOperands; + + auto takesItsOperandsAddress = [](Operation *user) { + auto applyOp = dyn_cast(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(); + 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 7284e24776175..6787c97340bd6 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(*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(*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(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(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.ptrdiff_t - // CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression : !emitc.ptrdiff_t { + // CHECK: %[[SShiftRes:[^ ]*]] = emitc.expression %[[SC1]], %[[AmountIdx]], %[[SCmpNoExcess]], %[[SZero]] : (!emitc.ptrdiff_t, !emitc.size_t, i1, !emitc.ptrdiff_t) -> !emitc.ptrdiff_t { // CHECK-NEXT: %[[SHRSI:[^ ]*]] = bitwise_right_shift %[[SC1]], %[[AmountIdx]] : (!emitc.ptrdiff_t, !emitc.size_t) -> !emitc.ptrdiff_t // CHECK-NEXT: %[[STernary:[^ ]*]] = conditional %[[SCmpNoExcess]], %[[SHRSI]], %[[SZero]] : !emitc.ptrdiff_t // CHECK-NEXT: yield %[[STernary]] : !emitc.ptrdiff_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) -> i1 { -// CHECK: %[[VAL_3:.*]] = emitc.expression : i32 { +// CHECK: %[[VAL_3:.*]] = emitc.expression %[[VAL_2]] : (!emitc.ptr) -> i32 { // CHECK: %[[VAL_4:.*]] = apply "*"(%[[VAL_2]]) : (!emitc.ptr) -> 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) -> i1 { // CHECK: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue -// CHECK: %[[VAL_4:.*]] = emitc.expression : i1 { +// CHECK: %[[VAL_4:.*]] = emitc.expression %[[VAL_2]], %[[VAL_1]], %[[VAL_3]] : (!emitc.ptr, i32, !emitc.lvalue) -> i1 { // CHECK: %[[VAL_5:.*]] = apply "&"(%[[VAL_3]]) : (!emitc.lvalue) -> !emitc.ptr // CHECK: %[[VAL_6:.*]] = add %[[VAL_5]], %[[VAL_1]] : (!emitc.ptr, i32) -> !emitc.ptr // CHECK: %[[VAL_7:.*]] = cmp lt, %[[VAL_6]], %[[VAL_2]] : (!emitc.ptr, !emitc.ptr) -> 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) -> i1 { // CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 0 : i64}> : () -> i64 // CHECK: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue -// CHECK: %[[VAL_4:.*]] = emitc.expression : i32 { +// CHECK: %[[VAL_4:.*]] = emitc.expression %[[VAL_3]] : (!emitc.lvalue) -> i32 { // CHECK: %[[VAL_5:.*]] = load %[[VAL_3]] : // CHECK: yield %[[VAL_5]] : i32 // CHECK: } // CHECK: %[[VAL_6:.*]] = emitc.subscript %[[VAL_1]]{{\[}}%[[VAL_2]]] : (!emitc.ptr, i64) -> !emitc.lvalue -// CHECK: %[[VAL_7:.*]] = emitc.expression : i32 { +// CHECK: %[[VAL_7:.*]] = emitc.expression %[[VAL_6]] : (!emitc.lvalue) -> i32 { // CHECK: %[[VAL_8:.*]] = load %[[VAL_6]] : // 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) -> 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 %y = emitc.load %x : 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 @different_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 @different_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 { - %c = emitc.expression : i32 { + %c = emitc.expression %arg1, %arg2 : (i32, !emitc.ptr) -> i32 { %e = emitc.sub %arg2, %arg1 : (!emitc.ptr, i32) -> !emitc.ptr %d = emitc.apply "*"(%e) : (!emitc.ptr) -> i32 emitc.yield %d : i32 @@ -327,7 +327,7 @@ func.func @expression_with_dereference(%arg1: i32, %arg2: !emitc.ptr) -> i3 func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr) -> i1 { %a = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue - %c = emitc.expression : i1 { + %c = emitc.expression %arg1, %arg2, %a : (i32, !emitc.ptr, !emitc.lvalue) -> i1 { %d = emitc.apply "&"(%a) : (!emitc.lvalue) -> !emitc.ptr %e = emitc.sub %d, %arg1 : (!emitc.ptr, i32) -> !emitc.ptr %f = emitc.cmp lt, %e, %arg2 : (!emitc.ptr, !emitc.ptr) -> 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>) -> i32 { %c0 = "emitc.constant"() {value = 0 : i64} : () -> i64 - %0 = emitc.expression : !emitc.ptr { + %0 = emitc.expression %arg0 : (!emitc.ptr>) -> !emitc.ptr { %0 = emitc.cast %arg0 : !emitc.ptr> to !emitc.ptr emitc.yield %0 : !emitc.ptr } @@ -381,7 +381,7 @@ func.func @expression_with_load(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr) %c0 = "emitc.constant"() {value = 0 : i64} : () -> i64 %0 = "emitc.variable"() <{value = #emitc.opaque<"42">}> : () -> !emitc.lvalue %ptr = emitc.subscript %arg2[%c0] : (!emitc.ptr, i64) -> !emitc.lvalue - %result = emitc.expression : i1 { + %result = emitc.expression %arg0, %arg1, %0, %ptr : (i32, i32, !emitc.lvalue, !emitc.lvalue) -> i1 { %a = emitc.load %0 : !emitc.lvalue %b = emitc.add %a, %arg1 : (i32, i32) -> i32 %c = emitc.load %ptr : !emitc.lvalue @@ -407,7 +407,7 @@ func.func @expression_with_load(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr) func.func @expression_with_load_and_call(%arg0: !emitc.ptr) -> i1 { %c0 = "emitc.constant"() {value = 0 : i64} : () -> i64 %ptr = emitc.subscript %arg0[%c0] : (!emitc.ptr, i64) -> !emitc.lvalue - %result = emitc.expression : i1 { + %result = emitc.expression %ptr : (!emitc.lvalue) -> i1 { %a = emitc.load %ptr : !emitc.lvalue %b = emitc.load %ptr : !emitc.lvalue %c = emitc.load %ptr : !emitc.lvalue @@ -432,7 +432,7 @@ func.func @expression_with_load_and_call(%arg0: !emitc.ptr) -> 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 }