[Mlir-commits] [mlir] [mlir][EmitC] Model lvalues as a type in EmitC (PR #91475)
Simon Camphausen
llvmlistbot at llvm.org
Tue Aug 20 00:45:56 PDT 2024
https://github.com/simon-camp updated https://github.com/llvm/llvm-project/pull/91475
>From 4560ca4b7fddc39cc43e122e8dab7bc6875c0610 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 4 Jun 2024 11:55:43 +0000
Subject: [PATCH 01/14] Add lvalue type
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 49 ++++++--
.../mlir/Dialect/EmitC/IR/EmitCTypes.td | 27 +++++
.../MemRefToEmitC/MemRefToEmitC.cpp | 7 +-
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 38 ++++++-
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 107 +++++++++++++-----
.../EmitC/Transforms/FormExpressions.cpp | 3 +-
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 18 ++-
.../MemRefToEmitC/memref-to-emitc.mlir | 24 ++--
mlir/test/Conversion/SCFToEmitC/for.mlir | 46 ++++----
mlir/test/Conversion/SCFToEmitC/if.mlir | 22 ++--
mlir/test/Conversion/SCFToEmitC/switch.mlir | 34 +++---
mlir/test/Dialect/EmitC/invalid_ops.mlir | 92 +++++++--------
mlir/test/Dialect/EmitC/invalid_types.mlir | 66 ++++++++---
mlir/test/Dialect/EmitC/ops.mlir | 37 +++---
mlir/test/Dialect/EmitC/transforms.mlir | 48 ++------
mlir/test/Dialect/EmitC/types.mlir | 19 +++-
mlir/test/Target/Cpp/common-cpp.mlir | 17 ++-
mlir/test/Target/Cpp/expressions.mlir | 84 ++++++++------
mlir/test/Target/Cpp/for.mlir | 82 ++++++++++----
mlir/test/Target/Cpp/global.mlir | 32 ++++--
mlir/test/Target/Cpp/if.mlir | 12 +-
mlir/test/Target/Cpp/invalid.mlir | 2 +-
mlir/test/Target/Cpp/lvalue.mlir | 17 +++
mlir/test/Target/Cpp/member.mlir | 41 ++++---
mlir/test/Target/Cpp/subscript.mlir | 106 ++++++++++++-----
mlir/test/Target/Cpp/switch.mlir | 56 ++++-----
mlir/test/Target/Cpp/variable.mlir | 16 +--
27 files changed, 714 insertions(+), 388 deletions(-)
create mode 100644 mlir/test/Target/Cpp/lvalue.mlir
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 40903b4e288ca6..0f876079d978bf 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -98,7 +98,7 @@ def EmitC_ApplyOp : EmitC_Op<"apply", [CExpression]> {
}];
let arguments = (ins
Arg<StrAttr, "the operator to apply">:$applicableOperator,
- EmitCType:$operand
+ AnyTypeOf<[EmitCType, EmitC_LValueType]>:$operand
);
let results = (outs EmitCType:$result);
let assemblyFormat = [{
@@ -836,6 +836,20 @@ def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", [CExpression]> {
let assemblyFormat = "operands attr-dict `:` type(operands)";
}
+def EmitC_LValueLoadOp : EmitC_Op<"lvalue_load", [
+ TypesMatchWith<"result type matches value type of 'operand'",
+ "operand", "result",
+ "::llvm::cast<LValueType>($_self).getValue()">
+]> {
+ let summary = "load an lvalue by assigning it to a local variable";
+ let description = [{}];
+
+ let arguments = (ins EmitC_LValueType:$operand);
+ let results = (outs AnyType:$result);
+
+ let assemblyFormat = "$operand attr-dict `:` type($operand)";
+}
+
def EmitC_MulOp : EmitC_BinaryOp<"mul", [CExpression]> {
let summary = "Multiplication operation";
let description = [{
@@ -924,9 +938,9 @@ def EmitC_MemberOp : EmitC_Op<"member"> {
let arguments = (ins
Arg<StrAttr, "the member to access">:$member,
- EmitC_OpaqueType:$operand
+ EmitC_LValueOf<[EmitC_OpaqueType]>:$operand
);
- let results = (outs EmitCType);
+ let results = (outs EmitC_LValueOf<[EmitCType]>);
}
def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
@@ -945,9 +959,9 @@ def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
let arguments = (ins
Arg<StrAttr, "the member to access">:$member,
- AnyTypeOf<[EmitC_OpaqueType,EmitC_PointerType]>:$operand
+ EmitC_LValueOf<[EmitC_OpaqueType,EmitC_PointerType]>:$operand
);
- let results = (outs EmitCType);
+ let results = (outs EmitC_LValueOf<[EmitCType]>);
}
def EmitC_ConditionalOp : EmitC_Op<"conditional",
@@ -1052,7 +1066,7 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
}];
let arguments = (ins EmitC_OpaqueOrTypedAttr:$value);
- let results = (outs EmitCType);
+ let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>);
let hasVerifier = 1;
}
@@ -1122,7 +1136,7 @@ def EmitC_GetGlobalOp : EmitC_Op<"get_global",
}];
let arguments = (ins FlatSymbolRefAttr:$name);
- let results = (outs EmitCType:$result);
+ let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>:$result);
let assemblyFormat = "$name `:` type($result) attr-dict";
}
@@ -1180,7 +1194,7 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
```
}];
- let arguments = (ins EmitCType:$var, EmitCType:$value);
+ let arguments = (ins EmitC_LValueType:$var, EmitCType:$value);
let results = (outs);
let hasVerifier = 1;
@@ -1286,15 +1300,26 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
EmitC_PointerType]>,
"the value to subscript">:$value,
Variadic<EmitCType>:$indices);
- let results = (outs EmitCType:$result);
+ let results = (outs EmitC_LValueType:$result);
let builders = [
OpBuilder<(ins "TypedValue<ArrayType>":$array, "ValueRange":$indices), [{
- build($_builder, $_state, array.getType().getElementType(), array, indices);
+ build(
+ $_builder,
+ $_state,
+ emitc::LValueType::get(array.getType().getElementType()),
+ array,
+ indices
+ );
}]>,
OpBuilder<(ins "TypedValue<PointerType>":$pointer, "Value":$index), [{
- build($_builder, $_state, pointer.getType().getPointee(), pointer,
- ValueRange{index});
+ build(
+ $_builder,
+ $_state,
+ emitc::LValueType::get(pointer.getType().getPointee()),
+ pointer,
+ ValueRange{index}
+ );
}]>
];
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
index 79f6d34fc91b13..b8169f43681b54 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -84,6 +84,23 @@ def EmitC_ArrayType : EmitC_Type<"Array", "array", [ShapedTypeInterface]> {
let hasCustomAssemblyFormat = 1;
}
+def EmitC_LValueType : EmitC_Type<"LValue", "lvalue"> {
+ let summary = "EmitC lvalue type";
+
+ let description = [{
+ Values of this type can be assigned to and their address can be taken.
+ }];
+
+ let parameters = (ins "Type":$value);
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "Type":$value), [{
+ return $_get(value.getContext(), value);
+ }]>
+ ];
+ let assemblyFormat = "`<` qualified($value) `>`";
+ let genVerifyDecl = 1;
+}
+
def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> {
let summary = "EmitC opaque type";
@@ -129,6 +146,7 @@ def EmitC_PointerType : EmitC_Type<"Pointer", "ptr"> {
}]>
];
let assemblyFormat = "`<` qualified($pointee) `>`";
+ let genVerifyDecl = 1;
}
def EmitC_SignedSizeT : EmitC_Type<"SignedSizeT", "ssize_t"> {
@@ -158,4 +176,13 @@ def EmitC_SizeT : EmitC_Type<"SizeT", "size_t"> {
}];
}
+class EmitC_LValueOf<list<Type> allowedTypes> :
+ ContainerType<
+ AnyTypeOf<allowedTypes>,
+ CPred<"::llvm::isa<::mlir::emitc::LValueType>($_self)">,
+ "::llvm::cast<::mlir::emitc::LValueType>($_self).getValue()",
+ "emitc.lvalue",
+ "::mlir::emitc::LValueType"
+ >;
+
#endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index e0c421741b3055..2e8fbbad14d40e 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -137,12 +137,7 @@ struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
auto subscript = rewriter.create<emitc::SubscriptOp>(
op.getLoc(), arrayValue, operands.getIndices());
- auto noInit = emitc::OpaqueAttr::get(getContext(), "");
- auto var =
- rewriter.create<emitc::VariableOp>(op.getLoc(), resultTy, noInit);
-
- rewriter.create<emitc::AssignOp>(op.getLoc(), var, subscript);
- rewriter.replaceOp(op, var);
+ rewriter.replaceOpWithNewOp<emitc::LValueLoadOp>(op, resultTy, subscript);
return success();
}
};
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index ede811c6e1bb1e..36f7f5b2f1eb90 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -63,9 +63,10 @@ static SmallVector<Value> createVariablesForResults(T op,
for (OpResult result : op.getResults()) {
Type resultType = result.getType();
+ Type varType = emitc::LValueType::get(resultType);
emitc::OpaqueAttr noInit = emitc::OpaqueAttr::get(context, "");
emitc::VariableOp var =
- rewriter.create<emitc::VariableOp>(loc, resultType, noInit);
+ rewriter.create<emitc::VariableOp>(loc, varType, noInit);
resultVariables.push_back(var);
}
@@ -80,6 +81,14 @@ static void assignValues(ValueRange values, SmallVector<Value> &variables,
rewriter.create<emitc::AssignOp>(loc, var, value);
}
+SmallVector<Value> loadValues(const SmallVector<Value> &variables,
+ PatternRewriter &rewriter, Location loc) {
+ return llvm::map_to_vector<>(variables, [&](Value var) {
+ Type type = cast<emitc::LValueType>(var.getType()).getValue();
+ return rewriter.create<emitc::LValueLoadOp>(loc, type, var).getResult();
+ });
+}
+
static void lowerYield(SmallVector<Value> &resultVariables,
PatternRewriter &rewriter, scf::YieldOp yield) {
Location loc = yield.getLoc();
@@ -126,15 +135,26 @@ LogicalResult ForLowering::matchAndRewrite(ForOp forOp,
// Erase the auto-generated terminator for the lowered for op.
rewriter.eraseOp(loweredBody->getTerminator());
+ IRRewriter::InsertPoint ip = rewriter.saveInsertionPoint();
+ rewriter.setInsertionPointToEnd(loweredBody);
+
+ SmallVector<Value> iterArgsValues =
+ loadValues(resultVariables, rewriter, loc);
+
+ rewriter.restoreInsertionPoint(ip);
+
SmallVector<Value> replacingValues;
replacingValues.push_back(loweredFor.getInductionVar());
- replacingValues.append(resultVariables.begin(), resultVariables.end());
+ replacingValues.append(iterArgsValues.begin(), iterArgsValues.end());
rewriter.mergeBlocks(forOp.getBody(), loweredBody, replacingValues);
lowerYield(resultVariables, rewriter,
cast<scf::YieldOp>(loweredBody->getTerminator()));
- rewriter.replaceOp(forOp, resultVariables);
+ // Copy iterArgs into results after the for loop.
+ SmallVector<Value> resultValues = loadValues(resultVariables, rewriter, loc);
+
+ rewriter.replaceOp(forOp, resultValues);
return success();
}
@@ -174,7 +194,10 @@ LogicalResult IfLowering::matchAndRewrite(IfOp ifOp,
lowerRegion(resultVariables, rewriter, elseRegion, loweredElseRegion);
}
- rewriter.replaceOp(ifOp, resultVariables);
+ rewriter.setInsertionPointAfter(ifOp);
+ SmallVector<Value> results = loadValues(resultVariables, rewriter, loc);
+
+ rewriter.replaceOp(ifOp, results);
return success();
}
@@ -212,7 +235,10 @@ IndexSwitchOpLowering::matchAndRewrite(IndexSwitchOp indexSwitchOp,
lowerRegion(resultVariables, rewriter, indexSwitchOp.getDefaultRegion(),
loweredSwitch.getDefaultRegion());
- rewriter.replaceOp(indexSwitchOp, resultVariables);
+ rewriter.setInsertionPointAfter(indexSwitchOp);
+ SmallVector<Value> results = loadValues(resultVariables, rewriter, loc);
+
+ rewriter.replaceOp(indexSwitchOp, results);
return success();
}
@@ -233,4 +259,4 @@ void SCFToEmitCPass::runOnOperation() {
if (failed(
applyPartialConversion(getOperation(), target, std::move(patterns))))
signalPassFailure();
-}
+}
\ No newline at end of file
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index d731a6756ff630..6b27c8c696a58e 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -61,6 +61,9 @@ void mlir::emitc::buildTerminatedBody(OpBuilder &builder, Location loc) {
bool mlir::emitc::isSupportedEmitCType(Type type) {
if (llvm::isa<emitc::OpaqueType>(type))
return true;
+ if (auto lType = llvm::dyn_cast<emitc::LValueType>(type))
+ // lvalue types are only allowed in a few places.
+ return false;
if (auto ptrType = llvm::dyn_cast<emitc::PointerType>(type))
return isSupportedEmitCType(ptrType.getPointee());
if (auto arrayType = llvm::dyn_cast<emitc::ArrayType>(type)) {
@@ -145,6 +148,8 @@ static LogicalResult verifyInitializationAttribute(Operation *op,
<< "string attributes are not supported, use #emitc.opaque instead";
Type resultType = op->getResult(0).getType();
+ if (auto lType = dyn_cast<LValueType>(resultType))
+ resultType = lType.getValue();
Type attrType = cast<TypedAttr>(value).getType();
if (isPointerWideType(resultType) && attrType.isIndex())
@@ -196,9 +201,17 @@ LogicalResult ApplyOp::verify() {
if (applicableOperatorStr != "&" && applicableOperatorStr != "*")
return emitOpError("applicable operator is illegal");
- Operation *op = getOperand().getDefiningOp();
- if (op && dyn_cast<ConstantOp>(op))
- return emitOpError("cannot apply to constant");
+ Type operandType = getOperand().getType();
+ Type resultType = getResult().getType();
+ if (applicableOperatorStr == "&") {
+ if (!llvm::isa<emitc::LValueType>(operandType))
+ return emitOpError("operand type must be an lvalue when applying `&`");
+ if (!llvm::isa<emitc::PointerType>(resultType))
+ return emitOpError("result type must be a pointer when applying `&`");
+ } else {
+ if (!llvm::isa<emitc::PointerType>(operandType))
+ return emitOpError("operand type must be a pointer when applying `*`");
+ }
return success();
}
@@ -210,22 +223,18 @@ LogicalResult ApplyOp::verify() {
/// The assign op requires that the assigned value's type matches the
/// assigned-to variable type.
LogicalResult emitc::AssignOp::verify() {
- Value variable = getVar();
- Operation *variableDef = variable.getDefiningOp();
- if (!variableDef ||
- !llvm::isa<emitc::GetGlobalOp, emitc::MemberOp, emitc::MemberOfPtrOp,
- emitc::SubscriptOp, emitc::VariableOp>(variableDef))
- return emitOpError() << "requires first operand (" << variable
- << ") to be a get_global, member, member of pointer, "
- "subscript or variable";
-
- Value value = getValue();
- if (variable.getType() != value.getType())
- return emitOpError() << "requires value's type (" << value.getType()
- << ") to match variable's type (" << variable.getType()
- << ")";
- if (isa<ArrayType>(variable.getType()))
- return emitOpError() << "cannot assign to array type";
+ TypedValue<emitc::LValueType> variable = getVar();
+
+ if (!variable.getDefiningOp())
+ return emitOpError() << "cannot assign to block argument";
+
+ Type valueType = getValue().getType();
+ Type variableType = variable.getType().getValue();
+ if (variableType != valueType)
+ return emitOpError() << "requires value's type (" << valueType
+ << ") to match variable's type (" << variableType
+ << ")\n variable: " << variable
+ << "\n value: " << getValue() << "\n";
return success();
}
@@ -853,9 +862,10 @@ LogicalResult emitc::SubscriptOp::verify() {
}
// Check element type.
Type elementType = arrayType.getElementType();
- if (elementType != getType()) {
+ Type resultType = getType().getValue();
+ if (elementType != resultType) {
return emitOpError() << "on array operand requires element type ("
- << elementType << ") and result type (" << getType()
+ << elementType << ") and result type (" << resultType
<< ") to match";
}
return success();
@@ -879,9 +889,10 @@ LogicalResult emitc::SubscriptOp::verify() {
}
// Check pointee type.
Type pointeeType = pointerType.getPointee();
- if (pointeeType != getType()) {
+ Type resultType = getType().getValue();
+ if (pointeeType != resultType) {
return emitOpError() << "on pointer operand requires pointee type ("
- << pointeeType << ") and result type (" << getType()
+ << pointeeType << ") and result type (" << resultType
<< ") to match";
}
return success();
@@ -975,6 +986,25 @@ emitc::ArrayType::cloneWith(std::optional<ArrayRef<int64_t>> shape,
return emitc::ArrayType::get(*shape, elementType);
}
+//===----------------------------------------------------------------------===//
+// LValueType
+//===----------------------------------------------------------------------===//
+
+LogicalResult mlir::emitc::LValueType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+ mlir::Type value) {
+ // Check that the wrapped type is valid. This especially forbids nested lvalue
+ // types.
+ if (!isSupportedEmitCType(value))
+ return emitError()
+ << "!emitc.lvalue must wrap supported emitc type, but got " << value;
+
+ if (llvm::isa<emitc::ArrayType>(value))
+ return emitError() << "!emitc.lvalue cannot wrap !emitc.array type";
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// OpaqueType
//===----------------------------------------------------------------------===//
@@ -992,6 +1022,18 @@ LogicalResult mlir::emitc::OpaqueType::verify(
return success();
}
+//===----------------------------------------------------------------------===//
+// PointerType
+//===----------------------------------------------------------------------===//
+
+LogicalResult mlir::emitc::PointerType::verify(
+ llvm::function_ref<mlir::InFlightDiagnostic()> emitError, Type value) {
+ if (llvm::isa<emitc::LValueType>(value))
+ return emitError() << "pointers to lvalues are not allowed";
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//
@@ -1089,9 +1131,22 @@ GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
<< getName() << "' does not reference a valid emitc.global";
Type resultType = getResult().getType();
- if (global.getType() != resultType)
- return emitOpError("result type ")
- << resultType << " does not match type " << global.getType()
+ Type globalType = global.getType();
+
+ // global has array type
+ if (llvm::isa<ArrayType>(globalType)) {
+ if (globalType != resultType)
+ return emitOpError("on array type expects result type ")
+ << resultType << " to match type " << globalType
+ << " of the global @" << getName();
+ return success();
+ }
+
+ // global has non-array type
+ auto lvalueType = dyn_cast<LValueType>(resultType);
+ if (!lvalueType || lvalueType.getValue() != globalType)
+ return emitOpError("on non-array type expects result inner type ")
+ << lvalueType.getValue() << " to match type " << globalType
<< " of the global @" << getName();
return success();
}
diff --git a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
index 82bd031430d36c..758b8527c2fa55 100644
--- a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
+++ b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
@@ -38,7 +38,8 @@ struct FormExpressionsPass
auto matchFun = [&](Operation *op) {
if (op->hasTrait<OpTrait::emitc::CExpression>() &&
!op->getParentOfType<emitc::ExpressionOp>() &&
- op->getNumResults() == 1)
+ op->getNumResults() == 1 &&
+ isSupportedEmitCType(op->getResult(0).getType()))
createExpression(op, builder);
};
rootOp->walk(matchFun);
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 8e112e6f7dda65..7cd9032d828498 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -384,6 +384,14 @@ static LogicalResult printOperation(CppEmitter &emitter,
return emitter.emitOperand(assignOp.getValue());
}
+static LogicalResult printOperation(CppEmitter &emitter,
+ emitc::LValueLoadOp lValueLoadOp) {
+ if (failed(emitter.emitAssignPrefix(*lValueLoadOp)))
+ return failure();
+
+ return emitter.emitOperand(lValueLoadOp.getOperand());
+}
+
static LogicalResult printBinaryOperation(CppEmitter &emitter,
Operation *operation,
StringRef binaryOperator) {
@@ -1544,10 +1552,10 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::ConditionalOp, emitc::ConstantOp, emitc::DeclareFuncOp,
emitc::DivOp, emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp,
emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp,
- emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
- emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
- emitc::SwitchOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp,
- emitc::VariableOp, emitc::VerbatimOp>(
+ emitc::LValueLoadOp, emitc::LogicalAndOp, emitc::LogicalNotOp,
+ emitc::LogicalOrOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp,
+ emitc::SubOp, emitc::SwitchOp, emitc::UnaryMinusOp,
+ emitc::UnaryPlusOp, emitc::VariableOp, emitc::VerbatimOp>(
[&](auto op) { return printOperation(*this, op); })
// Func ops.
.Case<func::CallOp, func::FuncOp, func::ReturnOp>(
@@ -1675,6 +1683,8 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) {
os << "[" << dim << "]";
return success();
}
+ if (auto lType = dyn_cast<emitc::LValueType>(type))
+ return emitType(loc, lType.getValue());
if (auto pType = dyn_cast<emitc::PointerType>(type)) {
if (isa<ArrayType>(pType.getPointee()))
return emitError(loc, "cannot emit pointer to array type ") << type;
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index bc40ef48268eb0..15ffd815250d20 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -3,11 +3,11 @@
// CHECK-LABEL: memref_store
// CHECK-SAME: %[[v:.*]]: f32, %[[i:.*]]: index, %[[j:.*]]: index
func.func @memref_store(%v : f32, %i: index, %j: index) {
- // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8xf32>
+ // CHECK-NEXT: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8xf32>
%0 = memref.alloca() : memref<4x8xf32>
- // CHECK: %[[SUBSCRIPT:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> f32
- // CHECK: emitc.assign %[[v]] : f32 to %[[SUBSCRIPT:.*]] : f32
+ // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
+ // CHECK-NEXT: emitc.assign %[[v]] : f32 to %[[SUBSCRIPT]] : <f32>
memref.store %v, %0[%i, %j] : memref<4x8xf32>
return
}
@@ -17,14 +17,13 @@ func.func @memref_store(%v : f32, %i: index, %j: index) {
// CHECK-LABEL: memref_load
// CHECK-SAME: %[[i:.*]]: index, %[[j:.*]]: index
func.func @memref_load(%i: index, %j: index) -> f32 {
- // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8xf32>
+ // CHECK-NEXT: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8xf32>
%0 = memref.alloca() : memref<4x8xf32>
- // CHECK: %[[LOAD:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> f32
- // CHECK: %[[VAR:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
- // CHECK: emitc.assign %[[LOAD]] : f32 to %[[VAR]] : f32
+ // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
+ // CHECK-NEXT: %[[LOAD:.*]] = emitc.lvalue_load %[[SUBSCRIPT]] : <f32>
%1 = memref.load %0[%i, %j] : memref<4x8xf32>
- // CHECK: return %[[VAR]] : f32
+ // CHECK-NEXT: return %[[LOAD]] : f32
return %1 : f32
}
@@ -33,14 +32,15 @@ func.func @memref_load(%i: index, %j: index) -> f32 {
// CHECK-LABEL: globals
module @globals {
memref.global "private" constant @internal_global : memref<3x7xf32> = dense<4.0>
- // CHECK: emitc.global static const @internal_global : !emitc.array<3x7xf32> = dense<4.000000e+00>
+ // CHECK-NEXT: emitc.global static const @internal_global : !emitc.array<3x7xf32> = dense<4.000000e+00>
memref.global @public_global : memref<3x7xf32>
- // CHECK: emitc.global extern @public_global : !emitc.array<3x7xf32>
+ // CHECK-NEXT: emitc.global extern @public_global : !emitc.array<3x7xf32>
memref.global @uninitialized_global : memref<3x7xf32> = uninitialized
- // CHECK: emitc.global extern @uninitialized_global : !emitc.array<3x7xf32>
+ // CHECK-NEXT: emitc.global extern @uninitialized_global : !emitc.array<3x7xf32>
+ // CHECK-LABEL: use_global
func.func @use_global() {
- // CHECK: emitc.get_global @public_global : !emitc.array<3x7xf32>
+ // CHECK-NEXT: emitc.get_global @public_global : !emitc.array<3x7xf32>
%0 = memref.get_global @public_global : memref<3x7xf32>
return
}
diff --git a/mlir/test/Conversion/SCFToEmitC/for.mlir b/mlir/test/Conversion/SCFToEmitC/for.mlir
index 7e59eac3d40950..32a9dfce7f4e62 100644
--- a/mlir/test/Conversion/SCFToEmitC/for.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/for.mlir
@@ -47,16 +47,20 @@ func.func @for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> (f32, f32)
// CHECK-SAME: %[[VAL_0:.*]]: index, %[[VAL_1:.*]]: index, %[[VAL_2:.*]]: index) -> (f32, f32) {
// CHECK-NEXT: %[[VAL_3:.*]] = arith.constant 0.000000e+00 : f32
// CHECK-NEXT: %[[VAL_4:.*]] = arith.constant 1.000000e+00 : f32
-// CHECK-NEXT: %[[VAL_5:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
-// CHECK-NEXT: %[[VAL_6:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
-// CHECK-NEXT: emitc.assign %[[VAL_3]] : f32 to %[[VAL_5]] : f32
-// CHECK-NEXT: emitc.assign %[[VAL_4]] : f32 to %[[VAL_6]] : f32
-// CHECK-NEXT: emitc.for %[[VAL_9:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
-// CHECK-NEXT: %[[VAL_10:.*]] = arith.addf %[[VAL_5]], %[[VAL_6]] : f32
-// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_5]] : f32
-// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_6]] : f32
+// CHECK-NEXT: %[[VAL_5:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+// CHECK-NEXT: %[[VAL_6:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+// CHECK-NEXT: emitc.assign %[[VAL_3]] : f32 to %[[VAL_5]] : <f32>
+// CHECK-NEXT: emitc.assign %[[VAL_4]] : f32 to %[[VAL_6]] : <f32>
+// CHECK-NEXT: emitc.for %[[VAL_7:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
+// CHECK-NEXT: %[[VAL_8:.*]] = emitc.lvalue_load %[[VAL_5]] : <f32>
+// CHECK-NEXT: %[[VAL_9:.*]] = emitc.lvalue_load %[[VAL_6]] : <f32>
+// CHECK-NEXT: %[[VAL_10:.*]] = arith.addf %[[VAL_8]], %[[VAL_9]] : f32
+// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_5]] : <f32>
+// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_6]] : <f32>
// CHECK-NEXT: }
-// CHECK-NEXT: return %[[VAL_5]], %[[VAL_6]] : f32, f32
+// CHECK-NEXT: %[[VAL_11:.*]] = emitc.lvalue_load %[[VAL_5]] : <f32>
+// CHECK-NEXT: %[[VAL_12:.*]] = emitc.lvalue_load %[[VAL_6]] : <f32>
+// CHECK-NEXT: return %[[VAL_11]], %[[VAL_12]] : f32, f32
// CHECK-NEXT: }
func.func @nested_for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> f32 {
@@ -73,16 +77,20 @@ func.func @nested_for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> f32
// CHECK-LABEL: func.func @nested_for_yield(
// CHECK-SAME: %[[VAL_0:.*]]: index, %[[VAL_1:.*]]: index, %[[VAL_2:.*]]: index) -> f32 {
// CHECK-NEXT: %[[VAL_3:.*]] = arith.constant 1.000000e+00 : f32
-// CHECK-NEXT: %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
-// CHECK-NEXT: emitc.assign %[[VAL_3]] : f32 to %[[VAL_4]] : f32
-// CHECK-NEXT: emitc.for %[[VAL_6:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
-// CHECK-NEXT: %[[VAL_7:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
-// CHECK-NEXT: emitc.assign %[[VAL_4]] : f32 to %[[VAL_7]] : f32
-// CHECK-NEXT: emitc.for %[[VAL_9:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
-// CHECK-NEXT: %[[VAL_10:.*]] = arith.addf %[[VAL_7]], %[[VAL_7]] : f32
-// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_7]] : f32
+// CHECK-NEXT: %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+// CHECK-NEXT: emitc.assign %[[VAL_3]] : f32 to %[[VAL_4]] : <f32>
+// CHECK-NEXT: emitc.for %[[VAL_5:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
+// CHECK-NEXT: %[[VAL_6:.*]] = emitc.lvalue_load %[[VAL_4]] : <f32>
+// CHECK-NEXT: %[[VAL_7:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+// CHECK-NEXT: emitc.assign %[[VAL_6]] : f32 to %[[VAL_7]] : <f32>
+// CHECK-NEXT: emitc.for %[[VAL_8:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
+// CHECK-NEXT: %[[VAL_9:.*]] = emitc.lvalue_load %[[VAL_7]] : <f32>
+// CHECK-NEXT: %[[VAL_10:.*]] = arith.addf %[[VAL_9]], %[[VAL_9]] : f32
+// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_7]] : <f32>
// CHECK-NEXT: }
-// CHECK-NEXT: emitc.assign %[[VAL_7]] : f32 to %[[VAL_4]] : f32
+// CHECK-NEXT: %[[VAL_11:.*]] = emitc.lvalue_load %[[VAL_7]] : <f32>
+// CHECK-NEXT: emitc.assign %[[VAL_11]] : f32 to %[[VAL_4]] : <f32>
// CHECK-NEXT: }
-// CHECK-NEXT: return %[[VAL_4]] : f32
+// CHECK-NEXT: %[[VAL_12:.*]] = emitc.lvalue_load %[[VAL_4]] : <f32>
+// CHECK-NEXT: return %[[VAL_12]] : f32
// CHECK-NEXT: }
diff --git a/mlir/test/Conversion/SCFToEmitC/if.mlir b/mlir/test/Conversion/SCFToEmitC/if.mlir
index afc9abc761eb4c..463cf1d3d96453 100644
--- a/mlir/test/Conversion/SCFToEmitC/if.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/if.mlir
@@ -36,7 +36,7 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
// CHECK-NEXT: }
-func.func @test_if_yield(%arg0: i1, %arg1: f32) {
+func.func @test_if_yield(%arg0: i1, %arg1: f32) -> (i32, f64) {
%0 = arith.constant 0 : i8
%x, %y = scf.if %arg0 -> (i32, f64) {
%1 = emitc.call_opaque "func_true_1"(%arg1) : (f32) -> i32
@@ -47,24 +47,26 @@ func.func @test_if_yield(%arg0: i1, %arg1: f32) {
%2 = emitc.call_opaque "func_false_2"(%arg1) : (f32) -> f64
scf.yield %1, %2 : i32, f64
}
- return
+ return %x, %y : i32, f64
}
// CHECK-LABEL: func.func @test_if_yield(
// CHECK-SAME: %[[VAL_0:.*]]: i1,
-// CHECK-SAME: %[[VAL_1:.*]]: f32) {
+// CHECK-SAME: %[[VAL_1:.*]]: f32) -> (i32, f64) {
// CHECK-NEXT: %[[VAL_2:.*]] = arith.constant 0 : i8
-// CHECK-NEXT: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
-// CHECK-NEXT: %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f64
+// CHECK-NEXT: %[[VAL_3:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+// CHECK-NEXT: %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f64>
// CHECK-NEXT: emitc.if %[[VAL_0]] {
// 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: 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_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: emitc.assign %[[VAL_7]] : i32 to %[[VAL_3]] : <i32>
+// CHECK-NEXT: emitc.assign %[[VAL_8]] : f64 to %[[VAL_4]] : <f64>
// CHECK-NEXT: }
-// CHECK-NEXT: return
+// CHECK-NEXT: %[[VAL_9:.*]] = emitc.lvalue_load %[[VAL_3]] : <i32>
+// CHECK-NEXT: %[[VAL_10:.*]] = emitc.lvalue_load %[[VAL_4]] : <f64>
+// CHECK-NEXT: return %[[VAL_9]], %[[VAL_10]] : i32, f64
// CHECK-NEXT: }
diff --git a/mlir/test/Conversion/SCFToEmitC/switch.mlir b/mlir/test/Conversion/SCFToEmitC/switch.mlir
index 659d9f43963efa..54d84738bcb9ac 100644
--- a/mlir/test/Conversion/SCFToEmitC/switch.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/switch.mlir
@@ -34,21 +34,21 @@ func.func @switch_no_result(%arg0 : index) {
// CHECK-LABEL: func.func @switch_one_result(
// CHECK-SAME: %[[VAL_0:.*]]: index) {
-// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
+// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
// CHECK: emitc.switch %[[VAL_0]]
// CHECK: case 2 {
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : i32
-// CHECK: emitc.assign %[[VAL_2]] : i32 to %[[VAL_1]] : i32
+// CHECK: emitc.assign %[[VAL_2]] : i32 to %[[VAL_1]] : <i32>
// CHECK: emitc.yield
// CHECK: }
// CHECK: case 5 {
// CHECK: %[[VAL_3:.*]] = arith.constant 20 : i32
-// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : i32
+// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : <i32>
// CHECK: emitc.yield
// CHECK: }
// CHECK: default {
// CHECK: %[[VAL_4:.*]] = arith.constant 30 : i32
-// CHECK: emitc.assign %[[VAL_4]] : i32 to %[[VAL_1]] : i32
+// CHECK: emitc.assign %[[VAL_4]] : i32 to %[[VAL_1]] : <i32>
// CHECK: }
// CHECK: return
// CHECK: }
@@ -70,33 +70,35 @@ func.func @switch_one_result(%arg0 : index) {
}
// CHECK-LABEL: func.func @switch_two_results(
-// CHECK-SAME: %[[VAL_0:.*]]: index) {
-// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
-// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
+// CHECK-SAME: %[[VAL_0:.*]]: index) -> (i32, f32) {
+// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
// CHECK: emitc.switch %[[VAL_0]]
// CHECK: case 2 {
// CHECK: %[[VAL_3:.*]] = arith.constant 10 : i32
// CHECK: %[[VAL_4:.*]] = arith.constant 1.200000e+00 : f32
-// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : i32
-// CHECK: emitc.assign %[[VAL_4]] : f32 to %[[VAL_2]] : f32
+// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : <i32>
+// CHECK: emitc.assign %[[VAL_4]] : f32 to %[[VAL_2]] : <f32>
// CHECK: emitc.yield
// CHECK: }
// CHECK: case 5 {
// CHECK: %[[VAL_5:.*]] = arith.constant 20 : i32
// CHECK: %[[VAL_6:.*]] = arith.constant 2.400000e+00 : f32
-// CHECK: emitc.assign %[[VAL_5]] : i32 to %[[VAL_1]] : i32
-// CHECK: emitc.assign %[[VAL_6]] : f32 to %[[VAL_2]] : f32
+// CHECK: emitc.assign %[[VAL_5]] : i32 to %[[VAL_1]] : <i32>
+// CHECK: emitc.assign %[[VAL_6]] : f32 to %[[VAL_2]] : <f32>
// CHECK: emitc.yield
// CHECK: }
// CHECK: default {
// CHECK: %[[VAL_7:.*]] = arith.constant 30 : i32
// CHECK: %[[VAL_8:.*]] = arith.constant 3.600000e+00 : f32
-// CHECK: emitc.assign %[[VAL_7]] : i32 to %[[VAL_1]] : i32
-// CHECK: emitc.assign %[[VAL_8]] : f32 to %[[VAL_2]] : f32
+// CHECK: emitc.assign %[[VAL_7]] : i32 to %[[VAL_1]] : <i32>
+// CHECK: emitc.assign %[[VAL_8]] : f32 to %[[VAL_2]] : <f32>
// CHECK: }
-// CHECK: return
+// CHECK: %[[RES_1:.*]] = emitc.lvalue_load %[[VAL_1]] : <i32>
+// CHECK: %[[RES_2:.*]] = emitc.lvalue_load %[[VAL_2]] : <f32>
+// CHECK: return %[[RES_1]], %[[RES_2]] : i32, f32
// CHECK: }
-func.func @switch_two_results(%arg0 : index) {
+func.func @switch_two_results(%arg0 : index) -> (i32, f32) {
%0, %1 = scf.index_switch %arg0 -> i32, f32
case 2 {
%2 = arith.constant 10 : i32
@@ -113,5 +115,5 @@ func.func @switch_two_results(%arg0 : index) {
%7 = arith.constant 3.6 : f32
scf.yield %6, %7 : i32, f32
}
- return
+ return %0, %1 : i32, f32
}
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 4b5bcf46c1aab9..d3f9c5c36ff8c8 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -88,26 +88,17 @@ func.func @array_result() {
// -----
-func.func @empty_operator(%arg : i32) {
+func.func @empty_operator(%arg : !emitc.lvalue<i32>) {
// expected-error @+1 {{'emitc.apply' op applicable operator must not be empty}}
- %2 = emitc.apply ""(%arg) : (i32) -> !emitc.ptr<i32>
+ %2 = emitc.apply ""(%arg) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
return
}
// -----
-func.func @illegal_operator(%arg : i32) {
+func.func @illegal_operator(%arg : !emitc.lvalue<i32>) {
// expected-error @+1 {{'emitc.apply' op applicable operator is illegal}}
- %2 = emitc.apply "+"(%arg) : (i32) -> !emitc.ptr<i32>
- return
-}
-
-// -----
-
-func.func @illegal_operand() {
- %1 = "emitc.constant"(){value = 42: i32} : () -> i32
- // expected-error @+1 {{'emitc.apply' op cannot apply to constant}}
- %2 = emitc.apply "&"(%1) : (i32) -> !emitc.ptr<i32>
+ %2 = emitc.apply "+"(%arg) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
return
}
@@ -115,7 +106,7 @@ func.func @illegal_operand() {
func.func @var_attribute_return_type_1() {
// expected-error @+1 {{'emitc.variable' op requires attribute to either be an #emitc.opaque attribute or it's type ('i64') to match the op's result type ('i32')}}
- %c0 = "emitc.variable"(){value = 42: i64} : () -> i32
+ %c0 = "emitc.variable"(){value = 42: i64} : () -> !emitc.lvalue<i32>
return
}
@@ -123,7 +114,7 @@ func.func @var_attribute_return_type_1() {
func.func @var_attribute_return_type_2() {
// expected-error @+1 {{'emitc.variable' op attribute 'value' failed to satisfy constraint: An opaque attribute or TypedAttr instance}}
- %c0 = "emitc.variable"(){value = unit} : () -> i32
+ %c0 = "emitc.variable"(){value = unit} : () -> !emitc.lvalue<i32>
return
}
@@ -234,18 +225,18 @@ func.func @test_misplaced_yield() {
// -----
-func.func @test_assign_to_non_variable(%arg1: f32, %arg2: f32) {
- // expected-error @+1 {{'emitc.assign' op requires first operand (<block argument> of type 'f32' at index: 1) to be a get_global, member, member of pointer, subscript or variable}}
- emitc.assign %arg1 : f32 to %arg2 : f32
+func.func @test_assign_to_non_variable(%arg1: f32, %arg2: !emitc.lvalue<f32>) {
+ // expected-error @+1 {{'emitc.assign' op cannot assign to block argument}}
+ emitc.assign %arg1 : f32 to %arg2 : !emitc.lvalue<f32>
return
}
// -----
func.func @test_assign_type_mismatch(%arg1: f32) {
- %v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
+ %v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
// expected-error @+1 {{'emitc.assign' op requires value's type ('f32') to match variable's type ('i32')}}
- emitc.assign %arg1 : f32 to %v : i32
+ emitc.assign %arg1 : f32 to %v : !emitc.lvalue<i32>
return
}
@@ -253,7 +244,7 @@ func.func @test_assign_type_mismatch(%arg1: f32) {
func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) {
%v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi32>
- // expected-error @+1 {{'emitc.assign' op cannot assign to array type}}
+ // expected-error @+1 {{invalid kind of Type specified}}
emitc.assign %arg1 : !emitc.array<4xi32> to %v : !emitc.array<4xi32>
return
}
@@ -273,8 +264,9 @@ 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 {
- %x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
- emitc.yield %x : i32
+ %x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %y = emitc.lvalue_load %x : <i32>
+ emitc.yield %y : i32
}
return %r : i32
}
@@ -392,7 +384,7 @@ func.func @logical_or_resulterror(%arg0: i32, %arg1: i32) {
func.func @test_subscript_array_indices_mismatch(%arg0: !emitc.array<4x8xf32>, %arg1: index) {
// expected-error @+1 {{'emitc.subscript' op on array operand requires number of indices (1) to match the rank of the array type (2)}}
- %0 = emitc.subscript %arg0[%arg1] : (!emitc.array<4x8xf32>, index) -> f32
+ %0 = emitc.subscript %arg0[%arg1] : (!emitc.array<4x8xf32>, index) -> !emitc.lvalue<f32>
return
}
@@ -400,7 +392,7 @@ func.func @test_subscript_array_indices_mismatch(%arg0: !emitc.array<4x8xf32>, %
func.func @test_subscript_array_index_type_mismatch(%arg0: !emitc.array<4x8xf32>, %arg1: index, %arg2: f32) {
// expected-error @+1 {{'emitc.subscript' op on array operand requires index operand 1 to be integer-like, but got 'f32'}}
- %0 = emitc.subscript %arg0[%arg1, %arg2] : (!emitc.array<4x8xf32>, index, f32) -> f32
+ %0 = emitc.subscript %arg0[%arg1, %arg2] : (!emitc.array<4x8xf32>, index, f32) -> !emitc.lvalue<f32>
return
}
@@ -408,7 +400,7 @@ func.func @test_subscript_array_index_type_mismatch(%arg0: !emitc.array<4x8xf32>
func.func @test_subscript_array_type_mismatch(%arg0: !emitc.array<4x8xf32>, %arg1: index, %arg2: index) {
// expected-error @+1 {{'emitc.subscript' op on array operand requires element type ('f32') and result type ('i32') to match}}
- %0 = emitc.subscript %arg0[%arg1, %arg2] : (!emitc.array<4x8xf32>, index, index) -> i32
+ %0 = emitc.subscript %arg0[%arg1, %arg2] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<i32>
return
}
@@ -416,7 +408,7 @@ func.func @test_subscript_array_type_mismatch(%arg0: !emitc.array<4x8xf32>, %arg
func.func @test_subscript_ptr_indices_mismatch(%arg0: !emitc.ptr<f32>, %arg1: index) {
// expected-error @+1 {{'emitc.subscript' op on pointer operand requires one index operand, but got 2}}
- %0 = emitc.subscript %arg0[%arg1, %arg1] : (!emitc.ptr<f32>, index, index) -> f32
+ %0 = emitc.subscript %arg0[%arg1, %arg1] : (!emitc.ptr<f32>, index, index) -> !emitc.lvalue<f32>
return
}
@@ -424,7 +416,7 @@ func.func @test_subscript_ptr_indices_mismatch(%arg0: !emitc.ptr<f32>, %arg1: in
func.func @test_subscript_ptr_index_type_mismatch(%arg0: !emitc.ptr<f32>, %arg1: f64) {
// expected-error @+1 {{'emitc.subscript' op on pointer operand requires index operand to be integer-like, but got 'f64'}}
- %0 = emitc.subscript %arg0[%arg1] : (!emitc.ptr<f32>, f64) -> f32
+ %0 = emitc.subscript %arg0[%arg1] : (!emitc.ptr<f32>, f64) -> !emitc.lvalue<f32>
return
}
@@ -432,7 +424,7 @@ func.func @test_subscript_ptr_index_type_mismatch(%arg0: !emitc.ptr<f32>, %arg1:
func.func @test_subscript_ptr_type_mismatch(%arg0: !emitc.ptr<f32>, %arg1: index) {
// expected-error @+1 {{'emitc.subscript' op on pointer operand requires pointee type ('f32') and result type ('f64') to match}}
- %0 = emitc.subscript %arg0[%arg1] : (!emitc.ptr<f32>, index) -> f64
+ %0 = emitc.subscript %arg0[%arg1] : (!emitc.ptr<f32>, index) -> !emitc.lvalue<f64>
return
}
@@ -443,34 +435,44 @@ emitc.global extern static @uninit : i32
// -----
-emitc.global @myglobal : !emitc.array<2xf32>
+emitc.global @myglobal_array : !emitc.array<2xf32>
+
+func.func @use_global() {
+ // expected-error @+1 {{'emitc.get_global' op on array type expects result type '!emitc.array<3xf32>' to match type '!emitc.array<2xf32>' of the global @myglobal_array}}
+ %0 = emitc.get_global @myglobal_array : !emitc.array<3xf32>
+ return
+}
+
+// -----
+
+emitc.global @myglobal_scalar : f32
func.func @use_global() {
- // expected-error @+1 {{'emitc.get_global' op result type 'f32' does not match type '!emitc.array<2xf32>' of the global @myglobal}}
- %0 = emitc.get_global @myglobal : f32
+ // expected-error @+1 {{'emitc.get_global' op on non-array type expects result inner type 'i32' to match type 'f32' of the global @myglobal_scalar}}
+ %0 = emitc.get_global @myglobal_scalar : !emitc.lvalue<i32>
return
}
// -----
-func.func @member(%arg0: i32) {
- // expected-error @+1 {{'emitc.member' op operand #0 must be EmitC opaque type, but got 'i32'}}
- %0 = "emitc.member" (%arg0) {member = "a"} : (i32) -> i32
+func.func @member(%arg0: !emitc.lvalue<i32>) {
+ // expected-error @+1 {{'emitc.member' op operand #0 must be emitc.lvalue of EmitC opaque type values, but got '!emitc.lvalue<i32>'}}
+ %0 = "emitc.member" (%arg0) {member = "a"} : (!emitc.lvalue<i32>) -> !emitc.lvalue<i32>
return
}
// -----
-func.func @member_of_ptr(%arg0: i32) {
- // expected-error @+1 {{'emitc.member_of_ptr' op operand #0 must be EmitC opaque type or EmitC pointer type, but got 'i32}}
- %0 = "emitc.member_of_ptr" (%arg0) {member = "a"} : (i32) -> i32
+func.func @member_of_ptr(%arg0: !emitc.lvalue<i32>) {
+ // expected-error @+1 {{'emitc.member_of_ptr' op operand #0 must be emitc.lvalue of EmitC opaque type or EmitC pointer type values, but got '!emitc.lvalue<i32>'}}
+ %0 = "emitc.member_of_ptr" (%arg0) {member = "a"} : (!emitc.lvalue<i32>) -> !emitc.lvalue<i32>
return
}
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+ %0 = "emitc.constant"(){value = 1 : i16} : () -> i16
// expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
emitc.switch %0 : i16
@@ -482,7 +484,7 @@ func.func @emitc_switch() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -492,7 +494,7 @@ func.func @emitc_switch() {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
+ %0 = "emitc.constant"(){value = 1 : i32} : () -> i32
emitc.switch %0 : i32
case 2 {
@@ -505,7 +507,7 @@ func.func @emitc_switch() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -515,7 +517,7 @@ func.func @emitc_switch() {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i8} : () -> i8
+ %0 = "emitc.constant"(){value = 1 : i8} : () -> i8
emitc.switch %0 : i8
case 2 {
@@ -533,7 +535,7 @@ func.func @emitc_switch() {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i64} : () -> i64
+ %0 = "emitc.constant"(){value = 1 : i64} : () -> i64
// expected-error at +1 {{'emitc.switch' op has duplicate case value: 2}}
emitc.switch %0 : i64
@@ -546,7 +548,7 @@ func.func @emitc_switch() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
diff --git a/mlir/test/Dialect/EmitC/invalid_types.mlir b/mlir/test/Dialect/EmitC/invalid_types.mlir
index 9bf0c49e7199a9..302a345c7c4f42 100644
--- a/mlir/test/Dialect/EmitC/invalid_types.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_types.mlir
@@ -84,6 +84,14 @@ func.func @illegal_array_with_tensor_element_type(
// -----
+func.func @illegal_array_with_lvalue_element_type(
+ // expected-error @+1 {{invalid array element type}}
+ %arg0: !emitc.array<4x!emitc.lvalue<i32>>
+) {
+}
+
+// -----
+
func.func @illegal_integer_type(%arg0: i11, %arg1: i11) -> i11 {
// expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point type supported by EmitC or integer, index or opaque type supported by EmitC, but got 'i11'}}
%mul = "emitc.mul" (%arg0, %arg1) : (i11, i11) -> i11
@@ -100,48 +108,80 @@ func.func @illegal_float_type(%arg0: f80, %arg1: f80) {
// -----
-func.func @illegal_pointee_type() {
- // expected-error @+1 {{'emitc.variable' op result #0 must be type supported by EmitC, but got '!emitc.ptr<i11>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.ptr<i11>
+func.func @illegal_lvalue_type_1() {
+ // expected-error @+1 {{!emitc.lvalue cannot wrap !emitc.array type}}
+ %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<!emitc.array<1xi32>>
+ return
+}
+
+// -----
+
+func.func @illegal_lvalue_type_2() {
+ // expected-error @+1 {{!emitc.lvalue must wrap supported emitc type, but got '!emitc.lvalue<i32>'}}
+ %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<!emitc.lvalue<i32>>
+ return
+}
+
+// -----
+
+func.func @illegal_lvalue_type_3() {
+ // expected-error @+1 {{!emitc.lvalue must wrap supported emitc type, but got 'i17'}}
+ %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i17>
+ return
+}
+
+// -----
+
+func.func @illegal_pointee_type_1() {
+ // expected-error @+1 {{'emitc.constant' op result #0 must be type supported by EmitC, but got '!emitc.ptr<i11>'}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"{}">} : () -> !emitc.ptr<i11>
+ return
+}
+
+// -----
+
+func.func @illegal_pointee_type_2() {
+ // expected-error @+1 {{pointers to lvalues are not allowed}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"NULL">} : () -> !emitc.ptr<!emitc.lvalue<i32>>
return
}
// -----
func.func @illegal_non_static_tensor_shape_type() {
- // expected-error @+1 {{'emitc.variable' op result #0 must be type supported by EmitC, but got 'tensor<?xf32>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> tensor<?xf32>
+ // expected-error @+1 {{'emitc.constant' op result #0 must be type supported by EmitC, but got 'tensor<?xf32>'}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"{}">} : () -> tensor<?xf32>
return
}
// -----
func.func @illegal_tensor_array_element_type() {
- // expected-error @+1 {{'emitc.variable' op result #0 must be type supported by EmitC, but got 'tensor<!emitc.array<9xi16>>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> tensor<!emitc.array<9xi16>>
+ // expected-error @+1 {{'emitc.constant' op result #0 must be type supported by EmitC, but got 'tensor<!emitc.array<9xi16>>'}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"{}">} : () -> tensor<!emitc.array<9xi16>>
return
}
// -----
func.func @illegal_tensor_integer_element_type() {
- // expected-error @+1 {{'emitc.variable' op result #0 must be type supported by EmitC, but got 'tensor<9xi11>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> tensor<9xi11>
+ // expected-error @+1 {{'emitc.constant' op result #0 must be type supported by EmitC, but got 'tensor<9xi11>'}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"{}">} : () -> tensor<9xi11>
return
}
// -----
func.func @illegal_tuple_array_element_type() {
- // expected-error @+1 {{'emitc.variable' op result #0 must be type supported by EmitC, but got 'tuple<!emitc.array<9xf32>, f32>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> tuple<!emitc.array<9xf32>, f32>
+ // expected-error @+1 {{'emitc.constant' op result #0 must be type supported by EmitC, but got 'tuple<!emitc.array<9xf32>, f32>'}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"{}">} : () -> tuple<!emitc.array<9xf32>, f32>
return
}
// -----
func.func @illegal_tuple_float_element_type() {
- // expected-error @+1 {{'emitc.variable' op result #0 must be type supported by EmitC, but got 'tuple<i32, f80>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> tuple<i32, f80>
+ // expected-error @+1 {{'emitc.constant' op result #0 must be type supported by EmitC, but got 'tuple<i32, f80>'}}
+ %v = "emitc.constant"(){value = #emitc.opaque<"{}">} : () -> tuple<i32, f80>
return
}
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index 64f22e8ad6b983..e72fc74a740029 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -47,9 +47,9 @@ func.func @c() {
return
}
-func.func @a(%arg0: i32, %arg1: i32) {
- %1 = "emitc.apply"(%arg0) {applicableOperator = "&"} : (i32) -> !emitc.ptr<i32>
- %2 = emitc.apply "&"(%arg1) : (i32) -> !emitc.ptr<i32>
+func.func @a(%arg0: !emitc.lvalue<i32>, %arg1: !emitc.lvalue<i32>) {
+ %1 = "emitc.apply"(%arg0) {applicableOperator = "&"} : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %2 = emitc.apply "&"(%arg1) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
return
}
@@ -173,8 +173,8 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
}
func.func @test_assign(%arg1: f32) {
- %v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
- emitc.assign %arg1 : f32 to %v : f32
+ %v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+ emitc.assign %arg1 : f32 to %v : !emitc.lvalue<f32>
return
}
@@ -218,9 +218,9 @@ func.func @test_for_not_index_induction(%arg0 : i16, %arg1 : i16, %arg2 : i16) {
}
func.func @test_subscript(%arg0 : !emitc.array<2x3xf32>, %arg1 : !emitc.ptr<i32>, %arg2 : !emitc.opaque<"std::map<char, int>">, %idx0 : index, %idx1 : i32, %idx2 : !emitc.opaque<"char">) {
- %0 = emitc.subscript %arg0[%idx0, %idx1] : (!emitc.array<2x3xf32>, index, i32) -> f32
- %1 = emitc.subscript %arg1[%idx0] : (!emitc.ptr<i32>, index) -> i32
- %2 = emitc.subscript %arg2[%idx2] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.opaque<"int">
+ %0 = emitc.subscript %arg0[%idx0, %idx1] : (!emitc.array<2x3xf32>, index, i32) -> !emitc.lvalue<f32>
+ %1 = emitc.subscript %arg1[%idx0] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+ %2 = emitc.subscript %arg2[%idx2] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.lvalue<!emitc.opaque<"int">>
return
}
@@ -245,25 +245,26 @@ emitc.global const @myconstant : !emitc.array<2xi16> = dense<2>
func.func @use_global(%i: index) -> f32 {
%0 = emitc.get_global @myglobal : !emitc.array<2xf32>
- %1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> f32
- return %1 : f32
+ %1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> !emitc.lvalue<f32>
+ %2 = emitc.lvalue_load %1 : <f32>
+ return %2 : f32
}
func.func @assign_global(%arg0 : i32) {
- %0 = emitc.get_global @myglobal_int : i32
- emitc.assign %arg0 : i32 to %0 : i32
+ %0 = emitc.get_global @myglobal_int : !emitc.lvalue<i32>
+ emitc.assign %arg0 : i32 to %0 : !emitc.lvalue<i32>
return
}
-func.func @member_access(%arg0: !emitc.opaque<"mystruct">, %arg1: !emitc.opaque<"mystruct_ptr">, %arg2: !emitc.ptr<!emitc.opaque<"mystruct">>) {
- %0 = "emitc.member" (%arg0) {member = "a"} : (!emitc.opaque<"mystruct">) -> i32
- %1 = "emitc.member_of_ptr" (%arg1) {member = "a"} : (!emitc.opaque<"mystruct_ptr">) -> i32
- %2 = "emitc.member_of_ptr" (%arg2) {member = "a"} : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
+func.func @member_access(%arg0: !emitc.lvalue<!emitc.opaque<"mystruct">>, %arg1: !emitc.lvalue<!emitc.opaque<"mystruct_ptr">>, %arg2: !emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) {
+ %0 = "emitc.member" (%arg0) {member = "a"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
+ %1 = "emitc.member_of_ptr" (%arg1) {member = "a"} : (!emitc.lvalue<!emitc.opaque<"mystruct_ptr">>) -> !emitc.lvalue<i32>
+ %2 = "emitc.member_of_ptr" (%arg2) {member = "a"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
return
}
func.func @switch() {
- %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ptrdiff_t
+ %0 = "emitc.constant"(){value = 1 : index} : () -> !emitc.ptrdiff_t
emitc.switch %0 : !emitc.ptrdiff_t
case 1 {
@@ -275,7 +276,7 @@ func.func @switch() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
}
diff --git a/mlir/test/Dialect/EmitC/transforms.mlir b/mlir/test/Dialect/EmitC/transforms.mlir
index a5c582be4aa7f6..996fd327f7af78 100644
--- a/mlir/test/Dialect/EmitC/transforms.mlir
+++ b/mlir/test/Dialect/EmitC/transforms.mlir
@@ -64,50 +64,24 @@ func.func @expression_with_call(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
return %c : i1
}
-// 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_4:.*]] = emitc.apply "*"(%[[VAL_2]]) : (!emitc.ptr<i32>) -> i32
-// CHECK: emitc.yield %[[VAL_4]] : i32
-// CHECK: }
-// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 {
-// CHECK: %[[VAL_6:.*]] = emitc.mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32
-// CHECK: %[[VAL_7:.*]] = emitc.cmp lt, %[[VAL_6]], %[[VAL_3]] : (i32, i32) -> i1
+// CHECK-LABEL: func.func @expression_with_address_taken(
+// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: !emitc.ptr<i32>, %[[VAL_3:.*]]: !emitc.lvalue<i32>) -> i1 {
+// CHECK: %[[VAL_4:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_5:.*]] = emitc.apply "&"(%[[VAL_3]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+// CHECK: %[[VAL_6:.*]] = emitc.add %[[VAL_5]], %[[VAL_1]] : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
+// CHECK: %[[VAL_7:.*]] = emitc.cmp lt, %[[VAL_6]], %[[VAL_2]] : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
// CHECK: emitc.yield %[[VAL_7]] : i1
// CHECK: }
-// CHECK: return %[[VAL_5]] : i1
+// CHECK: return %[[VAL_4]] : i1
// CHECK: }
-func.func @expression_with_dereference(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
- %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
- %b = emitc.apply "*"(%arg2) : (!emitc.ptr<i32>) -> (i32)
- %c = emitc.cmp lt, %a, %b :(i32, i32) -> i1
+func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>, %arg3: !emitc.lvalue<i32>) -> i1 {
+ %a = emitc.apply "&"(%arg3) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %b = emitc.add %a, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
+ %c = emitc.cmp lt, %b, %arg2 :(!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
return %c : i1
}
-// 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.expression : i32 {
-// CHECK: %[[VAL_4:.*]] = emitc.rem %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32
-// CHECK: emitc.yield %[[VAL_4]] : i32
-// CHECK: }
-// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 {
-// CHECK: %[[VAL_6:.*]] = emitc.apply "&"(%[[VAL_3]]) : (i32) -> !emitc.ptr<i32>
-// CHECK: %[[VAL_7:.*]] = emitc.add %[[VAL_6]], %[[VAL_1]] : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
-// CHECK: %[[VAL_8:.*]] = emitc.cmp lt, %[[VAL_7]], %[[VAL_2]] : (!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
-// CHECK: emitc.yield %[[VAL_8]] : i1
-// CHECK: }
-// CHECK: return %[[VAL_5]] : i1
-// CHECK: }
-
-func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
- %a = emitc.rem %arg0, %arg1 : (i32, i32) -> (i32)
- %b = emitc.apply "&"(%a) : (i32) -> !emitc.ptr<i32>
- %c = emitc.add %b, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
- %d = emitc.cmp lt, %c, %arg2 :(!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
- return %d : i1
-}
-
// CHECK-LABEL: func.func @no_nested_expression(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32) -> i1 {
// CHECK: %[[VAL_2:.*]] = emitc.expression : i1 {
diff --git a/mlir/test/Dialect/EmitC/types.mlir b/mlir/test/Dialect/EmitC/types.mlir
index 66947a97e1f9fe..e3462bffc5b0de 100644
--- a/mlir/test/Dialect/EmitC/types.mlir
+++ b/mlir/test/Dialect/EmitC/types.mlir
@@ -1,6 +1,6 @@
-// RUN: mlir-opt -verify-diagnostics %s | FileCheck %s
+// RUN: mlir-opt -verify-diagnostics -allow-unregistered-dialect %s | FileCheck %s
// check parser
-// RUN: mlir-opt -verify-diagnostics %s | mlir-opt -verify-diagnostics | FileCheck %s
+// RUN: mlir-opt -verify-diagnostics -allow-unregistered-dialect %s | mlir-opt -verify-diagnostics --allow-unregistered-dialect | FileCheck %s
// CHECK-LABEL: func @array_types(
func.func @array_types(
@@ -22,6 +22,21 @@ func.func @array_types(
return
}
+// CHECK-LABEL: func @lvalue_types(
+func.func @lvalue_types() {
+ // CHECK-NEXT: !emitc.lvalue<i32>
+ %0 = "typed.result"() : () -> (!emitc.lvalue<i32>)
+ // CHECK-NEXT: !emitc.lvalue<f64>
+ %2 = "typed.result"() : () -> (!emitc.lvalue<f64>)
+ // CHECK-NEXT: !emitc.lvalue<index>
+ %3 = "typed.result"() : () -> (!emitc.lvalue<index>)
+ // CHECK-NEXT: !emitc.lvalue<!emitc.ptr<i32>>
+ %4 = "typed.result"() : () -> (!emitc.lvalue<!emitc.ptr<i32>>)
+ // CHECK-NEXT: !emitc.lvalue<!emitc.opaque<"int">>
+ %5 = "typed.result"() : () -> (!emitc.lvalue<!emitc.opaque<"int">>)
+ return
+}
+
// CHECK-LABEL: func @opaque_types() {
func.func @opaque_types() {
// CHECK-NEXT: !emitc.opaque<"int">
diff --git a/mlir/test/Target/Cpp/common-cpp.mlir b/mlir/test/Target/Cpp/common-cpp.mlir
index 0e24bdd19993f0..8af29531905ba4 100644
--- a/mlir/test/Target/Cpp/common-cpp.mlir
+++ b/mlir/test/Target/Cpp/common-cpp.mlir
@@ -82,11 +82,18 @@ func.func @opaque_types(%arg0: !emitc.opaque<"bool">, %arg1: !emitc.opaque<"char
return %2 : !emitc.opaque<"status_t">
}
-func.func @apply(%arg0: i32) -> !emitc.ptr<i32> {
- // CHECK: int32_t* [[V2]] = &[[V1]];
- %0 = emitc.apply "&"(%arg0) : (i32) -> !emitc.ptr<i32>
- // CHECK: int32_t [[V3]] = *[[V2]];
- %1 = emitc.apply "*"(%0) : (!emitc.ptr<i32>) -> (i32)
+// CHECK-LABEL: int32_t* apply(
+// CHECK-SAME: int32_t [[V1:[^ ]*]]) {
+func.func @apply(%arg0: !emitc.lvalue<i32>) -> !emitc.ptr<i32> {
+ // CHECK-NEXT: int32_t* [[V2:[^ ]*]] = &[[V1]];
+ %0 = emitc.apply "&"(%arg0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ // CHECK-NEXT: int32_t [[V3:[^ ]*]];
+ %2 = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
+ // CHECK-NEXT: int32_t [[V4:[^ ]*]] = *[[V2]];
+ %1 = emitc.apply "*"(%0) : (!emitc.ptr<i32>) -> i32
+ // CHECK-NEXT: [[V3]] = [[V4]];
+ emitc.assign %1 : i32 to %2 : !emitc.lvalue<i32>
+ // CHECK-NEXT: return [[V2]];
return %0 : !emitc.ptr<i32>
}
diff --git a/mlir/test/Target/Cpp/expressions.mlir b/mlir/test/Target/Cpp/expressions.mlir
index caa0a340d3e0ad..d9455e8e98177d 100644
--- a/mlir/test/Target/Cpp/expressions.mlir
+++ b/mlir/test/Target/Cpp/expressions.mlir
@@ -9,12 +9,14 @@
// CPP-DEFAULT-NEXT: } else {
// CPP-DEFAULT-NEXT: [[VAL_6]] = [[VAL_1]];
// CPP-DEFAULT-NEXT: }
-// CPP-DEFAULT-NEXT: return [[VAL_6]];
+// CPP-DEFAULT-NEXT: int32_t [[VAL_7:v[0-9]+]] = [[VAL_6]];
+// CPP-DEFAULT-NEXT: return [[VAL_7]];
// CPP-DEFAULT-NEXT: }
// CPP-DECLTOP: int32_t single_use(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
// CPP-DECLTOP-NEXT: bool [[VAL_5:v[0-9]+]];
// CPP-DECLTOP-NEXT: int32_t [[VAL_6:v[0-9]+]];
+// CPP-DECLTOP-NEXT: int32_t [[VAL_7:v[0-9]+]];
// CPP-DECLTOP-NEXT: [[VAL_5]] = bar([[VAL_1]] * M_PI, [[VAL_3]]) - [[VAL_4]] < [[VAL_2]];
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: if ([[VAL_5]]) {
@@ -22,7 +24,8 @@
// CPP-DECLTOP-NEXT: } else {
// CPP-DECLTOP-NEXT: [[VAL_6]] = [[VAL_1]];
// CPP-DECLTOP-NEXT: }
-// CPP-DECLTOP-NEXT: return [[VAL_6]];
+// CPP-DECLTOP-NEXT: [[VAL_7]] = [[VAL_6]];
+// CPP-DECLTOP-NEXT: return [[VAL_7]];
// CPP-DECLTOP-NEXT: }
func.func @single_use(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
@@ -34,15 +37,16 @@ func.func @single_use(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
%d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
emitc.yield %d : i1
}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> i32
+ %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
emitc.if %e {
- emitc.assign %arg0 : i32 to %v : i32
+ emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
} else {
- emitc.assign %arg0 : i32 to %v : i32
+ emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
}
- return %v : i32
+ %v_load = emitc.lvalue_load %v : !emitc.lvalue<i32>
+ return %v_load : i32
}
// CPP-DEFAULT: int32_t do_not_inline(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]]) {
@@ -175,8 +179,8 @@ func.func @user_with_expression_trait(%arg0: i32, %arg1: i32, %arg2: i32) -> i32
%add = emitc.add %e1, %c0 : (i32, i32) -> i32
%call = emitc.call_opaque "bar" (%e2, %c0) : (i32, i32) -> (i32)
%cond = emitc.conditional %cast, %e3, %c0 : i32
- %var = "emitc.variable"() {value = #emitc.opaque<"">} : () -> i32
- emitc.assign %e4 : i32 to %var : i32
+ %var = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
+ emitc.assign %e4 : i32 to %var : !emitc.lvalue<i32>
return %e5 : i32
}
@@ -190,13 +194,15 @@ func.func @user_with_expression_trait(%arg0: i32, %arg1: i32, %arg2: i32) -> i32
// CPP-DEFAULT-NEXT: }
// CPP-DEFAULT-NEXT: bool [[VAL_7:v[0-9]+]];
// CPP-DEFAULT-NEXT: [[VAL_7]] = [[VAL_5]];
-// CPP-DEFAULT-NEXT: return [[VAL_6]];
+// CPP-DEFAULT-NEXT: int32_t [[VAL_8:v[0-9]+]] = [[VAL_6]];
+// CPP-DEFAULT-NEXT: return [[VAL_8]];
// CPP-DEFAULT-NEXT: }
// CPP-DECLTOP: int32_t multiple_uses(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
// CPP-DECLTOP-NEXT: bool [[VAL_5:v[0-9]+]];
// CPP-DECLTOP-NEXT: int32_t [[VAL_6:v[0-9]+]];
// CPP-DECLTOP-NEXT: bool [[VAL_7:v[0-9]+]];
+// CPP-DECLTOP-NEXT: int32_t [[VAL_8:v[0-9]+]];
// CPP-DECLTOP-NEXT: [[VAL_5]] = bar([[VAL_1]] * [[VAL_2]], [[VAL_3]]) - [[VAL_4]] < [[VAL_2]];
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: if ([[VAL_5]]) {
@@ -206,7 +212,8 @@ func.func @user_with_expression_trait(%arg0: i32, %arg1: i32, %arg2: i32) -> i32
// CPP-DECLTOP-NEXT: }
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: [[VAL_7]] = [[VAL_5]];
-// CPP-DECLTOP-NEXT: return [[VAL_6]];
+// CPP-DECLTOP-NEXT: [[VAL_8]] = [[VAL_6]];
+// CPP-DECLTOP-NEXT: return [[VAL_8]];
// CPP-DECLTOP-NEXT: }
func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
@@ -217,17 +224,18 @@ func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32
%d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
emitc.yield %d : i1
}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> i32
+ %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
emitc.if %e {
- emitc.assign %arg0 : i32 to %v : i32
+ emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
} else {
- emitc.assign %arg0 : i32 to %v : i32
+ emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
}
- %q = "emitc.variable"(){value = #emitc.opaque<"">} : () -> i1
- emitc.assign %e : i1 to %q : i1
- return %v : i32
+ %q = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i1>
+ emitc.assign %e : i1 to %q : !emitc.lvalue<i1>
+ %v_load = emitc.lvalue_load %v : !emitc.lvalue<i32>
+ return %v_load : i32
}
// CPP-DEFAULT: int32_t different_expressions(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
@@ -239,13 +247,15 @@ func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32
// CPP-DEFAULT-NEXT: } else {
// CPP-DEFAULT-NEXT: [[VAL_7]] = [[VAL_1]];
// CPP-DEFAULT-NEXT: }
-// CPP-DEFAULT-NEXT: return [[VAL_7]];
+// CPP-DEFAULT-NEXT: int32_t [[VAL_8:v[0-9]+]] = [[VAL_7]];
+// CPP-DEFAULT-NEXT: return [[VAL_8]];
// CPP-DEFAULT-NEXT: }
// CPP-DECLTOP: int32_t different_expressions(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t [[VAL_3:v[0-9]+]], int32_t [[VAL_4:v[0-9]+]]) {
// CPP-DECLTOP-NEXT: int32_t [[VAL_5:v[0-9]+]];
// CPP-DECLTOP-NEXT: int32_t [[VAL_6:v[0-9]+]];
// CPP-DECLTOP-NEXT: int32_t [[VAL_7:v[0-9]+]];
+// CPP-DECLTOP-NEXT: int32_t [[VAL_8:v[0-9]+]];
// CPP-DECLTOP-NEXT: [[VAL_5]] = [[VAL_3]] % [[VAL_4]];
// CPP-DECLTOP-NEXT: [[VAL_6]] = bar([[VAL_5]], [[VAL_1]] * [[VAL_2]]);
// CPP-DECLTOP-NEXT: ;
@@ -254,7 +264,8 @@ func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32
// CPP-DECLTOP-NEXT: } else {
// CPP-DECLTOP-NEXT: [[VAL_7]] = [[VAL_1]];
// CPP-DECLTOP-NEXT: }
-// CPP-DECLTOP-NEXT: return [[VAL_7]];
+// CPP-DECLTOP-NEXT: [[VAL_8]] = [[VAL_7]];
+// CPP-DECLTOP-NEXT: return [[VAL_8]];
// CPP-DECLTOP-NEXT: }
func.func @different_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
@@ -272,35 +283,33 @@ func.func @different_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
%d = emitc.cmp lt, %c, %arg1 :(i32, i32) -> i1
emitc.yield %d : i1
}
- %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> i32
+ %v = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
emitc.if %e3 {
- emitc.assign %arg0 : i32 to %v : i32
+ emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
} else {
- emitc.assign %arg0 : i32 to %v : i32
+ emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
}
- return %v : i32
+ %v_load = emitc.lvalue_load %v : !emitc.lvalue<i32>
+ return %v_load : i32
}
// CPP-DEFAULT: bool expression_with_address_taken(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) {
-// CPP-DEFAULT-NEXT: int32_t [[VAL_4:v[0-9]+]] = [[VAL_1]] % [[VAL_2]];
+// CPP-DEFAULT-NEXT: int32_t [[VAL_4:v[0-9]+]] = 42;
// CPP-DEFAULT-NEXT: return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]];
// CPP-DEFAULT-NEXT: }
// CPP-DECLTOP: bool expression_with_address_taken(int32_t [[VAL_1:v[0-9]+]], int32_t [[VAL_2:v[0-9]+]], int32_t* [[VAL_3]]) {
// CPP-DECLTOP-NEXT: int32_t [[VAL_4:v[0-9]+]];
-// CPP-DECLTOP-NEXT: [[VAL_4]] = [[VAL_1]] % [[VAL_2]];
+// CPP-DECLTOP-NEXT: [[VAL_4]] = 42;
// CPP-DECLTOP-NEXT: return &[[VAL_4]] - [[VAL_2]] < [[VAL_3]];
// CPP-DECLTOP-NEXT: }
func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
- %a = emitc.expression : i32 {
- %b = emitc.rem %arg0, %arg1 : (i32, i32) -> i32
- emitc.yield %b : i32
- }
+ %a = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue<i32>
%c = emitc.expression : i1 {
- %d = emitc.apply "&"(%a) : (i32) -> !emitc.ptr<i32>
+ %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
emitc.yield %f : i1
@@ -311,7 +320,17 @@ func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.p
// CPP-DEFAULT: int32_t expression_with_subscript_user(void* [[VAL_1:v.+]])
// CPP-DEFAULT-NEXT: int64_t [[VAL_2:v.+]] = 0;
// CPP-DEFAULT-NEXT: int32_t* [[VAL_3:v.+]] = (int32_t*) [[VAL_1]];
-// CPP-DEFAULT-NEXT: return [[VAL_3]][[[VAL_2]]];
+// CPP-DEFAULT-NEXT: int32_t [[VAL_4:v.+]] = [[VAL_3]][[[VAL_2]]];
+// CPP-DEFAULT-NEXT: return [[VAL_4]];
+
+// CPP-DECLTOP: int32_t expression_with_subscript_user(void* [[VAL_1:v.+]])
+// CPP-DECLTOP-NEXT: int64_t [[VAL_2:v.+]];
+// CPP-DECLTOP-NEXT: int32_t* [[VAL_3:v.+]];
+// CPP-DECLTOP-NEXT: int32_t [[VAL_4:v.+]];
+// CPP-DECLTOP-NEXT: [[VAL_2]] = 0;
+// CPP-DECLTOP-NEXT: [[VAL_3]] = (int32_t*) [[VAL_1]];
+// CPP-DECLTOP-NEXT: [[VAL_4]] = [[VAL_3]][[[VAL_2]]];
+// CPP-DECLTOP-NEXT: return [[VAL_4]];
func.func @expression_with_subscript_user(%arg0: !emitc.ptr<!emitc.opaque<"void">>) -> i32 {
%c0 = "emitc.constant"() {value = 0 : i64} : () -> i64
@@ -319,6 +338,7 @@ func.func @expression_with_subscript_user(%arg0: !emitc.ptr<!emitc.opaque<"void"
%0 = emitc.cast %arg0 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
emitc.yield %0 : !emitc.ptr<i32>
}
- %1 = emitc.subscript %0[%c0] : (!emitc.ptr<i32>, i64) -> i32
- return %1 : i32
+ %res = emitc.subscript %0[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
+ %res_load = emitc.lvalue_load %res : !emitc.lvalue<i32>
+ return %res_load : i32
}
diff --git a/mlir/test/Target/Cpp/for.mlir b/mlir/test/Target/Cpp/for.mlir
index af1d829113f9dd..14d3f05d6a08e0 100644
--- a/mlir/test/Target/Cpp/for.mlir
+++ b/mlir/test/Target/Cpp/for.mlir
@@ -40,17 +40,25 @@ func.func @test_for_yield() {
%s0 = "emitc.constant"() <{value = 0 : i32}> : () -> i32
%p0 = "emitc.constant"() <{value = 1.0 : f32}> : () -> f32
- %2 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
- %3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
- emitc.assign %s0 : i32 to %2 : i32
- emitc.assign %p0 : f32 to %3 : f32
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %1 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+ %2 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+ emitc.assign %s0 : i32 to %2 : !emitc.lvalue<i32>
+ emitc.assign %p0 : f32 to %3 : !emitc.lvalue<f32>
emitc.for %iter = %start to %stop step %step {
- %sn = emitc.call_opaque "add"(%2, %iter) : (i32, index) -> i32
- %pn = emitc.call_opaque "mul"(%3, %iter) : (f32, index) -> f32
- emitc.assign %sn : i32 to %2 : i32
- emitc.assign %pn : f32 to %3 : f32
+ %4 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ %sn = emitc.call_opaque "add"(%4, %iter) : (i32, index) -> i32
+ %5 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ %pn = emitc.call_opaque "mul"(%5, %iter) : (f32, index) -> f32
+ emitc.assign %sn : i32 to %2 : !emitc.lvalue<i32>
+ emitc.assign %pn : f32 to %3 : !emitc.lvalue<f32>
emitc.yield
}
+ %6 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ emitc.assign %6 : i32 to %0 : !emitc.lvalue<i32>
+ %7 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ emitc.assign %7 : f32 to %1 : !emitc.lvalue<f32>
return
}
@@ -60,16 +68,24 @@ func.func @test_for_yield() {
// CPP-DEFAULT-NEXT: size_t [[STEP:[^ ]*]] = 1;
// CPP-DEFAULT-NEXT: int32_t [[S0:[^ ]*]] = 0;
// CPP-DEFAULT-NEXT: float [[P0:[^ ]*]] = 1.000000000e+00f;
+// CPP-DEFAULT-NEXT: int32_t [[SE:[^ ]*]];
+// CPP-DEFAULT-NEXT: float [[PE:[^ ]*]];
// CPP-DEFAULT-NEXT: int32_t [[SI:[^ ]*]];
// CPP-DEFAULT-NEXT: float [[PI:[^ ]*]];
// CPP-DEFAULT-NEXT: [[SI:[^ ]*]] = [[S0]];
// CPP-DEFAULT-NEXT: [[PI:[^ ]*]] = [[P0]];
// CPP-DEFAULT-NEXT: for (size_t [[ITER:[^ ]*]] = [[START]]; [[ITER]] < [[STOP]]; [[ITER]] += [[STEP]]) {
-// CPP-DEFAULT-NEXT: int32_t [[SN:[^ ]*]] = add([[SI]], [[ITER]]);
-// CPP-DEFAULT-NEXT: float [[PN:[^ ]*]] = mul([[PI]], [[ITER]]);
+// CPP-DEFAULT-NEXT: int32_t [[SI_LOAD:[^ ]*]] = [[SI]];
+// CPP-DEFAULT-NEXT: int32_t [[SN:[^ ]*]] = add([[SI_LOAD]], [[ITER]]);
+// CPP-DEFAULT-NEXT: float [[PI_LOAD:[^ ]*]] = [[PI]];
+// CPP-DEFAULT-NEXT: float [[PN:[^ ]*]] = mul([[PI_LOAD]], [[ITER]]);
// CPP-DEFAULT-NEXT: [[SI]] = [[SN]];
// CPP-DEFAULT-NEXT: [[PI]] = [[PN]];
// CPP-DEFAULT-NEXT: }
+// CPP-DEFAULT-NEXT: int32_t [[SI_LOAD2:[^ ]*]] = [[SI]];
+// CPP-DEFAULT-NEXT: [[SE]] = [[SI_LOAD2]];
+// CPP-DEFAULT-NEXT: float [[PI_LOAD2:[^ ]*]] = [[PI]];
+// CPP-DEFAULT-NEXT: [[PE]] = [[PI_LOAD2]];
// CPP-DEFAULT-NEXT: return;
// CPP-DECLTOP: void test_for_yield() {
@@ -78,10 +94,16 @@ func.func @test_for_yield() {
// CPP-DECLTOP-NEXT: size_t [[STEP:[^ ]*]];
// CPP-DECLTOP-NEXT: int32_t [[S0:[^ ]*]];
// CPP-DECLTOP-NEXT: float [[P0:[^ ]*]];
+// CPP-DECLTOP-NEXT: int32_t [[SE:[^ ]*]];
+// CPP-DECLTOP-NEXT: float [[PE:[^ ]*]];
// CPP-DECLTOP-NEXT: int32_t [[SI:[^ ]*]];
// CPP-DECLTOP-NEXT: float [[PI:[^ ]*]];
+// CPP-DECLTOP-NEXT: int32_t [[SI_LOAD:[^ ]*]];
// CPP-DECLTOP-NEXT: int32_t [[SN:[^ ]*]];
+// CPP-DECLTOP-NEXT: float [[PI_LOAD:[^ ]*]];
// CPP-DECLTOP-NEXT: float [[PN:[^ ]*]];
+// CPP-DECLTOP-NEXT: int32_t [[SI_LOAD2:[^ ]*]];
+// CPP-DECLTOP-NEXT: float [[PI_LOAD2:[^ ]*]];
// CPP-DECLTOP-NEXT: [[START]] = 0;
// CPP-DECLTOP-NEXT: [[STOP]] = 10;
// CPP-DECLTOP-NEXT: [[STEP]] = 1;
@@ -89,14 +111,22 @@ func.func @test_for_yield() {
// CPP-DECLTOP-NEXT: [[P0]] = 1.000000000e+00f;
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: ;
-// CPP-DECLTOP-NEXT: [[SI:[^ ]*]] = [[S0]];
-// CPP-DECLTOP-NEXT: [[PI:[^ ]*]] = [[P0]];
+// CPP-DECLTOP-NEXT: ;
+// CPP-DECLTOP-NEXT: ;
+// CPP-DECLTOP-NEXT: [[SI]] = [[S0]];
+// CPP-DECLTOP-NEXT: [[PI]] = [[P0]];
// CPP-DECLTOP-NEXT: for (size_t [[ITER:[^ ]*]] = [[START]]; [[ITER]] < [[STOP]]; [[ITER]] += [[STEP]]) {
-// CPP-DECLTOP-NEXT: [[SN]] = add([[SI]], [[ITER]]);
-// CPP-DECLTOP-NEXT: [[PN]] = mul([[PI]], [[ITER]]);
+// CPP-DECLTOP-NEXT: [[SI_LOAD]] = [[SI]];
+// CPP-DECLTOP-NEXT: [[SN]] = add([[SI_LOAD]], [[ITER]]);
+// CPP-DECLTOP-NEXT: [[PI_LOAD]] = [[PI]];
+// CPP-DECLTOP-NEXT: [[PN]] = mul([[PI_LOAD]], [[ITER]]);
// CPP-DECLTOP-NEXT: [[SI]] = [[SN]];
// CPP-DECLTOP-NEXT: [[PI]] = [[PN]];
// CPP-DECLTOP-NEXT: }
+// CPP-DECLTOP-NEXT: [[SI_LOAD2]] = [[SI]];
+// CPP-DECLTOP-NEXT: [[SE]] = [[SI_LOAD2]];
+// CPP-DECLTOP-NEXT: [[PI_LOAD2]] = [[PI]];
+// CPP-DECLTOP-NEXT: [[PE]] = [[PI_LOAD2]];
// CPP-DECLTOP-NEXT: return;
func.func @test_for_yield_2() {
@@ -107,17 +137,25 @@ func.func @test_for_yield_2() {
%s0 = emitc.literal "0" : i32
%p0 = emitc.literal "M_PI" : f32
- %2 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
- %3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
- emitc.assign %s0 : i32 to %2 : i32
- emitc.assign %p0 : f32 to %3 : f32
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %1 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+ %2 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+ emitc.assign %s0 : i32 to %2 : !emitc.lvalue<i32>
+ emitc.assign %p0 : f32 to %3 : !emitc.lvalue<f32>
emitc.for %iter = %start to %stop step %step {
- %sn = emitc.call_opaque "add"(%2, %iter) : (i32, index) -> i32
- %pn = emitc.call_opaque "mul"(%3, %iter) : (f32, index) -> f32
- emitc.assign %sn : i32 to %2 : i32
- emitc.assign %pn : f32 to %3 : f32
+ %4 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ %sn = emitc.call_opaque "add"(%4, %iter) : (i32, index) -> i32
+ %5 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ %pn = emitc.call_opaque "mul"(%5, %iter) : (f32, index) -> f32
+ emitc.assign %sn : i32 to %2 : !emitc.lvalue<i32>
+ emitc.assign %pn : f32 to %3 : !emitc.lvalue<f32>
emitc.yield
}
+ %6 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ emitc.assign %6 : i32 to %0 : !emitc.lvalue<i32>
+ %7 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ emitc.assign %7 : f32 to %1 : !emitc.lvalue<f32>
return
}
diff --git a/mlir/test/Target/Cpp/global.mlir b/mlir/test/Target/Cpp/global.mlir
index bddd94aea4219c..b2d61681dbd601 100644
--- a/mlir/test/Target/Cpp/global.mlir
+++ b/mlir/test/Target/Cpp/global.mlir
@@ -38,18 +38,22 @@ emitc.global @opaque_init : !emitc.opaque<"char"> = #emitc.opaque<"CHAR_MIN">
// CPP-DECLTOP: char opaque_init = CHAR_MIN;
func.func @use_global_scalar_read() -> i32 {
- %0 = emitc.get_global @myglobal_int : i32
- return %0 : i32
+ %0 = emitc.get_global @myglobal_int : !emitc.lvalue<i32>
+ %1 = emitc.lvalue_load %0 : !emitc.lvalue<i32>
+ return %1 : i32
}
// CPP-DEFAULT-LABEL: int32_t use_global_scalar_read()
-// CPP-DEFAULT-NEXT: return myglobal_int;
+// CPP-DEFAULT-NEXT: int32_t [[V0:[^ ]*]] = myglobal_int;
+// CPP-DEFAULT-NEXT: return [[V0]];
// CPP-DECLTOP-LABEL: int32_t use_global_scalar_read()
-// CPP-DECLTOP-NEXT: return myglobal_int;
+// CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]];
+// CPP-DECLTOP-NEXT: [[V0]] = myglobal_int;
+// CPP-DECLTOP-NEXT: return [[V0]];
func.func @use_global_scalar_write(%arg0 : i32) {
- %0 = emitc.get_global @myglobal_int : i32
- emitc.assign %arg0 : i32 to %0 : i32
+ %0 = emitc.get_global @myglobal_int : !emitc.lvalue<i32>
+ emitc.assign %arg0 : i32 to %0 : !emitc.lvalue<i32>
return
}
// CPP-DEFAULT-LABEL: void use_global_scalar_write
@@ -64,21 +68,25 @@ func.func @use_global_scalar_write(%arg0 : i32) {
func.func @use_global_array_read(%i: index) -> f32 {
%0 = emitc.get_global @myglobal : !emitc.array<2xf32>
- %1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> f32
- return %1 : f32
+ %1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> !emitc.lvalue<f32>
+ %2 = emitc.lvalue_load %1 : !emitc.lvalue<f32>
+ return %2 : f32
}
// CPP-DEFAULT-LABEL: float use_global_array_read
// CPP-DEFAULT-SAME: (size_t [[V1:.*]])
-// CPP-DEFAULT-NEXT: return myglobal[[[V1]]];
+// CPP-DEFAULT-NEXT: float [[V2:.*]] = myglobal[[[V1]]];
+// CPP-DEFAULT-NEXT: return [[V2]];
// CPP-DECLTOP-LABEL: float use_global_array_read
// CPP-DECLTOP-SAME: (size_t [[V1:.*]])
-// CPP-DECLTOP-NEXT: return myglobal[[[V1]]];
+// CPP-DECLTOP-NEXT: float [[V2:.*]];
+// CPP-DECLTOP-NEXT: [[V2]] = myglobal[[[V1]]];
+// CPP-DECLTOP-NEXT: return [[V2]];
func.func @use_global_array_write(%i: index, %val : f32) {
%0 = emitc.get_global @myglobal : !emitc.array<2xf32>
- %1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> f32
- emitc.assign %val : f32 to %1 : f32
+ %1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> !emitc.lvalue<f32>
+ emitc.assign %val : f32 to %1 : !emitc.lvalue<f32>
return
}
// CPP-DEFAULT-LABEL: void use_global_array_write
diff --git a/mlir/test/Target/Cpp/if.mlir b/mlir/test/Target/Cpp/if.mlir
index 7b0e2da85d0eb2..d3b792192c8b10 100644
--- a/mlir/test/Target/Cpp/if.mlir
+++ b/mlir/test/Target/Cpp/if.mlir
@@ -50,18 +50,18 @@ func.func @test_if_else(%arg0: i1, %arg1: f32) {
func.func @test_if_yield(%arg0: i1, %arg1: f32) {
%0 = "emitc.constant"() <{value = 0 : i8}> : () -> i8
- %x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
- %y = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f64
+ %x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %y = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f64>
emitc.if %arg0 {
%1 = emitc.call_opaque "func_true_1"(%arg1) : (f32) -> i32
%2 = emitc.call_opaque "func_true_2"(%arg1) : (f32) -> f64
- emitc.assign %1 : i32 to %x : i32
- emitc.assign %2 : f64 to %y : f64
+ emitc.assign %1 : i32 to %x : !emitc.lvalue<i32>
+ emitc.assign %2 : f64 to %y : !emitc.lvalue<f64>
} else {
%1 = emitc.call_opaque "func_false_1"(%arg1) : (f32) -> i32
%2 = emitc.call_opaque "func_false_2"(%arg1) : (f32) -> f64
- emitc.assign %1 : i32 to %x : i32
- emitc.assign %2 : f64 to %y : f64
+ emitc.assign %1 : i32 to %x : !emitc.lvalue<i32>
+ emitc.assign %2 : f64 to %y : !emitc.lvalue<f64>
}
return
}
diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir
index 4e777239fba662..89f984f85347fc 100644
--- a/mlir/test/Target/Cpp/invalid.mlir
+++ b/mlir/test/Target/Cpp/invalid.mlir
@@ -83,6 +83,6 @@ func.func @array_as_result(%arg: !emitc.array<4xi8>) -> (!emitc.array<4xi8>) {
func.func @ptr_to_array() {
// expected-error at +1 {{cannot emit pointer to array type '!emitc.ptr<!emitc.array<9xi16>>'}}
- %v = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.ptr<!emitc.array<9xi16>>
+ %v = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.lvalue<!emitc.ptr<!emitc.array<9xi16>>>
return
}
diff --git a/mlir/test/Target/Cpp/lvalue.mlir b/mlir/test/Target/Cpp/lvalue.mlir
new file mode 100644
index 00000000000000..ce76dd7a7cfeb9
--- /dev/null
+++ b/mlir/test/Target/Cpp/lvalue.mlir
@@ -0,0 +1,17 @@
+// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
+
+// CHECK: int32_t lvalue_variables(
+emitc.func @lvalue_variables(%v1: i32, %v2: i32) -> i32 {
+ %val = emitc.mul %v1, %v2 : (i32, i32) -> i32
+ %variable = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32> // alloc effect
+ emitc.assign %val : i32 to %variable : !emitc.lvalue<i32> // write effect
+ %addr = emitc.apply "&"(%variable) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ emitc.call @zero (%addr) : (!emitc.ptr<i32>) -> ()
+ %updated_val = emitc.lvalue_load %variable : !emitc.lvalue<i32> // read effect, (noop in emitter?)
+ %neg_one = "emitc.constant"() {value = -1 : i32} : () -> i32
+ emitc.assign %neg_one : i32 to %variable : !emitc.lvalue<i32> // invalidates %updated_val
+ emitc.return %updated_val : i32
+ // dealloc effect through automatic allocation scope
+}
+
+emitc.func @zero(%arg0: !emitc.ptr<i32>) attributes {specifiers = ["extern"]}
\ No newline at end of file
diff --git a/mlir/test/Target/Cpp/member.mlir b/mlir/test/Target/Cpp/member.mlir
index 1b4a3dcab879da..d1c453f07cda53 100644
--- a/mlir/test/Target/Cpp/member.mlir
+++ b/mlir/test/Target/Cpp/member.mlir
@@ -1,34 +1,39 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT
-func.func @member(%arg0: !emitc.opaque<"mystruct">, %arg1: i32) {
- %0 = "emitc.member" (%arg0) {member = "a"} : (!emitc.opaque<"mystruct">) -> i32
- emitc.assign %arg1 : i32 to %0 : i32
+func.func @member(%arg0: !emitc.lvalue<!emitc.opaque<"mystruct">>, %arg1: i32) {
+ %0 = "emitc.member" (%arg0) {member = "a"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
+ emitc.assign %arg1 : i32 to %0 : !emitc.lvalue<i32>
- %1 = "emitc.member" (%arg0) {member = "b"} : (!emitc.opaque<"mystruct">) -> i32
- %2 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
- emitc.assign %1 : i32 to %2 : i32
+ %1 = "emitc.member" (%arg0) {member = "b"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
+ %2 = emitc.lvalue_load %1 : !emitc.lvalue<i32>
+ %3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ emitc.assign %2 : i32 to %3 : !emitc.lvalue<i32>
return
}
// CPP-DEFAULT: void member(mystruct [[V0:[^ ]*]], int32_t [[V1:[^ ]*]]) {
-// CPP-DEFAULT-NEXT: [[V0:[^ ]*]].a = [[V1:[^ ]*]];
-// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]];
-// CPP-DEFAULT-NEXT: [[V2:[^ ]*]] = [[V0:[^ ]*]].b;
+// CPP-DEFAULT-NEXT: [[V0]].a = [[V1]];
+// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]] = [[V0]].b;
+// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]];
+// CPP-DEFAULT-NEXT: [[V3]] = [[V2]];
-func.func @member_of_pointer(%arg0: !emitc.ptr<!emitc.opaque<"mystruct">>, %arg1: i32) {
- %0 = "emitc.member_of_ptr" (%arg0) {member = "a"} : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
- emitc.assign %arg1 : i32 to %0 : i32
+func.func @member_of_pointer(%arg0: !emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>, %arg1: i32) {
+ %0 = "emitc.member_of_ptr" (%arg0) {member = "a"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
+ emitc.assign %arg1 : i32 to %0 : !emitc.lvalue<i32>
- %1 = "emitc.member_of_ptr" (%arg0) {member = "b"} : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
- %2 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
- emitc.assign %1 : i32 to %2 : i32
+ %1 = "emitc.member_of_ptr" (%arg0) {member = "b"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
+ %2 = emitc.lvalue_load %1 : !emitc.lvalue<i32>
+ %3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ emitc.assign %2 : i32 to %3 : !emitc.lvalue<i32>
return
}
// CPP-DEFAULT: void member_of_pointer(mystruct* [[V0:[^ ]*]], int32_t [[V1:[^ ]*]]) {
-// CPP-DEFAULT-NEXT: [[V0:[^ ]*]]->a = [[V1:[^ ]*]];
-// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]];
-// CPP-DEFAULT-NEXT: [[V2:[^ ]*]] = [[V0:[^ ]*]]->b;
+// CPP-DEFAULT-NEXT: [[V0]]->a = [[V1]];
+// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]] = [[V0]]->b;
+// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]];
+// CPP-DEFAULT-NEXT: [[V3]] = [[V2]];
+
diff --git a/mlir/test/Target/Cpp/subscript.mlir b/mlir/test/Target/Cpp/subscript.mlir
index 0b388953c80d37..b5c94c146712eb 100644
--- a/mlir/test/Target/Cpp/subscript.mlir
+++ b/mlir/test/Target/Cpp/subscript.mlir
@@ -1,35 +1,59 @@
-// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
-// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s
+// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT
+// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s -check-prefix=CPP-DECLTOP
func.func @load_store_array(%arg0: !emitc.array<4x8xf32>, %arg1: !emitc.array<3x5xf32>, %arg2: index, %arg3: index) {
- %0 = emitc.subscript %arg0[%arg2, %arg3] : (!emitc.array<4x8xf32>, index, index) -> f32
- %1 = emitc.subscript %arg1[%arg2, %arg3] : (!emitc.array<3x5xf32>, index, index) -> f32
- emitc.assign %0 : f32 to %1 : f32
+ %0 = emitc.subscript %arg0[%arg2, %arg3] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
+ %1 = emitc.subscript %arg1[%arg2, %arg3] : (!emitc.array<3x5xf32>, index, index) -> !emitc.lvalue<f32>
+ %2 = emitc.lvalue_load %0 : <f32>
+ emitc.assign %2 : f32 to %1 : !emitc.lvalue<f32>
return
}
-// CHECK: void load_store_array(float [[ARR1:[^ ]*]][4][8], float [[ARR2:[^ ]*]][3][5],
-// CHECK-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]])
-// CHECK-NEXT: [[ARR2]][[[I]]][[[J]]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DEFAULT: void load_store_array(float [[ARR1:[^ ]*]][4][8], float [[ARR2:[^ ]*]][3][5],
+// CPP-DEFAULT-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]])
+// CPP-DEFAULT-NEXT: float [[VAL:[^ ]*]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DEFAULT-NEXT: [[ARR2]][[[I]]][[[J]]] = [[VAL]];
+
+// CPP-DECLTOP: void load_store_array(float [[ARR1:[^ ]*]][4][8], float [[ARR2:[^ ]*]][3][5],
+// CPP-DECLTOP-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]])
+// CPP-DECLTOP-NEXT: float [[VAL:[^ ]*]];
+// CPP-DECLTOP-NEXT: [[VAL]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DECLTOP-NEXT: [[ARR2]][[[I]]][[[J]]] = [[VAL]];
func.func @load_store_pointer(%arg0: !emitc.ptr<f32>, %arg1: !emitc.ptr<f32>, %arg2: index, %arg3: index) {
- %0 = emitc.subscript %arg0[%arg2] : (!emitc.ptr<f32>, index) -> f32
- %1 = emitc.subscript %arg1[%arg3] : (!emitc.ptr<f32>, index) -> f32
- emitc.assign %0 : f32 to %1 : f32
+ %0 = emitc.subscript %arg0[%arg2] : (!emitc.ptr<f32>, index) -> !emitc.lvalue<f32>
+ %1 = emitc.subscript %arg1[%arg3] : (!emitc.ptr<f32>, index) -> !emitc.lvalue<f32>
+ %2 = emitc.lvalue_load %0 : <f32>
+ emitc.assign %2 : f32 to %1 : <f32>
return
}
-// CHECK: void load_store_pointer(float* [[PTR1:[^ ]*]], float* [[PTR2:[^ ]*]],
-// CHECK-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]])
-// CHECK-NEXT: [[PTR2]][[[J]]] = [[PTR1]][[[I]]];
+// CPP-DEFAULT: void load_store_pointer(float* [[PTR1:[^ ]*]], float* [[PTR2:[^ ]*]],
+// CPP-DEFAULT-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]])
+// CPP-DEFAULT-NEXT: float [[VAL:[^ ]*]] = [[PTR1]][[[I]]];
+// CPP-DEFAULT-NEXT: [[PTR2]][[[J]]] = [[VAL]];
+
+// CPP-DECLTOP: void load_store_pointer(float* [[PTR1:[^ ]*]], float* [[PTR2:[^ ]*]],
+// CPP-DECLTOP-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]])
+// CPP-DECLTOP-NEXT: float [[VAL:[^ ]*]];
+// CPP-DECLTOP-NEXT: [[VAL]] = [[PTR1]][[[I]]];
+// CPP-DECLTOP-NEXT: [[PTR2]][[[J]]] = [[VAL]];
func.func @load_store_opaque(%arg0: !emitc.opaque<"std::map<char, int>">, %arg1: !emitc.opaque<"std::map<char, int>">, %arg2: !emitc.opaque<"char">, %arg3: !emitc.opaque<"char">) {
- %0 = emitc.subscript %arg0[%arg2] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.opaque<"int">
- %1 = emitc.subscript %arg1[%arg3] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.opaque<"int">
- emitc.assign %0 : !emitc.opaque<"int"> to %1 : !emitc.opaque<"int">
+ %0 = emitc.subscript %arg0[%arg2] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.lvalue<!emitc.opaque<"int">>
+ %1 = emitc.subscript %arg1[%arg3] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.lvalue<!emitc.opaque<"int">>
+ %2 = emitc.lvalue_load %0 : <!emitc.opaque<"int">>
+ emitc.assign %2 : !emitc.opaque<"int"> to %1 : <!emitc.opaque<"int">>
return
}
-// CHECK: void load_store_opaque(std::map<char, int> [[MAP1:[^ ]*]], std::map<char, int> [[MAP2:[^ ]*]],
-// CHECK-SAME: char [[I:[^ ]*]], char [[J:[^ ]*]])
-// CHECK-NEXT: [[MAP2]][[[J]]] = [[MAP1]][[[I]]];
+// CPP-DEFAULT: void load_store_opaque(std::map<char, int> [[MAP1:[^ ]*]], std::map<char, int> [[MAP2:[^ ]*]],
+// CPP-DEFAULT-SAME: char [[I:[^ ]*]], char [[J:[^ ]*]])
+// CPP-DEFAULT-NEXT: int [[VAL:[^ ]*]] = [[MAP1]][[[I]]];
+// CPP-DEFAULT-NEXT: [[MAP2]][[[J]]] = [[VAL]];
+
+// CPP-DECLTOP: void load_store_opaque(std::map<char, int> [[MAP1:[^ ]*]], std::map<char, int> [[MAP2:[^ ]*]],
+// CPP-DECLTOP-SAME: char [[I:[^ ]*]], char [[J:[^ ]*]])
+// CPP-DECLTOP-NEXT: int [[VAL:[^ ]*]];
+// CPP-DECLTOP-NEXT: [[VAL]] = [[MAP1]][[[I]]];
+// CPP-DECLTOP-NEXT: [[MAP2]][[[J]]] = [[VAL]];
emitc.func @func1(%arg0 : f32) {
emitc.return
@@ -37,16 +61,38 @@ emitc.func @func1(%arg0 : f32) {
emitc.func @call_arg(%arg0: !emitc.array<4x8xf32>, %i: i32, %j: i16,
%k: i8) {
- %0 = emitc.subscript %arg0[%i, %j] : (!emitc.array<4x8xf32>, i32, i16) -> f32
- %1 = emitc.subscript %arg0[%j, %k] : (!emitc.array<4x8xf32>, i16, i8) -> f32
+ %0 = emitc.subscript %arg0[%i, %j] : (!emitc.array<4x8xf32>, i32, i16) -> !emitc.lvalue<f32>
+ %1 = emitc.subscript %arg0[%j, %k] : (!emitc.array<4x8xf32>, i16, i8) -> !emitc.lvalue<f32>
- emitc.call @func1 (%0) : (f32) -> ()
- emitc.call_opaque "func2" (%1) : (f32) -> ()
- emitc.call_opaque "func3" (%0, %1) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ %2 = emitc.lvalue_load %0 : <f32>
+ emitc.call @func1 (%2) : (f32) -> ()
+ %3 = emitc.lvalue_load %1 : <f32>
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ %4 = emitc.lvalue_load %0 : <f32>
+ %5 = emitc.lvalue_load %1 : <f32>
+ emitc.call_opaque "func3" (%4, %5) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.return
}
-// CHECK: void call_arg(float [[ARR1:[^ ]*]][4][8], int32_t [[I:[^ ]*]],
-// CHECK-SAME: int16_t [[J:[^ ]*]], int8_t [[K:[^ ]*]])
-// CHECK-NEXT: func1([[ARR1]][[[I]]][[[J]]]);
-// CHECK-NEXT: func2([[ARR1]][[[J]]][[[K]]]);
-// CHECK-NEXT: func3([[ARR1]][[[J]]][[[K]]], [[ARR1]][[[I]]][[[J]]]);
+// CPP-DEFAULT: void call_arg(float [[ARR1:[^ ]*]][4][8], int32_t [[I:[^ ]*]],
+// CPP-DEFAULT-SAME: int16_t [[J:[^ ]*]], int8_t [[K:[^ ]*]])
+// CPP-DEFAULT-NEXT: float [[VAL0:[^ ]*]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DEFAULT-NEXT: func1([[VAL0]]);
+// CPP-DEFAULT-NEXT: float [[VAL1:[^ ]*]] = [[ARR1]][[[J]]][[[K]]];
+// CPP-DEFAULT-NEXT: func2([[VAL1]]);
+// CPP-DEFAULT-NEXT: float [[VAL2:[^ ]*]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DEFAULT-NEXT: float [[VAL3:[^ ]*]] = [[ARR1]][[[J]]][[[K]]];
+// CPP-DEFAULT-NEXT: func3([[VAL3]], [[VAL2]]);
+
+// CPP-DECLTOP: void call_arg(float [[ARR1:[^ ]*]][4][8], int32_t [[I:[^ ]*]],
+// CPP-DECLTOP-SAME: int16_t [[J:[^ ]*]], int8_t [[K:[^ ]*]])
+// CPP-DECLTOP-NEXT: float [[VAL0:[^ ]*]];
+// CPP-DECLTOP-NEXT: float [[VAL1:[^ ]*]];
+// CPP-DECLTOP-NEXT: float [[VAL2:[^ ]*]];
+// CPP-DECLTOP-NEXT: float [[VAL3:[^ ]*]];
+// CPP-DECLTOP-NEXT: [[VAL0]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DECLTOP-NEXT: func1([[VAL0]]);
+// CPP-DECLTOP-NEXT: [[VAL1]] = [[ARR1]][[[J]]][[[K]]];
+// CPP-DECLTOP-NEXT: func2([[VAL1]]);
+// CPP-DECLTOP-NEXT: [[VAL2]] = [[ARR1]][[[I]]][[[J]]];
+// CPP-DECLTOP-NEXT: [[VAL3]] = [[ARR1]][[[J]]][[[K]]];
+// CPP-DECLTOP-NEXT: func3([[VAL3]], [[VAL2]]);
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 0f2e716a98f16b..f9b8600606ec2b 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -43,7 +43,7 @@
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_ptrdiff_t() {
- %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ptrdiff_t
+ %0 = "emitc.constant"(){value = 1 : index} : () -> !emitc.ptrdiff_t
emitc.switch %0 : !emitc.ptrdiff_t
case 2 {
@@ -55,7 +55,7 @@ func.func @emitc_switch_ptrdiff_t() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
}
return
@@ -103,7 +103,7 @@ func.func @emitc_switch_ptrdiff_t() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_ssize_t() {
- %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ssize_t
+ %0 = "emitc.constant"(){value = 1 : index} : () -> !emitc.ssize_t
emitc.switch %0 : !emitc.ssize_t
case 2 {
@@ -115,7 +115,7 @@ func.func @emitc_switch_ssize_t() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -164,7 +164,7 @@ func.func @emitc_switch_ssize_t() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_size_t() {
- %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.size_t
+ %0 = "emitc.constant"(){value = 1 : index} : () -> !emitc.size_t
emitc.switch %0 : !emitc.size_t
case 2 {
@@ -176,7 +176,7 @@ func.func @emitc_switch_size_t() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -225,7 +225,7 @@ func.func @emitc_switch_size_t() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_index() {
- %0 = "emitc.variable"(){value = 1 : index} : () -> index
+ %0 = "emitc.constant"(){value = 1 : index} : () -> index
emitc.switch %0 : index
case 2 {
@@ -237,7 +237,7 @@ func.func @emitc_switch_index() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -286,7 +286,7 @@ func.func @emitc_switch_index() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_opaque() {
- %0 = "emitc.variable"() {value = #emitc.opaque<"1">}
+ %0 = "emitc.constant"() {value = #emitc.opaque<"1">}
: () -> !emitc.opaque<"size_t">
emitc.switch %0 : !emitc.opaque<"size_t">
@@ -299,7 +299,7 @@ func.func @emitc_switch_opaque() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -348,7 +348,7 @@ func.func @emitc_switch_opaque() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_i1() {
- %0 = "emitc.variable"(){value = 1 : i1} : () -> i1
+ %0 = "emitc.constant"(){value = 1 : i1} : () -> i1
emitc.switch %0 : i1
case 2 {
@@ -360,7 +360,7 @@ func.func @emitc_switch_i1() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -409,7 +409,7 @@ func.func @emitc_switch_i1() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_i8() {
- %0 = "emitc.variable"(){value = 1 : i8} : () -> i8
+ %0 = "emitc.constant"(){value = 1 : i8} : () -> i8
emitc.switch %0 : i8
case 2 {
@@ -421,7 +421,7 @@ func.func @emitc_switch_i8() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -470,7 +470,7 @@ func.func @emitc_switch_i8() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_ui8() {
- %0 = "emitc.variable"(){value = 1 : ui8} : () -> ui8
+ %0 = "emitc.constant"(){value = 1 : ui8} : () -> ui8
emitc.switch %0 : ui8
case 2 {
@@ -482,7 +482,7 @@ func.func @emitc_switch_ui8() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -531,7 +531,7 @@ func.func @emitc_switch_ui8() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_i16() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+ %0 = "emitc.constant"(){value = 1 : i16} : () -> i16
emitc.switch %0 : i16
case 2 {
@@ -543,7 +543,7 @@ func.func @emitc_switch_i16() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -592,7 +592,7 @@ func.func @emitc_switch_i16() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_ui16() {
- %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+ %0 = "emitc.constant"(){value = 1 : ui16} : () -> ui16
emitc.switch %0 : ui16
case 2 {
@@ -604,7 +604,7 @@ func.func @emitc_switch_ui16() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -653,7 +653,7 @@ func.func @emitc_switch_ui16() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_i32() {
- %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
+ %0 = "emitc.constant"(){value = 1 : i32} : () -> i32
emitc.switch %0 : i32
case 2 {
@@ -665,7 +665,7 @@ func.func @emitc_switch_i32() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -714,7 +714,7 @@ func.func @emitc_switch_i32() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_ui32() {
- %0 = "emitc.variable"(){value = 1 : ui32} : () -> ui32
+ %0 = "emitc.constant"(){value = 1 : ui32} : () -> ui32
emitc.switch %0 : ui32
case 2 {
@@ -726,7 +726,7 @@ func.func @emitc_switch_ui32() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -775,7 +775,7 @@ func.func @emitc_switch_ui32() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_i64() {
- %0 = "emitc.variable"(){value = 1 : i64} : () -> i64
+ %0 = "emitc.constant"(){value = 1 : i64} : () -> i64
emitc.switch %0 : i64
case 2 {
@@ -787,7 +787,7 @@ func.func @emitc_switch_i64() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
@@ -836,7 +836,7 @@ func.func @emitc_switch_i64() {
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_ui64() {
- %0 = "emitc.variable"(){value = 1 : ui64} : () -> ui64
+ %0 = "emitc.constant"(){value = 1 : ui64} : () -> ui64
emitc.switch %0 : ui64
case 2 {
@@ -848,7 +848,7 @@ func.func @emitc_switch_ui64() {
emitc.yield
}
default {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %3 = "emitc.constant"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
diff --git a/mlir/test/Target/Cpp/variable.mlir b/mlir/test/Target/Cpp/variable.mlir
index 126dd384b47a2a..a26d724127cf25 100644
--- a/mlir/test/Target/Cpp/variable.mlir
+++ b/mlir/test/Target/Cpp/variable.mlir
@@ -2,13 +2,13 @@
// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s -check-prefix=CPP-DECLTOP
func.func @emitc_variable() {
- %c0 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> i32
- %c1 = "emitc.variable"(){value = 42 : i32} : () -> i32
- %c2 = "emitc.variable"(){value = -1 : i32} : () -> i32
- %c3 = "emitc.variable"(){value = -1 : si8} : () -> si8
- %c4 = "emitc.variable"(){value = 255 : ui8} : () -> ui8
- %c5 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.ptr<i32>
- %c6 = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.ptr<i32>
+ %c0 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
+ %c1 = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue<i32>
+ %c2 = "emitc.variable"(){value = -1 : i32} : () -> !emitc.lvalue<i32>
+ %c3 = "emitc.variable"(){value = -1 : si8} : () -> !emitc.lvalue<si8>
+ %c4 = "emitc.variable"(){value = 255 : ui8} : () -> !emitc.lvalue<ui8>
+ %c5 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<!emitc.ptr<i32>>
+ %c6 = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.lvalue<!emitc.ptr<i32>>
%c7 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.array<3x7xi32>
%c8 = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.array<5x!emitc.ptr<i8>>
return
@@ -41,3 +41,5 @@ func.func @emitc_variable() {
// CPP-DECLTOP-NEXT: [[V4]] = 255;
// CPP-DECLTOP-NEXT: ;
// CPP-DECLTOP-NEXT: [[V6]] = NULL;
+// CPP-DECLTOP-NEXT: ;
+// CPP-DECLTOP-NEXT: ;
>From 5ec7fd548970eb2bb0b887583e35f1a7f582b866 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 11 Jun 2024 11:43:49 +0000
Subject: [PATCH 02/14] Add check lines
---
mlir/test/Target/Cpp/lvalue.mlir | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/mlir/test/Target/Cpp/lvalue.mlir b/mlir/test/Target/Cpp/lvalue.mlir
index ce76dd7a7cfeb9..5ef7fb27632462 100644
--- a/mlir/test/Target/Cpp/lvalue.mlir
+++ b/mlir/test/Target/Cpp/lvalue.mlir
@@ -1,17 +1,28 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
-// CHECK: int32_t lvalue_variables(
emitc.func @lvalue_variables(%v1: i32, %v2: i32) -> i32 {
%val = emitc.mul %v1, %v2 : (i32, i32) -> i32
- %variable = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32> // alloc effect
- emitc.assign %val : i32 to %variable : !emitc.lvalue<i32> // write effect
+ %variable = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
+ emitc.assign %val : i32 to %variable : !emitc.lvalue<i32>
%addr = emitc.apply "&"(%variable) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
emitc.call @zero (%addr) : (!emitc.ptr<i32>) -> ()
- %updated_val = emitc.lvalue_load %variable : !emitc.lvalue<i32> // read effect, (noop in emitter?)
+ %updated_val = emitc.lvalue_load %variable : !emitc.lvalue<i32>
%neg_one = "emitc.constant"() {value = -1 : i32} : () -> i32
- emitc.assign %neg_one : i32 to %variable : !emitc.lvalue<i32> // invalidates %updated_val
+ emitc.assign %neg_one : i32 to %variable : !emitc.lvalue<i32>
emitc.return %updated_val : i32
- // dealloc effect through automatic allocation scope
}
+// CHECK-LABEL: int32_t lvalue_variables(
+// CHECK-SAME: int32_t [[V1:[^ ]*]], int32_t [[V2:[^ ]*]])
+// CHECK-NEXT: int32_t [[VAL:[^ ]*]] = [[V1]] * [[V2]];
+// CHECK-NEXT: int32_t [[VAR:[^ ]*]];
+// CHECK-NEXT: [[VAR]] = [[VAL]];
+// CHECK-NEXT: int32_t* [[VAR_PTR:[^ ]*]] = &[[VAR]];
+// CHECK-NEXT: zero([[VAR_PTR]]);
+// CHECK-NEXT: int32_t [[VAR_LOAD:[^ ]*]] = [[VAR]];
+// CHECK-NEXT: int32_t [[NEG_ONE:[^ ]*]] = -1;
+// CHECK-NEXT: [[VAR]] = [[NEG_ONE]];
+// CHECK-NEXT: return [[VAR_LOAD]];
-emitc.func @zero(%arg0: !emitc.ptr<i32>) attributes {specifiers = ["extern"]}
\ No newline at end of file
+
+emitc.func @zero(%arg0: !emitc.ptr<i32>) attributes {specifiers = ["extern"]}
+// CHECK-LABEL: extern void zero(int32_t*);
>From 5fc4fb52e8de4be22ddc6fd80149989aafdeb985 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 11 Jun 2024 13:39:13 +0000
Subject: [PATCH 03/14] Add memory effects
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 0f876079d978bf..3c8cffa895401a 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -844,7 +844,8 @@ def EmitC_LValueLoadOp : EmitC_Op<"lvalue_load", [
let summary = "load an lvalue by assigning it to a local variable";
let description = [{}];
- let arguments = (ins EmitC_LValueType:$operand);
+ let arguments = (ins
+ Res<EmitC_LValueType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$operand);
let results = (outs AnyType:$result);
let assemblyFormat = "$operand attr-dict `:` type($operand)";
@@ -1066,7 +1067,8 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
}];
let arguments = (ins EmitC_OpaqueOrTypedAttr:$value);
- let results = (outs AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>);
+ let results = (outs Res<AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>, "",
+ [MemAlloc<DefaultResource, 0, FullEffect>]>:$memref);
let hasVerifier = 1;
}
@@ -1194,7 +1196,9 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
```
}];
- let arguments = (ins EmitC_LValueType:$var, EmitCType:$value);
+ let arguments = (ins
+ Res<EmitC_LValueType, "", [MemWrite<DefaultResource, 1, FullEffect>]>:$var,
+ Res<EmitCType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$value);
let results = (outs);
let hasVerifier = 1;
>From a98d7844532da862cae425fb23fe3b760f4a0818 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 11 Jun 2024 13:50:55 +0000
Subject: [PATCH 04/14] Disallow lvalues as block arguments
---
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 4 ++--
.../Cpp/invalid_declare_variables_at_top.mlir | 15 +++++++++++++--
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 7cd9032d828498..9263026127bcf5 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -1019,9 +1019,9 @@ static LogicalResult printFunctionBody(CppEmitter &emitter,
if (emitter.hasValueInScope(arg))
return functionOp->emitOpError(" block argument #")
<< arg.getArgNumber() << " is out of scope";
- if (isa<ArrayType>(arg.getType()))
+ if (isa<ArrayType, LValueType>(arg.getType()))
return functionOp->emitOpError("cannot emit block argument #")
- << arg.getArgNumber() << " with array type";
+ << arg.getArgNumber() << " with type " << arg.getType();
if (failed(
emitter.emitType(block.getParentOp()->getLoc(), arg.getType()))) {
return failure();
diff --git a/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir b/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir
index 844fe03bad4aba..8b87113e6d960a 100644
--- a/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir
+++ b/mlir/test/Target/Cpp/invalid_declare_variables_at_top.mlir
@@ -1,9 +1,20 @@
// RUN: mlir-translate -split-input-file -declare-variables-at-top -mlir-to-cpp -verify-diagnostics %s
-// expected-error at +1 {{'func.func' op cannot emit block argument #0 with array type}}
+// expected-error at +1 {{'func.func' op cannot emit block argument #0 with type '!emitc.array<4xi8>'}}
func.func @array_as_block_argument(!emitc.array<4xi8>) {
^bb0(%arg0 : !emitc.array<4xi8>):
cf.br ^bb1(%arg0 : !emitc.array<4xi8>)
^bb1(%a : !emitc.array<4xi8>):
- return
+ return
+}
+
+// -----
+
+// expected-error at +1 {{'emitc.func' op cannot emit block argument #0 with type '!emitc.lvalue<i32>'}}
+emitc.func @lvalue_as_block_argument() {
+^bb0:
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ cf.br ^bb1(%0 : !emitc.lvalue<i32>)
+^bb1(%a : !emitc.lvalue<i32>):
+ emitc.return
}
>From 39008854d810a875c57a770551ba0b5bb6ab038a Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 11 Jun 2024 14:04:48 +0000
Subject: [PATCH 05/14] Fix line endings
---
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index 36f7f5b2f1eb90..dcb146071e7cf5 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -259,4 +259,4 @@ void SCFToEmitCPass::runOnOperation() {
if (failed(
applyPartialConversion(getOperation(), target, std::move(patterns))))
signalPassFailure();
-}
\ No newline at end of file
+}
>From 0a5fbbb8ad38e1213efc6922477678e49e8d1090 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 11 Jun 2024 16:32:29 +0200
Subject: [PATCH 06/14] Apply suggestions from code review
Co-authored-by: Matthias Gehre <matthias.gehre at amd.com>
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 3c8cffa895401a..ad314da8a10dd9 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -841,7 +841,7 @@ def EmitC_LValueLoadOp : EmitC_Op<"lvalue_load", [
"operand", "result",
"::llvm::cast<LValueType>($_self).getValue()">
]> {
- let summary = "load an lvalue by assigning it to a local variable";
+ let summary = "Load an lvalue into an SSA value.";
let description = [{}];
let arguments = (ins
>From 9a75b898598af2d00e992ab4aa773d35f0d40d32 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Tue, 11 Jun 2024 14:46:17 +0000
Subject: [PATCH 07/14] Review comments
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 10 +++++++---
mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td | 8 ++++----
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 4 ++--
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 12 ++++++------
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 2 +-
5 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index ad314da8a10dd9..ff139f90947520 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -839,10 +839,14 @@ def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", [CExpression]> {
def EmitC_LValueLoadOp : EmitC_Op<"lvalue_load", [
TypesMatchWith<"result type matches value type of 'operand'",
"operand", "result",
- "::llvm::cast<LValueType>($_self).getValue()">
+ "::llvm::cast<LValueType>($_self).getValueType()">
]> {
let summary = "Load an lvalue into an SSA value.";
- let description = [{}];
+ let description = [{
+ This operation loads the content of a modifiable lvalue into an SSA value.
+ Modifications of the lvalue executed after the load are not observable on
+ the produced value.
+ }];
let arguments = (ins
Res<EmitC_LValueType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$operand);
@@ -1198,7 +1202,7 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
let arguments = (ins
Res<EmitC_LValueType, "", [MemWrite<DefaultResource, 1, FullEffect>]>:$var,
- Res<EmitCType, "", [MemRead<DefaultResource, 0, FullEffect>]>:$value);
+ EmitCType:$value);
let results = (outs);
let hasVerifier = 1;
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
index b8169f43681b54..e15185c888d2d5 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -91,13 +91,13 @@ def EmitC_LValueType : EmitC_Type<"LValue", "lvalue"> {
Values of this type can be assigned to and their address can be taken.
}];
- let parameters = (ins "Type":$value);
+ let parameters = (ins "Type":$valueType);
let builders = [
- TypeBuilderWithInferredContext<(ins "Type":$value), [{
- return $_get(value.getContext(), value);
+ TypeBuilderWithInferredContext<(ins "Type":$valueType), [{
+ return $_get(valueType.getContext(), valueType);
}]>
];
- let assemblyFormat = "`<` qualified($value) `>`";
+ let assemblyFormat = "`<` qualified($valueType) `>`";
let genVerifyDecl = 1;
}
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index dcb146071e7cf5..26d6a0af07c5c6 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -84,7 +84,7 @@ static void assignValues(ValueRange values, SmallVector<Value> &variables,
SmallVector<Value> loadValues(const SmallVector<Value> &variables,
PatternRewriter &rewriter, Location loc) {
return llvm::map_to_vector<>(variables, [&](Value var) {
- Type type = cast<emitc::LValueType>(var.getType()).getValue();
+ Type type = cast<emitc::LValueType>(var.getType()).getValueType();
return rewriter.create<emitc::LValueLoadOp>(loc, type, var).getResult();
});
}
@@ -151,7 +151,7 @@ LogicalResult ForLowering::matchAndRewrite(ForOp forOp,
lowerYield(resultVariables, rewriter,
cast<scf::YieldOp>(loweredBody->getTerminator()));
- // Copy iterArgs into results after the for loop.
+ // Load variables into SSA values after the for loop.
SmallVector<Value> resultValues = loadValues(resultVariables, rewriter, loc);
rewriter.replaceOp(forOp, resultValues);
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 6b27c8c696a58e..a97b54db726dd6 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -149,7 +149,7 @@ static LogicalResult verifyInitializationAttribute(Operation *op,
Type resultType = op->getResult(0).getType();
if (auto lType = dyn_cast<LValueType>(resultType))
- resultType = lType.getValue();
+ resultType = lType.getValueType();
Type attrType = cast<TypedAttr>(value).getType();
if (isPointerWideType(resultType) && attrType.isIndex())
@@ -229,7 +229,7 @@ LogicalResult emitc::AssignOp::verify() {
return emitOpError() << "cannot assign to block argument";
Type valueType = getValue().getType();
- Type variableType = variable.getType().getValue();
+ Type variableType = variable.getType().getValueType();
if (variableType != valueType)
return emitOpError() << "requires value's type (" << valueType
<< ") to match variable's type (" << variableType
@@ -862,7 +862,7 @@ LogicalResult emitc::SubscriptOp::verify() {
}
// Check element type.
Type elementType = arrayType.getElementType();
- Type resultType = getType().getValue();
+ Type resultType = getType().getValueType();
if (elementType != resultType) {
return emitOpError() << "on array operand requires element type ("
<< elementType << ") and result type (" << resultType
@@ -889,7 +889,7 @@ LogicalResult emitc::SubscriptOp::verify() {
}
// Check pointee type.
Type pointeeType = pointerType.getPointee();
- Type resultType = getType().getValue();
+ Type resultType = getType().getValueType();
if (pointeeType != resultType) {
return emitOpError() << "on pointer operand requires pointee type ("
<< pointeeType << ") and result type (" << resultType
@@ -1144,9 +1144,9 @@ GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
// global has non-array type
auto lvalueType = dyn_cast<LValueType>(resultType);
- if (!lvalueType || lvalueType.getValue() != globalType)
+ if (!lvalueType || lvalueType.getValueType() != globalType)
return emitOpError("on non-array type expects result inner type ")
- << lvalueType.getValue() << " to match type " << globalType
+ << lvalueType.getValueType() << " to match type " << globalType
<< " of the global @" << getName();
return success();
}
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 9263026127bcf5..146f423b469958 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -1684,7 +1684,7 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) {
return success();
}
if (auto lType = dyn_cast<emitc::LValueType>(type))
- return emitType(loc, lType.getValue());
+ return emitType(loc, lType.getValueType());
if (auto pType = dyn_cast<emitc::PointerType>(type)) {
if (isa<ArrayType>(pType.getPointee()))
return emitError(loc, "cannot emit pointer to array type ") << type;
>From 6931515b1b8bf5cef0ee9f668de33b1bebfc1899 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Wed, 12 Jun 2024 08:12:56 +0000
Subject: [PATCH 08/14] Rename lvalue_load to load
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 2 +-
.../include/mlir/Dialect/EmitC/IR/EmitCTypes.td | 2 +-
.../Conversion/MemRefToEmitC/MemRefToEmitC.cpp | 2 +-
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 2 +-
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 17 ++++++++---------
.../MemRefToEmitC/memref-to-emitc.mlir | 2 +-
mlir/test/Conversion/SCFToEmitC/for.mlir | 16 ++++++++--------
mlir/test/Conversion/SCFToEmitC/if.mlir | 4 ++--
mlir/test/Conversion/SCFToEmitC/switch.mlir | 4 ++--
mlir/test/Dialect/EmitC/invalid_ops.mlir | 2 +-
mlir/test/Dialect/EmitC/ops.mlir | 2 +-
mlir/test/Target/Cpp/expressions.mlir | 8 ++++----
mlir/test/Target/Cpp/for.mlir | 16 ++++++++--------
mlir/test/Target/Cpp/global.mlir | 4 ++--
mlir/test/Target/Cpp/lvalue.mlir | 2 +-
mlir/test/Target/Cpp/member.mlir | 4 ++--
mlir/test/Target/Cpp/subscript.mlir | 14 +++++++-------
17 files changed, 51 insertions(+), 52 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index ff139f90947520..f4043763445a0b 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -836,7 +836,7 @@ def EmitC_LogicalOrOp : EmitC_BinaryOp<"logical_or", [CExpression]> {
let assemblyFormat = "operands attr-dict `:` type(operands)";
}
-def EmitC_LValueLoadOp : EmitC_Op<"lvalue_load", [
+def EmitC_LoadOp : EmitC_Op<"load", [
TypesMatchWith<"result type matches value type of 'operand'",
"operand", "result",
"::llvm::cast<LValueType>($_self).getValueType()">
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
index e15185c888d2d5..134ef04f26dd4b 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -180,7 +180,7 @@ class EmitC_LValueOf<list<Type> allowedTypes> :
ContainerType<
AnyTypeOf<allowedTypes>,
CPred<"::llvm::isa<::mlir::emitc::LValueType>($_self)">,
- "::llvm::cast<::mlir::emitc::LValueType>($_self).getValue()",
+ "::llvm::cast<::mlir::emitc::LValueType>($_self).getValueType()",
"emitc.lvalue",
"::mlir::emitc::LValueType"
>;
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 2e8fbbad14d40e..1392bf924002ee 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -137,7 +137,7 @@ struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
auto subscript = rewriter.create<emitc::SubscriptOp>(
op.getLoc(), arrayValue, operands.getIndices());
- rewriter.replaceOpWithNewOp<emitc::LValueLoadOp>(op, resultTy, subscript);
+ rewriter.replaceOpWithNewOp<emitc::LoadOp>(op, resultTy, subscript);
return success();
}
};
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index 26d6a0af07c5c6..67a43c43d608b4 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -85,7 +85,7 @@ SmallVector<Value> loadValues(const SmallVector<Value> &variables,
PatternRewriter &rewriter, Location loc) {
return llvm::map_to_vector<>(variables, [&](Value var) {
Type type = cast<emitc::LValueType>(var.getType()).getValueType();
- return rewriter.create<emitc::LValueLoadOp>(loc, type, var).getResult();
+ return rewriter.create<emitc::LoadOp>(loc, type, var).getResult();
});
}
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 146f423b469958..a8a0efab84aed0 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -384,12 +384,11 @@ static LogicalResult printOperation(CppEmitter &emitter,
return emitter.emitOperand(assignOp.getValue());
}
-static LogicalResult printOperation(CppEmitter &emitter,
- emitc::LValueLoadOp lValueLoadOp) {
- if (failed(emitter.emitAssignPrefix(*lValueLoadOp)))
+static LogicalResult printOperation(CppEmitter &emitter, emitc::LoadOp loadOp) {
+ if (failed(emitter.emitAssignPrefix(*loadOp)))
return failure();
- return emitter.emitOperand(lValueLoadOp.getOperand());
+ return emitter.emitOperand(loadOp.getOperand());
}
static LogicalResult printBinaryOperation(CppEmitter &emitter,
@@ -1551,11 +1550,11 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::CallOpaqueOp, emitc::CastOp, emitc::CmpOp,
emitc::ConditionalOp, emitc::ConstantOp, emitc::DeclareFuncOp,
emitc::DivOp, emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp,
- emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp,
- emitc::LValueLoadOp, emitc::LogicalAndOp, emitc::LogicalNotOp,
- emitc::LogicalOrOp, emitc::MulOp, emitc::RemOp, emitc::ReturnOp,
- emitc::SubOp, emitc::SwitchOp, emitc::UnaryMinusOp,
- emitc::UnaryPlusOp, emitc::VariableOp, emitc::VerbatimOp>(
+ emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp, emitc::LoadOp,
+ emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
+ emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
+ emitc::SwitchOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp,
+ emitc::VariableOp, emitc::VerbatimOp>(
[&](auto op) { return printOperation(*this, op); })
// Func ops.
.Case<func::CallOp, func::FuncOp, func::ReturnOp>(
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index 15ffd815250d20..f4722da08cc40f 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -21,7 +21,7 @@ func.func @memref_load(%i: index, %j: index) -> f32 {
%0 = memref.alloca() : memref<4x8xf32>
// CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
- // CHECK-NEXT: %[[LOAD:.*]] = emitc.lvalue_load %[[SUBSCRIPT]] : <f32>
+ // CHECK-NEXT: %[[LOAD:.*]] = emitc.load %[[SUBSCRIPT]] : <f32>
%1 = memref.load %0[%i, %j] : memref<4x8xf32>
// CHECK-NEXT: return %[[LOAD]] : f32
return %1 : f32
diff --git a/mlir/test/Conversion/SCFToEmitC/for.mlir b/mlir/test/Conversion/SCFToEmitC/for.mlir
index 32a9dfce7f4e62..83592187a9b688 100644
--- a/mlir/test/Conversion/SCFToEmitC/for.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/for.mlir
@@ -52,14 +52,14 @@ func.func @for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> (f32, f32)
// CHECK-NEXT: emitc.assign %[[VAL_3]] : f32 to %[[VAL_5]] : <f32>
// CHECK-NEXT: emitc.assign %[[VAL_4]] : f32 to %[[VAL_6]] : <f32>
// CHECK-NEXT: emitc.for %[[VAL_7:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
-// CHECK-NEXT: %[[VAL_8:.*]] = emitc.lvalue_load %[[VAL_5]] : <f32>
-// CHECK-NEXT: %[[VAL_9:.*]] = emitc.lvalue_load %[[VAL_6]] : <f32>
+// CHECK-NEXT: %[[VAL_8:.*]] = emitc.load %[[VAL_5]] : <f32>
+// CHECK-NEXT: %[[VAL_9:.*]] = emitc.load %[[VAL_6]] : <f32>
// CHECK-NEXT: %[[VAL_10:.*]] = arith.addf %[[VAL_8]], %[[VAL_9]] : f32
// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_5]] : <f32>
// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_6]] : <f32>
// CHECK-NEXT: }
-// CHECK-NEXT: %[[VAL_11:.*]] = emitc.lvalue_load %[[VAL_5]] : <f32>
-// CHECK-NEXT: %[[VAL_12:.*]] = emitc.lvalue_load %[[VAL_6]] : <f32>
+// CHECK-NEXT: %[[VAL_11:.*]] = emitc.load %[[VAL_5]] : <f32>
+// CHECK-NEXT: %[[VAL_12:.*]] = emitc.load %[[VAL_6]] : <f32>
// CHECK-NEXT: return %[[VAL_11]], %[[VAL_12]] : f32, f32
// CHECK-NEXT: }
@@ -80,17 +80,17 @@ func.func @nested_for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> f32
// CHECK-NEXT: %[[VAL_4:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
// CHECK-NEXT: emitc.assign %[[VAL_3]] : f32 to %[[VAL_4]] : <f32>
// CHECK-NEXT: emitc.for %[[VAL_5:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
-// CHECK-NEXT: %[[VAL_6:.*]] = emitc.lvalue_load %[[VAL_4]] : <f32>
+// CHECK-NEXT: %[[VAL_6:.*]] = emitc.load %[[VAL_4]] : <f32>
// CHECK-NEXT: %[[VAL_7:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
// CHECK-NEXT: emitc.assign %[[VAL_6]] : f32 to %[[VAL_7]] : <f32>
// CHECK-NEXT: emitc.for %[[VAL_8:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[VAL_2]] {
-// CHECK-NEXT: %[[VAL_9:.*]] = emitc.lvalue_load %[[VAL_7]] : <f32>
+// CHECK-NEXT: %[[VAL_9:.*]] = emitc.load %[[VAL_7]] : <f32>
// CHECK-NEXT: %[[VAL_10:.*]] = arith.addf %[[VAL_9]], %[[VAL_9]] : f32
// CHECK-NEXT: emitc.assign %[[VAL_10]] : f32 to %[[VAL_7]] : <f32>
// CHECK-NEXT: }
-// CHECK-NEXT: %[[VAL_11:.*]] = emitc.lvalue_load %[[VAL_7]] : <f32>
+// CHECK-NEXT: %[[VAL_11:.*]] = emitc.load %[[VAL_7]] : <f32>
// CHECK-NEXT: emitc.assign %[[VAL_11]] : f32 to %[[VAL_4]] : <f32>
// CHECK-NEXT: }
-// CHECK-NEXT: %[[VAL_12:.*]] = emitc.lvalue_load %[[VAL_4]] : <f32>
+// CHECK-NEXT: %[[VAL_12:.*]] = emitc.load %[[VAL_4]] : <f32>
// CHECK-NEXT: return %[[VAL_12]] : f32
// CHECK-NEXT: }
diff --git a/mlir/test/Conversion/SCFToEmitC/if.mlir b/mlir/test/Conversion/SCFToEmitC/if.mlir
index 463cf1d3d96453..7d923785862d85 100644
--- a/mlir/test/Conversion/SCFToEmitC/if.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/if.mlir
@@ -66,7 +66,7 @@ func.func @test_if_yield(%arg0: i1, %arg1: f32) -> (i32, 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: }
-// CHECK-NEXT: %[[VAL_9:.*]] = emitc.lvalue_load %[[VAL_3]] : <i32>
-// CHECK-NEXT: %[[VAL_10:.*]] = emitc.lvalue_load %[[VAL_4]] : <f64>
+// CHECK-NEXT: %[[VAL_9:.*]] = emitc.load %[[VAL_3]] : <i32>
+// CHECK-NEXT: %[[VAL_10:.*]] = emitc.load %[[VAL_4]] : <f64>
// CHECK-NEXT: return %[[VAL_9]], %[[VAL_10]] : i32, f64
// CHECK-NEXT: }
diff --git a/mlir/test/Conversion/SCFToEmitC/switch.mlir b/mlir/test/Conversion/SCFToEmitC/switch.mlir
index 54d84738bcb9ac..86d96ed21f1b59 100644
--- a/mlir/test/Conversion/SCFToEmitC/switch.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/switch.mlir
@@ -94,8 +94,8 @@ func.func @switch_one_result(%arg0 : index) {
// CHECK: emitc.assign %[[VAL_7]] : i32 to %[[VAL_1]] : <i32>
// CHECK: emitc.assign %[[VAL_8]] : f32 to %[[VAL_2]] : <f32>
// CHECK: }
-// CHECK: %[[RES_1:.*]] = emitc.lvalue_load %[[VAL_1]] : <i32>
-// CHECK: %[[RES_2:.*]] = emitc.lvalue_load %[[VAL_2]] : <f32>
+// CHECK: %[[RES_1:.*]] = emitc.load %[[VAL_1]] : <i32>
+// CHECK: %[[RES_2:.*]] = emitc.load %[[VAL_2]] : <f32>
// CHECK: return %[[RES_1]], %[[RES_2]] : i32, f32
// CHECK: }
func.func @switch_two_results(%arg0 : index) -> (i32, f32) {
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index d3f9c5c36ff8c8..a80e49cc33fac4 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -265,7 +265,7 @@ func.func @test_expression_illegal_op(%arg0 : i1) -> i32 {
// expected-error @+1 {{'emitc.expression' op contains an unsupported operation}}
%r = emitc.expression : i32 {
%x = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
- %y = emitc.lvalue_load %x : <i32>
+ %y = emitc.load %x : <i32>
emitc.yield %y : i32
}
return %r : i32
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index e72fc74a740029..bb38754ff469b8 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -246,7 +246,7 @@ emitc.global const @myconstant : !emitc.array<2xi16> = dense<2>
func.func @use_global(%i: index) -> f32 {
%0 = emitc.get_global @myglobal : !emitc.array<2xf32>
%1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> !emitc.lvalue<f32>
- %2 = emitc.lvalue_load %1 : <f32>
+ %2 = emitc.load %1 : <f32>
return %2 : f32
}
diff --git a/mlir/test/Target/Cpp/expressions.mlir b/mlir/test/Target/Cpp/expressions.mlir
index d9455e8e98177d..6b67065f5d1a1c 100644
--- a/mlir/test/Target/Cpp/expressions.mlir
+++ b/mlir/test/Target/Cpp/expressions.mlir
@@ -45,7 +45,7 @@ func.func @single_use(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32 {
emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
}
- %v_load = emitc.lvalue_load %v : !emitc.lvalue<i32>
+ %v_load = emitc.load %v : !emitc.lvalue<i32>
return %v_load : i32
}
@@ -234,7 +234,7 @@ func.func @multiple_uses(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i32
}
%q = "emitc.variable"(){value = #emitc.opaque<"">} : () -> !emitc.lvalue<i1>
emitc.assign %e : i1 to %q : !emitc.lvalue<i1>
- %v_load = emitc.lvalue_load %v : !emitc.lvalue<i32>
+ %v_load = emitc.load %v : !emitc.lvalue<i32>
return %v_load : i32
}
@@ -291,7 +291,7 @@ func.func @different_expressions(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
emitc.assign %arg0 : i32 to %v : !emitc.lvalue<i32>
emitc.yield
}
- %v_load = emitc.lvalue_load %v : !emitc.lvalue<i32>
+ %v_load = emitc.load %v : !emitc.lvalue<i32>
return %v_load : i32
}
@@ -339,6 +339,6 @@ func.func @expression_with_subscript_user(%arg0: !emitc.ptr<!emitc.opaque<"void"
emitc.yield %0 : !emitc.ptr<i32>
}
%res = emitc.subscript %0[%c0] : (!emitc.ptr<i32>, i64) -> !emitc.lvalue<i32>
- %res_load = emitc.lvalue_load %res : !emitc.lvalue<i32>
+ %res_load = emitc.load %res : !emitc.lvalue<i32>
return %res_load : i32
}
diff --git a/mlir/test/Target/Cpp/for.mlir b/mlir/test/Target/Cpp/for.mlir
index 14d3f05d6a08e0..6a446eaf4add3f 100644
--- a/mlir/test/Target/Cpp/for.mlir
+++ b/mlir/test/Target/Cpp/for.mlir
@@ -47,17 +47,17 @@ func.func @test_for_yield() {
emitc.assign %s0 : i32 to %2 : !emitc.lvalue<i32>
emitc.assign %p0 : f32 to %3 : !emitc.lvalue<f32>
emitc.for %iter = %start to %stop step %step {
- %4 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ %4 = emitc.load %2 : !emitc.lvalue<i32>
%sn = emitc.call_opaque "add"(%4, %iter) : (i32, index) -> i32
- %5 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ %5 = emitc.load %3 : !emitc.lvalue<f32>
%pn = emitc.call_opaque "mul"(%5, %iter) : (f32, index) -> f32
emitc.assign %sn : i32 to %2 : !emitc.lvalue<i32>
emitc.assign %pn : f32 to %3 : !emitc.lvalue<f32>
emitc.yield
}
- %6 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ %6 = emitc.load %2 : !emitc.lvalue<i32>
emitc.assign %6 : i32 to %0 : !emitc.lvalue<i32>
- %7 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ %7 = emitc.load %3 : !emitc.lvalue<f32>
emitc.assign %7 : f32 to %1 : !emitc.lvalue<f32>
return
@@ -144,17 +144,17 @@ func.func @test_for_yield_2() {
emitc.assign %s0 : i32 to %2 : !emitc.lvalue<i32>
emitc.assign %p0 : f32 to %3 : !emitc.lvalue<f32>
emitc.for %iter = %start to %stop step %step {
- %4 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ %4 = emitc.load %2 : !emitc.lvalue<i32>
%sn = emitc.call_opaque "add"(%4, %iter) : (i32, index) -> i32
- %5 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ %5 = emitc.load %3 : !emitc.lvalue<f32>
%pn = emitc.call_opaque "mul"(%5, %iter) : (f32, index) -> f32
emitc.assign %sn : i32 to %2 : !emitc.lvalue<i32>
emitc.assign %pn : f32 to %3 : !emitc.lvalue<f32>
emitc.yield
}
- %6 = emitc.lvalue_load %2 : !emitc.lvalue<i32>
+ %6 = emitc.load %2 : !emitc.lvalue<i32>
emitc.assign %6 : i32 to %0 : !emitc.lvalue<i32>
- %7 = emitc.lvalue_load %3 : !emitc.lvalue<f32>
+ %7 = emitc.load %3 : !emitc.lvalue<f32>
emitc.assign %7 : f32 to %1 : !emitc.lvalue<f32>
return
diff --git a/mlir/test/Target/Cpp/global.mlir b/mlir/test/Target/Cpp/global.mlir
index b2d61681dbd601..c54338bc2faffd 100644
--- a/mlir/test/Target/Cpp/global.mlir
+++ b/mlir/test/Target/Cpp/global.mlir
@@ -39,7 +39,7 @@ emitc.global @opaque_init : !emitc.opaque<"char"> = #emitc.opaque<"CHAR_MIN">
func.func @use_global_scalar_read() -> i32 {
%0 = emitc.get_global @myglobal_int : !emitc.lvalue<i32>
- %1 = emitc.lvalue_load %0 : !emitc.lvalue<i32>
+ %1 = emitc.load %0 : !emitc.lvalue<i32>
return %1 : i32
}
// CPP-DEFAULT-LABEL: int32_t use_global_scalar_read()
@@ -69,7 +69,7 @@ func.func @use_global_scalar_write(%arg0 : i32) {
func.func @use_global_array_read(%i: index) -> f32 {
%0 = emitc.get_global @myglobal : !emitc.array<2xf32>
%1 = emitc.subscript %0[%i] : (!emitc.array<2xf32>, index) -> !emitc.lvalue<f32>
- %2 = emitc.lvalue_load %1 : !emitc.lvalue<f32>
+ %2 = emitc.load %1 : <f32>
return %2 : f32
}
// CPP-DEFAULT-LABEL: float use_global_array_read
diff --git a/mlir/test/Target/Cpp/lvalue.mlir b/mlir/test/Target/Cpp/lvalue.mlir
index 5ef7fb27632462..2aa438eb6371c7 100644
--- a/mlir/test/Target/Cpp/lvalue.mlir
+++ b/mlir/test/Target/Cpp/lvalue.mlir
@@ -6,7 +6,7 @@ emitc.func @lvalue_variables(%v1: i32, %v2: i32) -> i32 {
emitc.assign %val : i32 to %variable : !emitc.lvalue<i32>
%addr = emitc.apply "&"(%variable) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
emitc.call @zero (%addr) : (!emitc.ptr<i32>) -> ()
- %updated_val = emitc.lvalue_load %variable : !emitc.lvalue<i32>
+ %updated_val = emitc.load %variable : !emitc.lvalue<i32>
%neg_one = "emitc.constant"() {value = -1 : i32} : () -> i32
emitc.assign %neg_one : i32 to %variable : !emitc.lvalue<i32>
emitc.return %updated_val : i32
diff --git a/mlir/test/Target/Cpp/member.mlir b/mlir/test/Target/Cpp/member.mlir
index d1c453f07cda53..df3450c05dbf9e 100644
--- a/mlir/test/Target/Cpp/member.mlir
+++ b/mlir/test/Target/Cpp/member.mlir
@@ -5,7 +5,7 @@ func.func @member(%arg0: !emitc.lvalue<!emitc.opaque<"mystruct">>, %arg1: i32) {
emitc.assign %arg1 : i32 to %0 : !emitc.lvalue<i32>
%1 = "emitc.member" (%arg0) {member = "b"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
- %2 = emitc.lvalue_load %1 : !emitc.lvalue<i32>
+ %2 = emitc.load %1 : !emitc.lvalue<i32>
%3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
emitc.assign %2 : i32 to %3 : !emitc.lvalue<i32>
@@ -24,7 +24,7 @@ func.func @member_of_pointer(%arg0: !emitc.lvalue<!emitc.ptr<!emitc.opaque<"myst
emitc.assign %arg1 : i32 to %0 : !emitc.lvalue<i32>
%1 = "emitc.member_of_ptr" (%arg0) {member = "b"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
- %2 = emitc.lvalue_load %1 : !emitc.lvalue<i32>
+ %2 = emitc.load %1 : !emitc.lvalue<i32>
%3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
emitc.assign %2 : i32 to %3 : !emitc.lvalue<i32>
diff --git a/mlir/test/Target/Cpp/subscript.mlir b/mlir/test/Target/Cpp/subscript.mlir
index b5c94c146712eb..7f015c210796e7 100644
--- a/mlir/test/Target/Cpp/subscript.mlir
+++ b/mlir/test/Target/Cpp/subscript.mlir
@@ -4,7 +4,7 @@
func.func @load_store_array(%arg0: !emitc.array<4x8xf32>, %arg1: !emitc.array<3x5xf32>, %arg2: index, %arg3: index) {
%0 = emitc.subscript %arg0[%arg2, %arg3] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
%1 = emitc.subscript %arg1[%arg2, %arg3] : (!emitc.array<3x5xf32>, index, index) -> !emitc.lvalue<f32>
- %2 = emitc.lvalue_load %0 : <f32>
+ %2 = emitc.load %0 : <f32>
emitc.assign %2 : f32 to %1 : !emitc.lvalue<f32>
return
}
@@ -22,7 +22,7 @@ func.func @load_store_array(%arg0: !emitc.array<4x8xf32>, %arg1: !emitc.array<3x
func.func @load_store_pointer(%arg0: !emitc.ptr<f32>, %arg1: !emitc.ptr<f32>, %arg2: index, %arg3: index) {
%0 = emitc.subscript %arg0[%arg2] : (!emitc.ptr<f32>, index) -> !emitc.lvalue<f32>
%1 = emitc.subscript %arg1[%arg3] : (!emitc.ptr<f32>, index) -> !emitc.lvalue<f32>
- %2 = emitc.lvalue_load %0 : <f32>
+ %2 = emitc.load %0 : <f32>
emitc.assign %2 : f32 to %1 : <f32>
return
}
@@ -40,7 +40,7 @@ func.func @load_store_pointer(%arg0: !emitc.ptr<f32>, %arg1: !emitc.ptr<f32>, %a
func.func @load_store_opaque(%arg0: !emitc.opaque<"std::map<char, int>">, %arg1: !emitc.opaque<"std::map<char, int>">, %arg2: !emitc.opaque<"char">, %arg3: !emitc.opaque<"char">) {
%0 = emitc.subscript %arg0[%arg2] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.lvalue<!emitc.opaque<"int">>
%1 = emitc.subscript %arg1[%arg3] : (!emitc.opaque<"std::map<char, int>">, !emitc.opaque<"char">) -> !emitc.lvalue<!emitc.opaque<"int">>
- %2 = emitc.lvalue_load %0 : <!emitc.opaque<"int">>
+ %2 = emitc.load %0 : <!emitc.opaque<"int">>
emitc.assign %2 : !emitc.opaque<"int"> to %1 : <!emitc.opaque<"int">>
return
}
@@ -64,12 +64,12 @@ emitc.func @call_arg(%arg0: !emitc.array<4x8xf32>, %i: i32, %j: i16,
%0 = emitc.subscript %arg0[%i, %j] : (!emitc.array<4x8xf32>, i32, i16) -> !emitc.lvalue<f32>
%1 = emitc.subscript %arg0[%j, %k] : (!emitc.array<4x8xf32>, i16, i8) -> !emitc.lvalue<f32>
- %2 = emitc.lvalue_load %0 : <f32>
+ %2 = emitc.load %0 : <f32>
emitc.call @func1 (%2) : (f32) -> ()
- %3 = emitc.lvalue_load %1 : <f32>
+ %3 = emitc.load %1 : <f32>
emitc.call_opaque "func2" (%3) : (f32) -> ()
- %4 = emitc.lvalue_load %0 : <f32>
- %5 = emitc.lvalue_load %1 : <f32>
+ %4 = emitc.load %0 : <f32>
+ %5 = emitc.load %1 : <f32>
emitc.call_opaque "func3" (%4, %5) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.return
}
>From 0aab7aa710f5950148e82cd5f826dfb4d49c6a2f Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Thu, 13 Jun 2024 08:03:40 +0000
Subject: [PATCH 09/14] Restore xpression_with_dereference test
---
mlir/test/Dialect/EmitC/transforms.mlir | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/mlir/test/Dialect/EmitC/transforms.mlir b/mlir/test/Dialect/EmitC/transforms.mlir
index 996fd327f7af78..bd0dd820609bf7 100644
--- a/mlir/test/Dialect/EmitC/transforms.mlir
+++ b/mlir/test/Dialect/EmitC/transforms.mlir
@@ -64,6 +64,26 @@ func.func @expression_with_call(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32)
return %c : i1
}
+// 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_4:.*]] = emitc.apply "*"(%[[VAL_2]]) : (!emitc.ptr<i32>) -> i32
+// CHECK: emitc.yield %[[VAL_4]] : i32
+// CHECK: }
+// CHECK: %[[VAL_5:.*]] = emitc.expression : i1 {
+// CHECK: %[[VAL_6:.*]] = emitc.mul %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i32
+// CHECK: %[[VAL_7:.*]] = emitc.cmp lt, %[[VAL_6]], %[[VAL_3]] : (i32, i32) -> i1
+// CHECK: return %[[VAL_5]] : i1
+// CHECK: }
+
+func.func @expression_with_dereference(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
+ %a = emitc.mul %arg0, %arg1 : (i32, i32) -> i32
+ %b = emitc.apply "*"(%arg2) : (!emitc.ptr<i32>) -> (i32)
+ %c = emitc.cmp lt, %a, %b :(i32, i32) -> i1
+ return %c : i1
+}
+
+
// CHECK-LABEL: func.func @expression_with_address_taken(
// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32, %[[VAL_2:.*]]: !emitc.ptr<i32>, %[[VAL_3:.*]]: !emitc.lvalue<i32>) -> i1 {
// CHECK: %[[VAL_4:.*]] = emitc.expression : i1 {
>From 3c34aa3f64a76bb2d7562eea630c947308e732ab Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Thu, 13 Jun 2024 08:19:27 +0000
Subject: [PATCH 10/14] Drop unnecessary check
---
mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
index 758b8527c2fa55..82bd031430d36c 100644
--- a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
+++ b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp
@@ -38,8 +38,7 @@ struct FormExpressionsPass
auto matchFun = [&](Operation *op) {
if (op->hasTrait<OpTrait::emitc::CExpression>() &&
!op->getParentOfType<emitc::ExpressionOp>() &&
- op->getNumResults() == 1 &&
- isSupportedEmitCType(op->getResult(0).getType()))
+ op->getNumResults() == 1)
createExpression(op, builder);
};
rootOp->walk(matchFun);
>From bbb4e9e0cb7ab626f5be17475a9a81ebf7e09edb Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Thu, 13 Jun 2024 15:20:52 +0000
Subject: [PATCH 11/14] Remove result name
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index f4043763445a0b..dbee2ff5ce7f04 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1072,7 +1072,7 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
let arguments = (ins EmitC_OpaqueOrTypedAttr:$value);
let results = (outs Res<AnyTypeOf<[EmitC_ArrayType, EmitC_LValueType]>, "",
- [MemAlloc<DefaultResource, 0, FullEffect>]>:$memref);
+ [MemAlloc<DefaultResource, 0, FullEffect>]>);
let hasVerifier = 1;
}
>From a15dd75c3d9853dfeda33dd015fa3ea007cb9c15 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Thu, 13 Jun 2024 15:25:03 +0000
Subject: [PATCH 12/14] Review comment
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index a97b54db726dd6..86a227c2d8d1cd 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -61,9 +61,6 @@ void mlir::emitc::buildTerminatedBody(OpBuilder &builder, Location loc) {
bool mlir::emitc::isSupportedEmitCType(Type type) {
if (llvm::isa<emitc::OpaqueType>(type))
return true;
- if (auto lType = llvm::dyn_cast<emitc::LValueType>(type))
- // lvalue types are only allowed in a few places.
- return false;
if (auto ptrType = llvm::dyn_cast<emitc::PointerType>(type))
return isSupportedEmitCType(ptrType.getPointee());
if (auto arrayType = llvm::dyn_cast<emitc::ArrayType>(type)) {
>From 5f41378613f9155bae5b2f28d03cec58ed4edce7 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Thu, 13 Jun 2024 16:09:11 +0000
Subject: [PATCH 13/14] Disallow lvalue as argument types
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 4 +++
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 5 +++
mlir/test/Dialect/EmitC/invalid_ops.mlir | 26 +++++++++++----
mlir/test/Dialect/EmitC/ops.mlir | 8 +++--
mlir/test/Dialect/EmitC/transforms.mlir | 8 +++--
mlir/test/Target/Cpp/common-cpp.mlir | 15 +++++----
mlir/test/Target/Cpp/invalid.mlir | 7 ++++
mlir/test/Target/Cpp/member.mlir | 42 +++++++++++++++---------
8 files changed, 79 insertions(+), 36 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 86a227c2d8d1cd..a7f033fc1ea37b 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -548,6 +548,10 @@ void FuncOp::print(OpAsmPrinter &p) {
}
LogicalResult FuncOp::verify() {
+ if (llvm::any_of(getArgumentTypes(), llvm::IsaPred<LValueType>)) {
+ return emitOpError("cannot have lvalue type as argument");
+ }
+
if (getNumResults() > 1)
return emitOpError("requires zero or exactly one result, but has ")
<< getNumResults();
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index a8a0efab84aed0..c043582b7be9c6 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -1064,6 +1064,11 @@ static LogicalResult printOperation(CppEmitter &emitter,
"with multiple blocks needs variables declared at top");
}
+ if (llvm::any_of(functionOp.getArgumentTypes(), llvm::IsaPred<LValueType>)) {
+ return functionOp.emitOpError()
+ << "cannot emit lvalue type as argument type";
+ }
+
if (llvm::any_of(functionOp.getResultTypes(), llvm::IsaPred<ArrayType>)) {
return functionOp.emitOpError() << "cannot emit array type as result type";
}
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index a80e49cc33fac4..fda2ffa5642d2d 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -88,17 +88,19 @@ func.func @array_result() {
// -----
-func.func @empty_operator(%arg : !emitc.lvalue<i32>) {
+func.func @empty_operator() {
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
// expected-error @+1 {{'emitc.apply' op applicable operator must not be empty}}
- %2 = emitc.apply ""(%arg) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %1 = emitc.apply ""(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
return
}
// -----
-func.func @illegal_operator(%arg : !emitc.lvalue<i32>) {
+func.func @illegal_operator() {
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
// expected-error @+1 {{'emitc.apply' op applicable operator is illegal}}
- %2 = emitc.apply "+"(%arg) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %1 = emitc.apply "+"(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
return
}
@@ -225,10 +227,13 @@ func.func @test_misplaced_yield() {
// -----
-func.func @test_assign_to_non_variable(%arg1: f32, %arg2: !emitc.lvalue<f32>) {
+func.func @test_assign_to_block_argument(%arg0: f32) {
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+ cf.br ^bb1(%0 : !emitc.lvalue<f32>)
+^bb1(%a : !emitc.lvalue<f32>):
// expected-error @+1 {{'emitc.assign' op cannot assign to block argument}}
- emitc.assign %arg1 : f32 to %arg2 : !emitc.lvalue<f32>
- return
+ emitc.assign %arg0 : f32 to %a : !emitc.lvalue<f32>
+ func.return
}
// -----
@@ -330,6 +335,13 @@ emitc.func @return_type_mismatch() -> i32 {
// -----
+// expected-error at +1 {{'emitc.func' op cannot have lvalue type as argument}}
+emitc.func @argument_type_lvalue(%arg : !emitc.lvalue<i32>) {
+ emitc.return
+}
+
+// -----
+
// expected-error at +1 {{'emitc.func' op cannot return array type}}
emitc.func @return_type_array(%arg : !emitc.array<4xi32>) -> !emitc.array<4xi32> {
emitc.return %arg : !emitc.array<4xi32>
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index bb38754ff469b8..b0a95b8940cc7e 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -47,9 +47,11 @@ func.func @c() {
return
}
-func.func @a(%arg0: !emitc.lvalue<i32>, %arg1: !emitc.lvalue<i32>) {
- %1 = "emitc.apply"(%arg0) {applicableOperator = "&"} : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
- %2 = emitc.apply "&"(%arg1) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+func.func @a() {
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %1 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %2 = "emitc.apply"(%0) {applicableOperator = "&"} : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %3 = emitc.apply "&"(%1) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
return
}
diff --git a/mlir/test/Dialect/EmitC/transforms.mlir b/mlir/test/Dialect/EmitC/transforms.mlir
index bd0dd820609bf7..6cfac6462623c9 100644
--- a/mlir/test/Dialect/EmitC/transforms.mlir
+++ b/mlir/test/Dialect/EmitC/transforms.mlir
@@ -85,7 +85,8 @@ 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>, %[[VAL_3:.*]]: !emitc.lvalue<i32>) -> i1 {
+// 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_5:.*]] = emitc.apply "&"(%[[VAL_3]]) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
// CHECK: %[[VAL_6:.*]] = emitc.add %[[VAL_5]], %[[VAL_1]] : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
@@ -95,8 +96,9 @@ func.func @expression_with_dereference(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr
// CHECK: return %[[VAL_4]] : i1
// CHECK: }
-func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>, %arg3: !emitc.lvalue<i32>) -> i1 {
- %a = emitc.apply "&"(%arg3) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.ptr<i32>) -> i1 {
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
+ %a = emitc.apply "&"(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
%b = emitc.add %a, %arg1 : (!emitc.ptr<i32>, i32) -> !emitc.ptr<i32>
%c = emitc.cmp lt, %b, %arg2 :(!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1
return %c : i1
diff --git a/mlir/test/Target/Cpp/common-cpp.mlir b/mlir/test/Target/Cpp/common-cpp.mlir
index 8af29531905ba4..2036a10e0cad15 100644
--- a/mlir/test/Target/Cpp/common-cpp.mlir
+++ b/mlir/test/Target/Cpp/common-cpp.mlir
@@ -82,19 +82,20 @@ func.func @opaque_types(%arg0: !emitc.opaque<"bool">, %arg1: !emitc.opaque<"char
return %2 : !emitc.opaque<"status_t">
}
-// CHECK-LABEL: int32_t* apply(
-// CHECK-SAME: int32_t [[V1:[^ ]*]]) {
-func.func @apply(%arg0: !emitc.lvalue<i32>) -> !emitc.ptr<i32> {
+// CHECK-LABEL: int32_t* apply() {
+func.func @apply() -> !emitc.ptr<i32> {
+ // CHECK-NEXT: int32_t [[V1:[^ ]*]];
+ %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
// CHECK-NEXT: int32_t* [[V2:[^ ]*]] = &[[V1]];
- %0 = emitc.apply "&"(%arg0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %1 = emitc.apply "&"(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
// CHECK-NEXT: int32_t [[V3:[^ ]*]];
%2 = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue<i32>
// CHECK-NEXT: int32_t [[V4:[^ ]*]] = *[[V2]];
- %1 = emitc.apply "*"(%0) : (!emitc.ptr<i32>) -> i32
+ %3 = emitc.apply "*"(%1) : (!emitc.ptr<i32>) -> i32
// CHECK-NEXT: [[V3]] = [[V4]];
- emitc.assign %1 : i32 to %2 : !emitc.lvalue<i32>
+ emitc.assign %3 : i32 to %2 : !emitc.lvalue<i32>
// CHECK-NEXT: return [[V2]];
- return %0 : !emitc.ptr<i32>
+ return %1 : !emitc.ptr<i32>
}
// CHECK: void array_type(int32_t v1[3], float v2[10][20])
diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir
index 89f984f85347fc..df4627a158319b 100644
--- a/mlir/test/Target/Cpp/invalid.mlir
+++ b/mlir/test/Target/Cpp/invalid.mlir
@@ -74,6 +74,13 @@ func.func @pointer_to_array(%arg0 : !emitc.ptr<!emitc.array<4xf32>>) {
// -----
+// expected-error at +1 {{cannot emit lvalue type as argument type}}
+func.func @lvalue_as_argument(%arg: !emitc.lvalue<i8>) {
+ return
+}
+
+// -----
+
// expected-error at +1 {{cannot emit array type as result type}}
func.func @array_as_result(%arg: !emitc.array<4xi8>) -> (!emitc.array<4xi8>) {
return %arg : !emitc.array<4xi8>
diff --git a/mlir/test/Target/Cpp/member.mlir b/mlir/test/Target/Cpp/member.mlir
index df3450c05dbf9e..20589fe5b00b8f 100644
--- a/mlir/test/Target/Cpp/member.mlir
+++ b/mlir/test/Target/Cpp/member.mlir
@@ -1,10 +1,13 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s -check-prefix=CPP-DEFAULT
-func.func @member(%arg0: !emitc.lvalue<!emitc.opaque<"mystruct">>, %arg1: i32) {
- %0 = "emitc.member" (%arg0) {member = "a"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
+func.func @member(%arg0: !emitc.opaque<"mystruct">, %arg1: i32) {
+ %var0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.opaque<"mystruct">>
+ emitc.assign %arg0 : !emitc.opaque<"mystruct"> to %var0 : !emitc.lvalue<!emitc.opaque<"mystruct">>
+
+ %0 = "emitc.member" (%var0) {member = "a"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
emitc.assign %arg1 : i32 to %0 : !emitc.lvalue<i32>
- %1 = "emitc.member" (%arg0) {member = "b"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
+ %1 = "emitc.member" (%var0) {member = "b"} : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
%2 = emitc.load %1 : !emitc.lvalue<i32>
%3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
emitc.assign %2 : i32 to %3 : !emitc.lvalue<i32>
@@ -13,17 +16,22 @@ func.func @member(%arg0: !emitc.lvalue<!emitc.opaque<"mystruct">>, %arg1: i32) {
}
// CPP-DEFAULT: void member(mystruct [[V0:[^ ]*]], int32_t [[V1:[^ ]*]]) {
-// CPP-DEFAULT-NEXT: [[V0]].a = [[V1]];
-// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]] = [[V0]].b;
-// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]];
-// CPP-DEFAULT-NEXT: [[V3]] = [[V2]];
-
-
-func.func @member_of_pointer(%arg0: !emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>, %arg1: i32) {
- %0 = "emitc.member_of_ptr" (%arg0) {member = "a"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
+// CPP-DEFAULT-NEXT: mystruct [[V2:[^ ]*]];
+// CPP-DEFAULT-NEXT: [[V2]] = [[V0]];
+// CPP-DEFAULT-NEXT: [[V2]].a = [[V1]];
+// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]] = [[V2]].b;
+// CPP-DEFAULT-NEXT: int32_t [[V4:[^ ]*]];
+// CPP-DEFAULT-NEXT: [[V4]] = [[V3]];
+
+
+func.func @member_of_pointer(%arg0: !emitc.ptr<!emitc.opaque<"mystruct">>, %arg1: i32) {
+ %var0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>
+ emitc.assign %arg0 : !emitc.ptr<!emitc.opaque<"mystruct">> to %var0 : !emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>
+
+ %0 = "emitc.member_of_ptr" (%var0) {member = "a"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
emitc.assign %arg1 : i32 to %0 : !emitc.lvalue<i32>
- %1 = "emitc.member_of_ptr" (%arg0) {member = "b"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
+ %1 = "emitc.member_of_ptr" (%var0) {member = "b"} : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>) -> !emitc.lvalue<i32>
%2 = emitc.load %1 : !emitc.lvalue<i32>
%3 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<i32>
emitc.assign %2 : i32 to %3 : !emitc.lvalue<i32>
@@ -32,8 +40,10 @@ func.func @member_of_pointer(%arg0: !emitc.lvalue<!emitc.ptr<!emitc.opaque<"myst
}
// CPP-DEFAULT: void member_of_pointer(mystruct* [[V0:[^ ]*]], int32_t [[V1:[^ ]*]]) {
-// CPP-DEFAULT-NEXT: [[V0]]->a = [[V1]];
-// CPP-DEFAULT-NEXT: int32_t [[V2:[^ ]*]] = [[V0]]->b;
-// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]];
-// CPP-DEFAULT-NEXT: [[V3]] = [[V2]];
+// CPP-DEFAULT-NEXT: mystruct* [[V2:[^ ]*]];
+// CPP-DEFAULT-NEXT: [[V2]] = [[V0]];
+// CPP-DEFAULT-NEXT: [[V2]]->a = [[V1]];
+// CPP-DEFAULT-NEXT: int32_t [[V3:[^ ]*]] = [[V2]]->b;
+// CPP-DEFAULT-NEXT: int32_t [[V4:[^ ]*]];
+// CPP-DEFAULT-NEXT: [[V4]] = [[V3]];
>From 5b772cb40749d234b397445598fb5c39f9ed68e8 Mon Sep 17 00:00:00 2001
From: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Date: Mon, 5 Aug 2024 12:40:17 +0000
Subject: [PATCH 14/14] Fix examples in op descriptions
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 38 ++++++++++++++-------
1 file changed, 26 insertions(+), 12 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index dbee2ff5ce7f04..0fdf5c08b5ce95 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -88,11 +88,11 @@ def EmitC_ApplyOp : EmitC_Op<"apply", [CExpression]> {
```mlir
// Custom form of applying the & operator.
- %0 = emitc.apply "&"(%arg0) : (i32) -> !emitc.ptr<i32>
+ %0 = emitc.apply "&"(%arg0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
// Generic form of the same operation.
%0 = "emitc.apply"(%arg0) {applicableOperator = "&"}
- : (i32) -> !emitc.ptr<i32>
+ : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
```
}];
@@ -846,6 +846,16 @@ def EmitC_LoadOp : EmitC_Op<"load", [
This operation loads the content of a modifiable lvalue into an SSA value.
Modifications of the lvalue executed after the load are not observable on
the produced value.
+
+ Example:
+
+ ```mlir
+ %1 = emitc.load %0 : !emitc.lvalue<i32>
+ ```
+ ```c++
+ // Code emitted for the operation above.
+ int32_t v2 = v1;
+ ```
}];
let arguments = (ins
@@ -937,7 +947,7 @@ def EmitC_MemberOp : EmitC_Op<"member"> {
```mlir
%0 = "emitc.member" (%arg0) {member = "a"}
- : (!emitc.opaque<"mystruct">) -> i32
+ : (!emitc.lvalue<!emitc.opaque<"mystruct">>) -> !emitc.lvalue<i32>
```
}];
@@ -958,7 +968,8 @@ def EmitC_MemberOfPtrOp : EmitC_Op<"member_of_ptr"> {
```mlir
%0 = "emitc.member_of_ptr" (%arg0) {member = "a"}
- : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
+ : (!emitc.lvalue<!emitc.ptr<!emitc.opaque<"mystruct">>>)
+ -> !emitc.lvalue<i32>
```
}];
@@ -1061,10 +1072,10 @@ def EmitC_VariableOp : EmitC_Op<"variable", []> {
As an example, it is valid to create pointers to `variable` operations
by using `apply` operations and pass these to a `call` operation.
```mlir
- %0 = "emitc.variable"() {value = 0 : i32} : () -> i32
- %1 = "emitc.variable"() {value = 0 : i32} : () -> i32
- %2 = emitc.apply "&"(%0) : (i32) -> !emitc.ptr<i32>
- %3 = emitc.apply "&"(%1) : (i32) -> !emitc.ptr<i32>
+ %0 = "emitc.variable"() {value = 0 : i32} : () -> !emitc.lvalue<i32>
+ %1 = "emitc.variable"() {value = 0 : i32} : () -> !emitc.lvalue<i32>
+ %2 = emitc.apply "&"(%0) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
+ %3 = emitc.apply "&"(%1) : (!emitc.lvalue<i32>) -> !emitc.ptr<i32>
emitc.call_opaque "write"(%2, %3)
: (!emitc.ptr<i32>, !emitc.ptr<i32>) -> ()
```
@@ -1138,6 +1149,7 @@ def EmitC_GetGlobalOp : EmitC_Op<"get_global",
```mlir
%x = emitc.get_global @foo : !emitc.array<2xf32>
+ %y = emitc.get_global @bar : !emitc.lvalue<i32>
```
}];
@@ -1192,11 +1204,11 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
```mlir
// Integer variable
- %0 = "emitc.variable"(){value = 42 : i32} : () -> i32
+ %0 = "emitc.variable"(){value = 42 : i32} : () -> !emitc.lvalue<i32>
%1 = emitc.call_opaque "foo"() : () -> (i32)
// Assign emitted as `... = ...;`
- "emitc.assign"(%0, %1) : (i32, i32) -> ()
+ "emitc.assign"(%0, %1) : (!emitc.lvalue<i32>, i32) -> ()
```
}];
@@ -1298,8 +1310,10 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
```mlir
%i = index.constant 1
%j = index.constant 7
- %0 = emitc.subscript %arg0[%i, %j] : !emitc.array<4x8xf32>, index, index
- %1 = emitc.subscript %arg1[%i] : !emitc.ptr<i32>, index
+ %0 = emitc.subscript %arg0[%i, %j] : (!emitc.array<4x8xf32>, index, index)
+ -> !emitc.lvalue<f32>
+ %1 = emitc.subscript %arg1[%i] : (!emitc.ptr<i32>, index)
+ -> !emitc.lvalue<i32>
```
}];
let arguments = (ins Arg<AnyTypeOf<[
More information about the Mlir-commits
mailing list