[Mlir-commits] [mlir] [mlir][emitc] Add 'emitc.switch' op to the dialect (PR #102331)
Andrey Timonin
llvmlistbot at llvm.org
Thu Aug 15 08:38:53 PDT 2024
https://github.com/EtoAndruwa updated https://github.com/llvm/llvm-project/pull/102331
>From 11a57c346a2f5c88f75d23f292ae017617ecd1a1 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Wed, 7 Aug 2024 19:34:36 +0300
Subject: [PATCH 01/25] [mlir][emitc] Add 'emitc.switch' op to the dialect
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.h | 3 +
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 89 ++++++++-
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 206 ++++++++++++++++++++
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 45 ++++-
mlir/test/Target/Cpp/invalid.mlir | 173 ++++++++++++++++
mlir/test/Target/Cpp/switch.mlir | 129 ++++++++++++
6 files changed, 641 insertions(+), 4 deletions(-)
create mode 100644 mlir/test/Target/Cpp/switch.mlir
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
index 87a4078f280f65..c7211c9e9b010e 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
@@ -47,6 +47,9 @@ bool isSupportedFloatType(mlir::Type type);
/// Determines whether \p type is a emitc.size_t/ssize_t type.
bool isPointerWideType(mlir::Type type);
+/// Determines whether \p type is a valid integer or opaque type for SwitchOp.
+bool isSwitchOperandType(Type type);
+
} // namespace emitc
} // namespace mlir
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 16fa58ce47013d..0f1ab8cee8dfa0 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -54,6 +54,8 @@ def CExpression : NativeOpTrait<"emitc::CExpression">;
def IntegerIndexOrOpaqueType : Type<CPred<"emitc::isIntegerIndexOrOpaqueType($_self)">,
"integer, index or opaque type supported by EmitC">;
def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[EmitCFloatType, IntegerIndexOrOpaqueType]>;
+def SwitchOperandType : Type<CPred<"emitc::isSwitchOperandType($_self)">,
+"integer type for switch operation">;
def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> {
let summary = "Addition operation";
@@ -1188,7 +1190,7 @@ def EmitC_AssignOp : EmitC_Op<"assign", []> {
}
def EmitC_YieldOp : EmitC_Op<"yield",
- [Pure, Terminator, ParentOneOf<["ExpressionOp", "IfOp", "ForOp"]>]> {
+ [Pure, Terminator, ParentOneOf<["ExpressionOp", "IfOp", "ForOp", "SwitchOp"]>]> {
let summary = "Block termination operation";
let description = [{
The `emitc.yield` terminates its parent EmitC op's region, optionally yielding
@@ -1302,5 +1304,90 @@ def EmitC_SubscriptOp : EmitC_Op<"subscript", []> {
let assemblyFormat = "$value `[` $indices `]` attr-dict `:` functional-type(operands, results)";
}
+def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
+ SingleBlockImplicitTerminator<"emitc::YieldOp">,
+ DeclareOpInterfaceMethods<RegionBranchOpInterface,
+ ["getRegionInvocationBounds",
+ "getEntrySuccessorRegions"]>]> {
+ let summary = "Switch operation";
+ let description = [{
+ The `emitc.switch` is a control-flow operation that branches to one of
+ the given regions based on the values of the argument and the cases. The
+ argument is always of type opaque or integer (singed or unsigned), excluding i8
+ and i1.
+
+ The operation always has a "default" region and any number of case regions
+ denoted by integer constants. Control-flow transfers to the case region
+ whose constant value equals the value of the argument. If the argument does
+ not equal any of the case values, control-flow transfer to the "default"
+ region.
+
+ The operation does not return any value. Moreover, case regions and
+ default region must be terminated using the `emitc.yield` operation.
+
+ Example:
+
+ ```mlir
+ // Cases with i32 type.
+ %0 = "emitc.variable"(){value = 42 : i32} : () -> i32
+ emitc.switch %0 : i32
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default : {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ ...
+ // Cases with i16 type.
+ %0 = "emitc.variable"(){value = 42 : i16} : () -> i16
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default : {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ ```
+ }];
+
+ let arguments = (ins SwitchOperandType:$arg, DenseI64ArrayAttr:$cases);
+ let results = (outs);
+ let regions = (region SizedRegion<1>:$defaultRegion,
+ VariadicRegion<SizedRegion<1>>:$caseRegions);
+
+ let extraClassDeclaration = [{
+ /// Get the number of cases.
+ unsigned getNumCases();
+
+ /// Get the default region body.
+ Block &getDefaultBlock();
+
+ /// Get the body of a case region.
+ Block &getCaseBlock(unsigned idx);
+ }];
+
+ let hasCustomAssemblyFormat = 1;
+ let hasVerifier = 1;
+}
#endif // MLIR_DIALECT_EMITC_IR_EMITC
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 70e3e728e01950..dc40f3a7cedaa5 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -131,6 +131,13 @@ bool mlir::emitc::isPointerWideType(Type type) {
type);
}
+bool mlir::emitc::isSwitchOperandType(Type type) {
+ auto intType = llvm::dyn_cast<IntegerType>(type);
+ return isa<emitc::OpaqueType>(type) ||
+ (isSupportedIntegerType(type) && intType.getWidth() != 1 &&
+ intType.getWidth() != 8);
+}
+
/// Check that the type of the initial value is compatible with the operations
/// result type.
static LogicalResult verifyInitializationAttribute(Operation *op,
@@ -1096,6 +1103,205 @@ GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
return success();
}
+//===----------------------------------------------------------------------===//
+// SwitchOp
+//===----------------------------------------------------------------------===//
+
+/// Parse the case regions and values.
+static ParseResult
+parseSwitchCases(OpAsmParser &parser, DenseI64ArrayAttr &cases,
+ SmallVectorImpl<std::unique_ptr<Region>> &caseRegions) {
+ SmallVector<int64_t> caseValues;
+ while (succeeded(parser.parseOptionalKeyword("case"))) {
+ int64_t value;
+ Region ®ion = *caseRegions.emplace_back(std::make_unique<Region>());
+
+ if (parser.parseInteger(value) || parser.parseColon() ||
+ parser.parseRegion(region, /*arguments=*/{}))
+ return failure();
+ caseValues.push_back(value);
+ }
+ cases = parser.getBuilder().getDenseI64ArrayAttr(caseValues);
+ return success();
+}
+
+/// Print the case regions and values.
+static void printSwitchCases(OpAsmPrinter &parser, Operation *op,
+ DenseI64ArrayAttr cases, RegionRange caseRegions) {
+ for (auto [value, region] : llvm::zip(cases.asArrayRef(), caseRegions)) {
+ parser.printNewline();
+ parser << "case " << value << ": ";
+ parser.printRegion(*region, /*printEntryBlockArgs=*/false);
+ }
+ return;
+}
+
+ParseResult SwitchOp::parse(OpAsmParser &parser, OperationState &result) {
+ OpAsmParser::UnresolvedOperand arg;
+ DenseI64ArrayAttr casesAttr;
+ SmallVector<std::unique_ptr<Region>, 2> caseRegionsRegions;
+ std::unique_ptr<Region> defaultRegionRegion = std::make_unique<Region>();
+
+ if (parser.parseOperand(arg))
+ return failure();
+
+ Type argType;
+ // Parse the case's type.
+ if (parser.parseColon() || parser.parseType(argType))
+ return failure();
+
+ auto loc = parser.getCurrentLocation();
+ if (parser.parseOptionalAttrDict(result.attributes))
+ return failure();
+
+ if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
+ return parser.emitError(loc)
+ << "'" << result.name.getStringRef() << "' op ";
+ })))
+ return failure();
+
+ auto odsResult = parseSwitchCases(parser, casesAttr, caseRegionsRegions);
+ if (odsResult)
+ return failure();
+
+ result.getOrAddProperties<SwitchOp::Properties>().cases = casesAttr;
+
+ if (parser.parseKeyword("default") || parser.parseColon())
+ return failure();
+
+ if (parser.parseRegion(*defaultRegionRegion))
+ return failure();
+
+ result.addRegion(std::move(defaultRegionRegion));
+ result.addRegions(caseRegionsRegions);
+
+ if (parser.resolveOperand(arg, argType, result.operands))
+ return failure();
+
+ return success();
+}
+
+void SwitchOp::print(OpAsmPrinter &parser) {
+ parser << ' ';
+ parser << getArg();
+ SmallVector<StringRef, 2> elidedAttrs;
+ elidedAttrs.push_back("cases");
+ parser.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
+ parser << ' ';
+ printSwitchCases(parser, *this, getCasesAttr(), getCaseRegions());
+ parser.printNewline();
+ parser << "default";
+ parser << ' ';
+ parser.printRegion(getDefaultRegion(), /*printEntryBlockArgs=*/true,
+ /*printBlockTerminators=*/true);
+
+ return;
+}
+
+static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion,
+ const Twine &name) {
+ auto yield = dyn_cast<emitc::YieldOp>(region.front().back());
+ if (!yield)
+ return op.emitOpError("expected region to end with emitc.yield, but got ")
+ << region.front().back().getName();
+
+ if (yield.getNumOperands() != 0) {
+ return (op.emitOpError("expected each region to return ")
+ << "0 values, but " << name << " returns "
+ << yield.getNumOperands())
+ .attachNote(yield.getLoc())
+ << "see yield operation here";
+ }
+ return success();
+}
+
+LogicalResult emitc::SwitchOp::verify() {
+ if (!isSwitchOperandType(getArg().getType()))
+ return emitOpError("unsupported type ") << getArg().getType();
+
+ if (getCases().size() != getCaseRegions().size()) {
+ return emitOpError("has ")
+ << getCaseRegions().size() << " case regions but "
+ << getCases().size() << " case values";
+ }
+
+ DenseSet<int64_t> valueSet;
+ for (int64_t value : getCases())
+ if (!valueSet.insert(value).second)
+ return emitOpError("has duplicate case value: ") << value;
+
+ if (failed(verifyRegion(*this, getDefaultRegion(), "default region")))
+ return failure();
+
+ for (auto [idx, caseRegion] : llvm::enumerate(getCaseRegions()))
+ if (failed(verifyRegion(*this, caseRegion, "case region #" + Twine(idx))))
+ return failure();
+
+ return success();
+}
+
+unsigned emitc::SwitchOp::getNumCases() { return getCases().size(); }
+
+Block &emitc::SwitchOp::getDefaultBlock() { return getDefaultRegion().front(); }
+
+Block &emitc::SwitchOp::getCaseBlock(unsigned idx) {
+ assert(idx < getNumCases() && "case index out-of-bounds");
+ return getCaseRegions()[idx].front();
+}
+
+void SwitchOp::getSuccessorRegions(
+ RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> &successors) {
+ llvm::copy(getRegions(), std::back_inserter(successors));
+ return;
+}
+
+void SwitchOp::getEntrySuccessorRegions(
+ ArrayRef<Attribute> operands,
+ SmallVectorImpl<RegionSuccessor> &successors) {
+ FoldAdaptor adaptor(operands, *this);
+
+ // If a constant was not provided, all regions are possible successors.
+ auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
+ if (!arg) {
+ llvm::copy(getRegions(), std::back_inserter(successors));
+ return;
+ }
+
+ // Otherwise, try to find a case with a matching value. If not, the
+ // default region is the only successor.
+ for (auto [caseValue, caseRegion] : llvm::zip(getCases(), getCaseRegions())) {
+ if (caseValue == arg.getInt()) {
+ successors.emplace_back(&caseRegion);
+ return;
+ }
+ }
+ successors.emplace_back(&getDefaultRegion());
+ return;
+}
+
+void SwitchOp::getRegionInvocationBounds(
+ ArrayRef<Attribute> operands, SmallVectorImpl<InvocationBounds> &bounds) {
+ auto operandValue = llvm::dyn_cast_or_null<IntegerAttr>(operands.front());
+ if (!operandValue) {
+ // All regions are invoked at most once.
+ bounds.append(getNumRegions(), InvocationBounds(/*lb=*/0, /*ub=*/1));
+ return;
+ }
+
+ unsigned liveIndex = getNumRegions() - 1;
+ const auto *iteratorToInt = llvm::find(getCases(), operandValue.getInt());
+
+ liveIndex = iteratorToInt != getCases().end()
+ ? std::distance(getCases().begin(), iteratorToInt)
+ : liveIndex;
+
+ for (unsigned regIndex = 0, regNum = getNumRegions(); regIndex < regNum;
+ ++regIndex)
+ bounds.emplace_back(/*lb=*/0, /*ub=*/regIndex == liveIndex);
+
+ return;
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 1dadb9dd691e70..8831b95a27246a 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -449,6 +449,45 @@ static LogicalResult printOperation(CppEmitter &emitter, emitc::SubOp subOp) {
return printBinaryOperation(emitter, operation, "-");
}
+static LogicalResult emitSwitchCase(CppEmitter &emitter,
+ raw_indented_ostream &os, Region ®ion) {
+ for (Region::OpIterator iteratorOp = region.op_begin(), end = region.op_end();
+ std::next(iteratorOp) != end; ++iteratorOp) {
+ if (failed(emitter.emitOperation(*iteratorOp, /*trailingSemicolon=*/true)))
+ return failure();
+ }
+ os << "break;\n";
+ return success();
+}
+
+static LogicalResult printOperation(CppEmitter &emitter,
+ emitc::SwitchOp switchOp) {
+ raw_indented_ostream &os = emitter.ostream();
+
+ os << "\nswitch(" << emitter.getOrCreateName(switchOp.getArg()) << ") {";
+
+ for (auto pair : llvm::zip(switchOp.getCases(), switchOp.getCaseRegions())) {
+ os << "\ncase "
+ << "(" << std::get<0>(pair) << ")"
+ << ": {\n";
+ os.indent();
+
+ if (failed(emitSwitchCase(emitter, os, std::get<1>(pair))))
+ return failure();
+
+ os.unindent() << "}";
+ }
+
+ os << "\ndefault: {\n";
+ os.indent();
+
+ if (failed(emitSwitchCase(emitter, os, switchOp.getDefaultRegion())))
+ return failure();
+
+ os.unindent() << "}";
+ return success();
+}
+
static LogicalResult printOperation(CppEmitter &emitter, emitc::CmpOp cmpOp) {
Operation *operation = cmpOp.getOperation();
@@ -998,7 +1037,7 @@ static LogicalResult printFunctionBody(CppEmitter &emitter,
// trailing semicolon is handled within the printOperation function.
bool trailingSemicolon =
!isa<cf::CondBranchOp, emitc::DeclareFuncOp, emitc::ForOp,
- emitc::IfOp, emitc::VerbatimOp>(op);
+ emitc::IfOp, emitc::SwitchOp, emitc::VerbatimOp>(op);
if (failed(emitter.emitOperation(
op, /*trailingSemicolon=*/trailingSemicolon)))
@@ -1509,8 +1548,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) {
emitc::GlobalOp, emitc::IfOp, emitc::IncludeOp,
emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp,
emitc::MulOp, emitc::RemOp, emitc::ReturnOp, emitc::SubOp,
- emitc::UnaryMinusOp, emitc::UnaryPlusOp, emitc::VariableOp,
- emitc::VerbatimOp>(
+ 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/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir
index 513371a09cde1d..d2808476f21f84 100644
--- a/mlir/test/Target/Cpp/invalid.mlir
+++ b/mlir/test/Target/Cpp/invalid.mlir
@@ -80,8 +80,181 @@ 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>>
return
}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+
+ // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
+ emitc.switch %0 : ui16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+
+ // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
+ emitc.switch %0 : ui16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i8} : () -> i8
+
+ // expected-error at +1 {{'emitc.switch' op operand #0 must be integer type for switch operation, but got 'i8'}}
+ emitc.switch %0 : i8
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i1} : () -> i1
+
+ // expected-error at +1 {{'emitc.switch' op operand #0 must be integer type for switch operation, but got 'i1'}}
+ emitc.switch %0 : i1
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ // expected-error at +1 {{custom op 'emitc.switch' expected integer value}}
+ case : {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 3: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ // expected-error at +1 {{custom op 'emitc.switch' expected 'default'}}
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ // expected-error at +1 {{'emitc.switch' op has duplicate case value: 2}}
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 2: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
new file mode 100644
index 00000000000000..878a7e4863856c
--- /dev/null
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -0,0 +1,129 @@
+// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
+
+// CHECK-LABEL: int32_t v1 = 1;
+// CHECK-LABEL: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_i32() {
+ %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
+
+ emitc.switch %0 : i32
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: void emitc_switch_i16() {
+// CHECK: int16_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_i16() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: void emitc_switch_ui16() {
+// CHECK: uint16_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_ui16() {
+ %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+
+ emitc.switch %0 : ui16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
>From 82b8c25b92e347c0dac90ace4058c04f86daf64a Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Thu, 8 Aug 2024 16:03:51 +0300
Subject: [PATCH 02/25] [mlir][emitc] Add support of opaque type and all
integral types
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 4 +-
mlir/test/Target/Cpp/invalid.mlir | 52 -------
mlir/test/Target/Cpp/switch.mlir | 224 +++++++++++++++++++++++++++-
3 files changed, 221 insertions(+), 59 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index dc40f3a7cedaa5..8f3f5f0be7263f 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -133,9 +133,7 @@ bool mlir::emitc::isPointerWideType(Type type) {
bool mlir::emitc::isSwitchOperandType(Type type) {
auto intType = llvm::dyn_cast<IntegerType>(type);
- return isa<emitc::OpaqueType>(type) ||
- (isSupportedIntegerType(type) && intType.getWidth() != 1 &&
- intType.getWidth() != 8);
+ return isa<emitc::OpaqueType>(type) || isSupportedIntegerType(type);
}
/// Check that the type of the initial value is compatible with the operations
diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir
index d2808476f21f84..8db4b7e5ed8f01 100644
--- a/mlir/test/Target/Cpp/invalid.mlir
+++ b/mlir/test/Target/Cpp/invalid.mlir
@@ -139,58 +139,6 @@ func.func @emitc_switch() {
// -----
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i8} : () -> i8
-
- // expected-error at +1 {{'emitc.switch' op operand #0 must be integer type for switch operation, but got 'i8'}}
- emitc.switch %0 : i8
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
-}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i1} : () -> i1
-
- // expected-error at +1 {{'emitc.switch' op operand #0 must be integer type for switch operation, but got 'i1'}}
- emitc.switch %0 : i1
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
-}
-
-// -----
-
func.func @emitc_switch() {
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 878a7e4863856c..92228504c20eb2 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -1,6 +1,6 @@
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
-// CHECK-LABEL: int32_t v1 = 1;
+// CHECK-LABEL: int8_t v1 = 1;
// CHECK-LABEL: switch(v1) {
// CHECK: case (2): {
// CHECK: int32_t v2 = func_b();
@@ -19,10 +19,54 @@
// CHECK: }
// CHECK: return;
// CHECK: }
-func.func @emitc_switch_i32() {
- %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
+func.func @emitc_switch_i8() {
+ %0 = "emitc.variable"(){value = 1 : i8} : () -> i8
- emitc.switch %0 : i32
+ emitc.switch %0 : i8
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+
+// CHECK-LABEL: void emitc_switch_ui8() {
+// CHECK: uint8_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_ui8() {
+ %0 = "emitc.variable"(){value = 1 : ui8} : () -> ui8
+
+ emitc.switch %0 : ui8
case 2: {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
@@ -127,3 +171,175 @@ func.func @emitc_switch_ui16() {
}
return
}
+
+// CHECK-LABEL: void emitc_switch_i32() {
+// CHECK: int32_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_i32() {
+ %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
+
+ emitc.switch %0 : i32
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: void emitc_switch_ui32() {
+// CHECK: uint32_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_ui32() {
+ %0 = "emitc.variable"(){value = 1 : ui32} : () -> ui32
+
+ emitc.switch %0 : ui32
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: void emitc_switch_i64() {
+// CHECK: int64_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_i64() {
+ %0 = "emitc.variable"(){value = 1 : i64} : () -> i64
+
+ emitc.switch %0 : i64
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CHECK-LABEL: void emitc_switch_ui64() {
+// CHECK: uint64_t v1 = 1;
+// CHECK: switch(v1) {
+// CHECK: case (2): {
+// CHECK: int32_t v2 = func_b();
+// CHECK: break;
+// CHECK: }
+// CHECK: case (5): {
+// CHECK: int32_t v3 = func_a();
+// CHECK: break;
+// CHECK: }
+// CHECK: default: {
+// CHECK: float v4 = 4.200000000e+01f;
+// CHECK: float v5 = 4.200000000e+01f;
+// CHECK: func2(v4);
+// CHECK: func3(v5, v4);
+// CHECK: break;
+// CHECK: }
+// CHECK: return;
+// CHECK: }
+func.func @emitc_switch_ui64() {
+ %0 = "emitc.variable"(){value = 1 : ui64} : () -> ui64
+
+ emitc.switch %0 : ui64
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
>From 89b62040c209f97b0cadbc184212c2f54ada7a44 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Thu, 8 Aug 2024 16:16:33 +0300
Subject: [PATCH 03/25] [mlir][emict] Fix description of the switch op
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 0f1ab8cee8dfa0..f0c65548ed396c 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1312,9 +1312,8 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
let summary = "Switch operation";
let description = [{
The `emitc.switch` is a control-flow operation that branches to one of
- the given regions based on the values of the argument and the cases. The
- argument is always of type opaque or integer (singed or unsigned), excluding i8
- and i1.
+ the given regions based on the values of the argument and the cases.
+ The operand to a switch operation is a opaque or integral value.
The operation always has a "default" region and any number of case regions
denoted by integer constants. Control-flow transfers to the case region
@@ -1323,7 +1322,7 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
region.
The operation does not return any value. Moreover, case regions and
- default region must be terminated using the `emitc.yield` operation.
+ default region must be explicitly terminated using the `emitc.yield` operation.
Example:
>From e99904d1c8b0410accd7908d62f8fbbc08db2560 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 13:04:56 +0300
Subject: [PATCH 04/25] [mlir][emitc] NFC
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 29 ++++++++++----------------
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 2 +-
2 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 8f3f5f0be7263f..608199ce9fffe0 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1131,7 +1131,6 @@ static void printSwitchCases(OpAsmPrinter &parser, Operation *op,
parser << "case " << value << ": ";
parser.printRegion(*region, /*printEntryBlockArgs=*/false);
}
- return;
}
ParseResult SwitchOp::parse(OpAsmParser &parser, OperationState &result) {
@@ -1179,21 +1178,19 @@ ParseResult SwitchOp::parse(OpAsmParser &parser, OperationState &result) {
return success();
}
-void SwitchOp::print(OpAsmPrinter &parser) {
- parser << ' ';
- parser << getArg();
+void SwitchOp::print(OpAsmPrinter &p) {
+ p << ' ';
+ p << getArg();
SmallVector<StringRef, 2> elidedAttrs;
elidedAttrs.push_back("cases");
- parser.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
- parser << ' ';
- printSwitchCases(parser, *this, getCasesAttr(), getCaseRegions());
- parser.printNewline();
- parser << "default";
- parser << ' ';
- parser.printRegion(getDefaultRegion(), /*printEntryBlockArgs=*/true,
- /*printBlockTerminators=*/true);
-
- return;
+ p.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
+ p << ' ';
+ printSwitchCases(p, *this, getCasesAttr(), getCaseRegions());
+ p.printNewline();
+ p << "default";
+ p << ' ';
+ p.printRegion(getDefaultRegion(), /*printEntryBlockArgs=*/true,
+ /*printBlockTerminators=*/true);
}
static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion,
@@ -1250,7 +1247,6 @@ Block &emitc::SwitchOp::getCaseBlock(unsigned idx) {
void SwitchOp::getSuccessorRegions(
RegionBranchPoint point, SmallVectorImpl<RegionSuccessor> &successors) {
llvm::copy(getRegions(), std::back_inserter(successors));
- return;
}
void SwitchOp::getEntrySuccessorRegions(
@@ -1274,7 +1270,6 @@ void SwitchOp::getEntrySuccessorRegions(
}
}
successors.emplace_back(&getDefaultRegion());
- return;
}
void SwitchOp::getRegionInvocationBounds(
@@ -1296,8 +1291,6 @@ void SwitchOp::getRegionInvocationBounds(
for (unsigned regIndex = 0, regNum = getNumRegions(); regIndex < regNum;
++regIndex)
bounds.emplace_back(/*lb=*/0, /*ub=*/regIndex == liveIndex);
-
- return;
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 8831b95a27246a..ff5515a3bf7c4a 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -464,7 +464,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
emitc::SwitchOp switchOp) {
raw_indented_ostream &os = emitter.ostream();
- os << "\nswitch(" << emitter.getOrCreateName(switchOp.getArg()) << ") {";
+ os << "\nswitch (" << emitter.getOrCreateName(switchOp.getArg()) << ") {";
for (auto pair : llvm::zip(switchOp.getCases(), switchOp.getCaseRegions())) {
os << "\ncase "
>From 5c44e22c90875906eb2318ddf608fdc185e8291a Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 13:50:43 +0300
Subject: [PATCH 05/25] [mlir][emitc] Add test cases for
'-declare-variables-at-top'
---
mlir/test/Target/Cpp/switch.mlir | 670 +++++++++++++++++++++++--------
1 file changed, 509 insertions(+), 161 deletions(-)
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 92228504c20eb2..65367d8f819e58 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -1,24 +1,191 @@
-// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
-
-// CHECK-LABEL: int8_t v1 = 1;
-// CHECK-LABEL: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// 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
+
+// CPP-DEFAULT-LABEL: void emitc_switch_opaque() {
+// CPP-DEFAULT: size_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_opaque() {
+// CPP-DECLTOP: size_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
+func.func @emitc_switch_opaque() {
+ %0 = "emitc.variable"() {value = #emitc.opaque<"1">}
+ : () -> !emitc.opaque<"size_t">
+
+ emitc.switch %0 : !emitc.opaque<"size_t">
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CPP-DEFAULT-LABEL: void emitc_switch_i1() {
+// CPP-DEFAULT: bool v1 = true;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_i1() {
+// CPP-DECLTOP: bool v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = true;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
+func.func @emitc_switch_i1() {
+ %0 = "emitc.variable"(){value = 1 : i1} : () -> i1
+
+ emitc.switch %0 : i1
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CPP-DEFAULT-LABEL: void emitc_switch_i8() {
+// CPP-DEFAULT: int8_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_i8() {
+// CPP-DECLTOP: int8_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_i8() {
%0 = "emitc.variable"(){value = 1 : i8} : () -> i8
@@ -42,27 +209,52 @@ func.func @emitc_switch_i8() {
return
}
+// CPP-DEFAULT-LABEL: void emitc_switch_ui8() {
+// CPP-DEFAULT: uint8_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
-// CHECK-LABEL: void emitc_switch_ui8() {
-// CHECK: uint8_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DECLTOP-LABEL: void emitc_switch_ui8() {
+// CPP-DECLTOP: uint8_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_ui8() {
%0 = "emitc.variable"(){value = 1 : ui8} : () -> ui8
@@ -86,26 +278,52 @@ func.func @emitc_switch_ui8() {
return
}
-// CHECK-LABEL: void emitc_switch_i16() {
-// CHECK: int16_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DEFAULT-LABEL: void emitc_switch_i16() {
+// CPP-DEFAULT: int16_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_i16() {
+// CPP-DECLTOP: int16_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_i16() {
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
@@ -129,26 +347,52 @@ func.func @emitc_switch_i16() {
return
}
-// CHECK-LABEL: void emitc_switch_ui16() {
-// CHECK: uint16_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DEFAULT-LABEL: void emitc_switch_ui16() {
+// CPP-DEFAULT: uint16_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_ui16() {
+// CPP-DECLTOP: uint16_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_ui16() {
%0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
@@ -172,26 +416,52 @@ func.func @emitc_switch_ui16() {
return
}
-// CHECK-LABEL: void emitc_switch_i32() {
-// CHECK: int32_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DEFAULT-LABEL: void emitc_switch_i32() {
+// CPP-DEFAULT: int32_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_i32() {
+// CPP-DECLTOP: int32_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_i32() {
%0 = "emitc.variable"(){value = 1 : i32} : () -> i32
@@ -215,26 +485,52 @@ func.func @emitc_switch_i32() {
return
}
-// CHECK-LABEL: void emitc_switch_ui32() {
-// CHECK: uint32_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DEFAULT-LABEL: void emitc_switch_ui32() {
+// CPP-DEFAULT: uint32_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_ui32() {
+// CPP-DECLTOP: uint32_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_ui32() {
%0 = "emitc.variable"(){value = 1 : ui32} : () -> ui32
@@ -258,26 +554,52 @@ func.func @emitc_switch_ui32() {
return
}
-// CHECK-LABEL: void emitc_switch_i64() {
-// CHECK: int64_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DEFAULT-LABEL: void emitc_switch_i64() {
+// CPP-DEFAULT: int64_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_i64() {
+// CPP-DECLTOP: int64_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_i64() {
%0 = "emitc.variable"(){value = 1 : i64} : () -> i64
@@ -301,26 +623,52 @@ func.func @emitc_switch_i64() {
return
}
-// CHECK-LABEL: void emitc_switch_ui64() {
-// CHECK: uint64_t v1 = 1;
-// CHECK: switch(v1) {
-// CHECK: case (2): {
-// CHECK: int32_t v2 = func_b();
-// CHECK: break;
-// CHECK: }
-// CHECK: case (5): {
-// CHECK: int32_t v3 = func_a();
-// CHECK: break;
-// CHECK: }
-// CHECK: default: {
-// CHECK: float v4 = 4.200000000e+01f;
-// CHECK: float v5 = 4.200000000e+01f;
-// CHECK: func2(v4);
-// CHECK: func3(v5, v4);
-// CHECK: break;
-// CHECK: }
-// CHECK: return;
-// CHECK: }
+// CPP-DEFAULT-LABEL: void emitc_switch_ui64() {
+// CPP-DEFAULT: uint64_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_ui64() {
+// CPP-DECLTOP: uint64_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
func.func @emitc_switch_ui64() {
%0 = "emitc.variable"(){value = 1 : ui64} : () -> ui64
>From 246e9f710254be4c47de4b41b54737a42fc89c20 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 13:55:46 +0300
Subject: [PATCH 06/25] [mlir][emitc] Fix 'isSwitchOperandType' function
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 608199ce9fffe0..1839d6621af389 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -132,8 +132,8 @@ bool mlir::emitc::isPointerWideType(Type type) {
}
bool mlir::emitc::isSwitchOperandType(Type type) {
- auto intType = llvm::dyn_cast<IntegerType>(type);
- return isa<emitc::OpaqueType>(type) || isSupportedIntegerType(type);
+ return isa<emitc::OpaqueType, IndexType>(type) ||
+ isSupportedIntegerType(type);
}
/// Check that the type of the initial value is compatible with the operations
>From 6f53683cea3dc1bd6787a03ea2743ddf89ece649 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 14:14:00 +0300
Subject: [PATCH 07/25] [mlir][emitc] NFC
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.h | 2 +-
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
index c7211c9e9b010e..8d32e74d68820c 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
@@ -47,7 +47,7 @@ bool isSupportedFloatType(mlir::Type type);
/// Determines whether \p type is a emitc.size_t/ssize_t type.
bool isPointerWideType(mlir::Type type);
-/// Determines whether \p type is a valid integer or opaque type for SwitchOp.
+/// Determines whether \p type is a valid integer, index or opaque type for SwitchOp.
bool isSwitchOperandType(Type type);
} // namespace emitc
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 1839d6621af389..7ce03d9f5bed94 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1124,12 +1124,12 @@ parseSwitchCases(OpAsmParser &parser, DenseI64ArrayAttr &cases,
}
/// Print the case regions and values.
-static void printSwitchCases(OpAsmPrinter &parser, Operation *op,
+static void printSwitchCases(OpAsmPrinter &p, Operation *op,
DenseI64ArrayAttr cases, RegionRange caseRegions) {
for (auto [value, region] : llvm::zip(cases.asArrayRef(), caseRegions)) {
- parser.printNewline();
- parser << "case " << value << ": ";
- parser.printRegion(*region, /*printEntryBlockArgs=*/false);
+ p.printNewline();
+ p << "case " << value << ": ";
+ p.printRegion(*region, /*printEntryBlockArgs=*/false);
}
}
>From 99903071992922c8b8aec1f50c56ce3ca39e42d7 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 14:15:29 +0300
Subject: [PATCH 08/25] [mlir][emitc] Add example of emitted code to the op's
description
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 168 ++++++++++++++++----
1 file changed, 137 insertions(+), 31 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index f0c65548ed396c..2ba5d64d15f129 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1327,44 +1327,150 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
Example:
```mlir
- // Cases with i32 type.
- %0 = "emitc.variable"(){value = 42 : i32} : () -> i32
- emitc.switch %0 : i32
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
+ // Example for i32:
+ func.func @emitc_switch_i32() {
+ %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
+
+ emitc.switch %0 : i32
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
}
- default : {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
+ // Output for i32:
+ void emitc_switch_i32() {
+ int32_t v1 = 1;
+
+ switch (v1) {
+ case (2): {
+ int32_t v2 = func_b();
+ break;
+ }
+ case (5): {
+ int32_t v3 = func_a();
+ break;
+ }
+ default: {
+ float v4 = 4.200000000e+01f;
+ float v5 = 4.200000000e+01f;
+ func2(v4);
+ func3(v5, v4);
+ break;
+ }
+ return;
}
...
- // Cases with i16 type.
- %0 = "emitc.variable"(){value = 42 : i16} : () -> i16
- emitc.switch %0 : i16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
+ // Example for ui16:
+ func.func @emitc_switch_ui16() {
+ %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+
+ emitc.switch %0 : ui16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
}
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
+
+ // Output for ui16:
+ void emitc_switch_ui16() {
+ uint16_t v1 = 1;
+
+ switch (v1) {
+ case (2): {
+ int32_t v2 = func_b();
+ break;
+ }
+ case (5): {
+ int32_t v3 = func_a();
+ break;
+ }
+ default: {
+ float v4 = 4.200000000e+01f;
+ float v5 = 4.200000000e+01f;
+ func2(v4);
+ func3(v5, v4);
+ break;
+ }
+ return;
+ }
+ ...
+ // Example for i64 with `-declare-variables-at-top` option:
+ func.func @emitc_switch_i64() {
+ %0 = "emitc.variable"(){value = 1 : i64} : () -> i64
+
+ emitc.switch %0 : i64
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
}
- default : {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
+ // Output for i64 with `-declare-variables-at-top` option:
+ void emitc_switch_i64() {
+ int64_t v1;
+ float v2;
+ float v3;
+ int32_t v4;
+ int32_t v5;
+ v1 = 1;
+
+ switch (v1) {
+ case (2): {
+ v4 = func_b();
+ break;
+ }
+ case (5): {
+ v5 = func_a();
+ break;
+ }
+ default: {
+ v2 = 4.200000000e+01f;
+ v3 = 4.200000000e+01f;
+ func2(v2);
+ func3(v3, v2);
+ break;
+ }
+ return;
}
```
}];
>From b9793a6f04b3ab1ff9ed86a675c93e957ec52f51 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 15:00:50 +0300
Subject: [PATCH 09/25] [mlir][emitc] NFC
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
index 8d32e74d68820c..5d623a816ed5a1 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
@@ -47,7 +47,8 @@ bool isSupportedFloatType(mlir::Type type);
/// Determines whether \p type is a emitc.size_t/ssize_t type.
bool isPointerWideType(mlir::Type type);
-/// Determines whether \p type is a valid integer, index or opaque type for SwitchOp.
+/// Determines whether \p type is a valid integer, index or opaque type for
+/// SwitchOp.
bool isSwitchOperandType(Type type);
} // namespace emitc
>From 07f8db06d4431df1d4c4e95754b184bacd28c637 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 18:16:15 +0300
Subject: [PATCH 10/25] [mlir][emitc] NFC. Fix 'test_misplaced_yield' test case
---
mlir/test/Dialect/EmitC/invalid_ops.mlir | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 4181b726593e4a..66da0a06a1ac95 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -227,7 +227,7 @@ func.func @sub_pointer_pointer(%arg0: !emitc.ptr<f32>, %arg1: !emitc.ptr<f32>) {
// -----
func.func @test_misplaced_yield() {
- // expected-error @+1 {{'emitc.yield' op expects parent op to be one of 'emitc.expression, emitc.if, emitc.for'}}
+ // expected-error @+1 {{'emitc.yield' op expects parent op to be one of 'emitc.expression, emitc.if, emitc.for, emitc.switch'}}
emitc.yield
return
}
>From e7d1c50985185f49d300980d8aa73d26f192fefb Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 19:17:42 +0300
Subject: [PATCH 11/25] [mlir][emitc] Add conversion from 'scf::index_switch'
to 'emitc::switch'
---
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 52 +++++++-
mlir/test/Conversion/SCFToEmitC/switch.mlir | 121 ++++++++++++++++++
2 files changed, 172 insertions(+), 1 deletion(-)
create mode 100644 mlir/test/Conversion/SCFToEmitC/switch.mlir
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index 0a892422252554..10ac078145e8bb 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -177,9 +177,59 @@ LogicalResult IfLowering::matchAndRewrite(IfOp ifOp,
return success();
}
+// Lower scf::index_switch to emitc::switch, implementing result values as
+// emitc::variable's updated within the case and default regions.
+struct IndexSwitchOpLowering : public OpRewritePattern<IndexSwitchOp> {
+ using OpRewritePattern<IndexSwitchOp>::OpRewritePattern;
+
+ LogicalResult matchAndRewrite(IndexSwitchOp indexSwitchOp,
+ PatternRewriter &rewriter) const override;
+};
+
+LogicalResult
+IndexSwitchOpLowering::matchAndRewrite(IndexSwitchOp indexSwitchOp,
+ PatternRewriter &rewriter) const {
+ Location loc = indexSwitchOp.getLoc();
+
+ // Create an emitc::variable op for each result. These variables will be
+ // assigned to by emitc::assign ops within the case and default regions.
+ SmallVector<Value> resultVariables =
+ createVariablesForResults(indexSwitchOp, rewriter);
+
+ // Utility function to lower the contents of an scf::index_switch regions to
+ // an emitc::switch regions. The contents of the scf::index_switch regions is
+ // moved into the respective emitc::switch regions, but the scf::yield is
+ // replaced not only with an emitc::yield, but also with a sequence of
+ // emitc::assign ops that set the yielded values into the result variables.
+ auto lowerRegion = [&resultVariables, &rewriter](Region ®ion,
+ Region &loweredRegion) {
+ rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.end());
+ Operation *terminator = loweredRegion.back().getTerminator();
+ lowerYield(resultVariables, rewriter, cast<scf::YieldOp>(terminator));
+ };
+
+ auto loweredSwitch = rewriter.create<emitc::SwitchOp>(
+ loc, indexSwitchOp.getArg(), indexSwitchOp.getCases(),
+ indexSwitchOp.getNumCases());
+
+ // Lowering all case regions.
+ for (auto pair : llvm::zip(indexSwitchOp.getCaseRegions(),
+ loweredSwitch.getCaseRegions())) {
+ lowerRegion(std::get<0>(pair), std::get<1>(pair));
+ }
+
+ // Lowering default region.
+ lowerRegion(indexSwitchOp.getDefaultRegion(),
+ loweredSwitch.getDefaultRegion());
+
+ rewriter.replaceOp(indexSwitchOp, resultVariables);
+ return success();
+}
+
void mlir::populateSCFToEmitCConversionPatterns(RewritePatternSet &patterns) {
patterns.add<ForLowering>(patterns.getContext());
patterns.add<IfLowering>(patterns.getContext());
+ patterns.add<IndexSwitchOpLowering>(patterns.getContext());
}
void SCFToEmitCPass::runOnOperation() {
@@ -188,7 +238,7 @@ void SCFToEmitCPass::runOnOperation() {
// Configure conversion to lower out SCF operations.
ConversionTarget target(getContext());
- target.addIllegalOp<scf::ForOp, scf::IfOp>();
+ target.addIllegalOp<scf::ForOp, scf::IfOp, scf::IndexSwitchOp>();
target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
if (failed(
applyPartialConversion(getOperation(), target, std::move(patterns))))
diff --git a/mlir/test/Conversion/SCFToEmitC/switch.mlir b/mlir/test/Conversion/SCFToEmitC/switch.mlir
new file mode 100644
index 00000000000000..ef6018e0405618
--- /dev/null
+++ b/mlir/test/Conversion/SCFToEmitC/switch.mlir
@@ -0,0 +1,121 @@
+// RUN: mlir-opt -allow-unregistered-dialect -convert-scf-to-emitc %s | FileCheck %s
+
+// CHECK-LABEL: func.func @switch_no_result(
+// CHECK-SAME: %[[VAL_0:.*]]: index) {
+// CHECK: emitc.switch %[[VAL_0]]
+// CHECK: case 2: {
+// CHECK: %[[VAL_1:.*]] = arith.constant 10 : i32
+// CHECK: emitc.yield
+// CHECK: }
+// CHECK: case 5: {
+// CHECK: %[[VAL_2:.*]] = arith.constant 20 : i32
+// CHECK: emitc.yield
+// CHECK: }
+// CHECK: default {
+// CHECK: %[[VAL_3:.*]] = arith.constant 30 : i32
+// CHECK: emitc.yield
+// CHECK: }
+// CHECK: return
+// CHECK: }
+func.func @switch_no_result(%arg0 : index) {
+ scf.index_switch %arg0
+ case 2 {
+ %1 = arith.constant 10 : i32
+ scf.yield
+ }
+ case 5 {
+ %2 = arith.constant 20 : i32
+ scf.yield
+ }
+ default {
+ %3 = arith.constant 30 : i32
+ scf.yield
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @switch_one_result(
+// CHECK-SAME: %[[VAL_0:.*]]: index) {
+// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> 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.yield
+// CHECK: }
+// CHECK: case 5: {
+// CHECK: %[[VAL_3:.*]] = arith.constant 20 : 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.yield
+// CHECK: }
+// CHECK: return
+// CHECK: }
+func.func @switch_one_result(%arg0 : index) {
+ %0 = scf.index_switch %arg0 -> i32
+ case 2 {
+ %1 = arith.constant 10 : i32
+ scf.yield %1 : i32
+ }
+ case 5 {
+ %2 = arith.constant 20 : i32
+ scf.yield %2 : i32
+ }
+ default {
+ %3 = arith.constant 30 : i32
+ scf.yield %3 : i32
+ }
+ return
+}
+
+// CHECK-LABEL: func.func @switch_two_results(
+// CHECK-SAME: %[[VAL_0:.*]]: index) {
+// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> i32
+// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> 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.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.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.yield
+// CHECK: }
+// CHECK: return
+// CHECK: }
+func.func @switch_two_results(%arg0 : index) {
+ %0, %1 = scf.index_switch %arg0 -> i32, f32
+ case 2 {
+ %2 = arith.constant 10 : i32
+ %3 = arith.constant 1.2 : f32
+ scf.yield %2, %3 : i32, f32
+ }
+ case 5 {
+ %4 = arith.constant 20 : i32
+ %5 = arith.constant 2.4 : f32
+ scf.yield %4, %5 : i32, f32
+ }
+ default {
+ %6 = arith.constant 30 : i32
+ %7 = arith.constant 3.6 : f32
+ scf.yield %6, %7 : i32, f32
+ }
+ return
+}
>From df8e92b1bc90cd9c43fc10c05914a83229919ecb Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Fri, 9 Aug 2024 19:27:48 +0300
Subject: [PATCH 12/25] [mlir][emitc] Add test case for the index type
---
mlir/test/Target/Cpp/switch.mlir | 69 ++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 65367d8f819e58..f301b7d2fe17a9 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -1,6 +1,75 @@
// 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
+// CPP-DEFAULT-LABEL: void emitc_switch_index() {
+// CPP-DEFAULT: size_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: float v5 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: func3(v5, v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_index() {
+// CPP-DECLTOP: size_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: int32_t v5;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case (2): {
+// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case (5): {
+// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: v3 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: func3(v3, v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
+func.func @emitc_switch_index() {
+ %0 = "emitc.variable"(){value = 1 : index} : () -> index
+
+ emitc.switch %0 : index
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
// CPP-DEFAULT-LABEL: void emitc_switch_opaque() {
// CPP-DEFAULT: size_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
>From dfacff1c0cfd3d47d31e74c046f280d56e135b7c Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Sat, 10 Aug 2024 00:09:07 +0300
Subject: [PATCH 13/25] [mlir][emitc] NFC. Fix op's example in the description
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 162 +++-----------------
1 file changed, 24 insertions(+), 138 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 2ba5d64d15f129..ad3f732614ee9e 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1327,150 +1327,36 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
Example:
```mlir
- // Example for i32:
- func.func @emitc_switch_i32() {
- %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
-
- emitc.switch %0 : i32
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
+ // Example:
+ emitc.switch %0 : i32
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
}
-
- // Output for i32:
- void emitc_switch_i32() {
- int32_t v1 = 1;
-
- switch (v1) {
- case (2): {
- int32_t v2 = func_b();
- break;
- }
- case (5): {
- int32_t v3 = func_a();
- break;
- }
- default: {
- float v4 = 4.200000000e+01f;
- float v5 = 4.200000000e+01f;
- func2(v4);
- func3(v5, v4);
- break;
- }
- return;
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
}
- ...
- // Example for ui16:
- func.func @emitc_switch_ui16() {
- %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
-
- emitc.switch %0 : ui16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
}
- // Output for ui16:
- void emitc_switch_ui16() {
- uint16_t v1 = 1;
-
- switch (v1) {
- case (2): {
- int32_t v2 = func_b();
- break;
- }
- case (5): {
- int32_t v3 = func_a();
- break;
- }
- default: {
- float v4 = 4.200000000e+01f;
- float v5 = 4.200000000e+01f;
- func2(v4);
- func3(v5, v4);
- break;
- }
- return;
+ // Output:
+ switch (v1) {
+ case (2): {
+ int32_t v2 = func_b();
+ break;
}
- ...
- // Example for i64 with `-declare-variables-at-top` option:
- func.func @emitc_switch_i64() {
- %0 = "emitc.variable"(){value = 1 : i64} : () -> i64
-
- emitc.switch %0 : i64
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
+ case (5): {
+ int32_t v3 = func_a();
+ break;
}
-
- // Output for i64 with `-declare-variables-at-top` option:
- void emitc_switch_i64() {
- int64_t v1;
- float v2;
- float v3;
- int32_t v4;
- int32_t v5;
- v1 = 1;
-
- switch (v1) {
- case (2): {
- v4 = func_b();
- break;
- }
- case (5): {
- v5 = func_a();
- break;
- }
- default: {
- v2 = 4.200000000e+01f;
- v3 = 4.200000000e+01f;
- func2(v2);
- func3(v3, v2);
- break;
- }
- return;
+ default: {
+ float v4 = 4.200000000e+01f;
+ func2(v4);
+ break;
}
```
}];
>From 1188105f351201fb67d53b88ef6d2f7a10cb94c7 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 11:51:27 +0300
Subject: [PATCH 14/25] [emitc][mlir] Refactor 'lowerRegion' lambda function
---
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 37 +++++++------------
1 file changed, 13 insertions(+), 24 deletions(-)
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index 10ac078145e8bb..63933515810d44 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -94,6 +94,19 @@ static void lowerYield(SmallVector<Value> &resultVariables,
rewriter.eraseOp(yield);
}
+// Lower the contents of an scf::if/scf::index_switch regions to an
+// emitc::if/emitc::switch regions. The contents of the lowering region is
+// moved into the respective lowered region, but the scf::yield is replaced not
+// only with an emitc::yield, but also with a sequence of emitc::assign ops that
+// set the yielded values into the result variables.
+static void lowerRegion(SmallVector<Value> &resultVariables,
+ PatternRewriter &rewriter, Region ®ion,
+ Region &loweredRegion) {
+ rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.end());
+ Operation *terminator = loweredRegion.back().getTerminator();
+ lowerYield(resultVariables, rewriter, cast<scf::YieldOp>(terminator));
+}
+
LogicalResult ForLowering::matchAndRewrite(ForOp forOp,
PatternRewriter &rewriter) const {
Location loc = forOp.getLoc();
@@ -145,18 +158,6 @@ LogicalResult IfLowering::matchAndRewrite(IfOp ifOp,
SmallVector<Value> resultVariables =
createVariablesForResults(ifOp, rewriter);
- // Utility function to lower the contents of an scf::if region to an emitc::if
- // region. The contents of the scf::if regions is moved into the respective
- // emitc::if regions, but the scf::yield is replaced not only with an
- // emitc::yield, but also with a sequence of emitc::assign ops that set the
- // yielded values into the result variables.
- auto lowerRegion = [&resultVariables, &rewriter](Region ®ion,
- Region &loweredRegion) {
- rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.end());
- Operation *terminator = loweredRegion.back().getTerminator();
- lowerYield(resultVariables, rewriter, cast<scf::YieldOp>(terminator));
- };
-
Region &thenRegion = ifOp.getThenRegion();
Region &elseRegion = ifOp.getElseRegion();
@@ -196,18 +197,6 @@ IndexSwitchOpLowering::matchAndRewrite(IndexSwitchOp indexSwitchOp,
SmallVector<Value> resultVariables =
createVariablesForResults(indexSwitchOp, rewriter);
- // Utility function to lower the contents of an scf::index_switch regions to
- // an emitc::switch regions. The contents of the scf::index_switch regions is
- // moved into the respective emitc::switch regions, but the scf::yield is
- // replaced not only with an emitc::yield, but also with a sequence of
- // emitc::assign ops that set the yielded values into the result variables.
- auto lowerRegion = [&resultVariables, &rewriter](Region ®ion,
- Region &loweredRegion) {
- rewriter.inlineRegionBefore(region, loweredRegion, loweredRegion.end());
- Operation *terminator = loweredRegion.back().getTerminator();
- lowerYield(resultVariables, rewriter, cast<scf::YieldOp>(terminator));
- };
-
auto loweredSwitch = rewriter.create<emitc::SwitchOp>(
loc, indexSwitchOp.getArg(), indexSwitchOp.getCases(),
indexSwitchOp.getNumCases());
>From 125466ae60c7862113feb1b66b6827889fbf0807 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 12:04:41 +0300
Subject: [PATCH 15/25] [mlir][emitc] Add support of pointer wide types
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.h | 4 ----
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 4 +---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 2 +-
3 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
index 5d623a816ed5a1..87a4078f280f65 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
@@ -47,10 +47,6 @@ bool isSupportedFloatType(mlir::Type type);
/// Determines whether \p type is a emitc.size_t/ssize_t type.
bool isPointerWideType(mlir::Type type);
-/// Determines whether \p type is a valid integer, index or opaque type for
-/// SwitchOp.
-bool isSwitchOperandType(Type type);
-
} // namespace emitc
} // namespace mlir
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index ad3f732614ee9e..a0cb177fc5216e 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -54,8 +54,6 @@ def CExpression : NativeOpTrait<"emitc::CExpression">;
def IntegerIndexOrOpaqueType : Type<CPred<"emitc::isIntegerIndexOrOpaqueType($_self)">,
"integer, index or opaque type supported by EmitC">;
def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[EmitCFloatType, IntegerIndexOrOpaqueType]>;
-def SwitchOperandType : Type<CPred<"emitc::isSwitchOperandType($_self)">,
-"integer type for switch operation">;
def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> {
let summary = "Addition operation";
@@ -1361,7 +1359,7 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
```
}];
- let arguments = (ins SwitchOperandType:$arg, DenseI64ArrayAttr:$cases);
+ let arguments = (ins IntegerIndexOrOpaqueType:$arg, DenseI64ArrayAttr:$cases);
let results = (outs);
let regions = (region SizedRegion<1>:$defaultRegion,
VariadicRegion<SizedRegion<1>>:$caseRegions);
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 7ce03d9f5bed94..1f12bd33274967 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1211,7 +1211,7 @@ static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion,
}
LogicalResult emitc::SwitchOp::verify() {
- if (!isSwitchOperandType(getArg().getType()))
+ if (!isIntegerIndexOrOpaqueType(getArg().getType()))
return emitOpError("unsupported type ") << getArg().getType();
if (getCases().size() != getCaseRegions().size()) {
>From 67c45e5e36cf1a7e9aa4b67986365bf1fe561b2f Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 12:59:26 +0300
Subject: [PATCH 16/25] [mlir][emitc] NFC
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 7 +++----
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 4 +---
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 1f12bd33274967..3342b191f9c70a 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1179,16 +1179,14 @@ ParseResult SwitchOp::parse(OpAsmParser &parser, OperationState &result) {
}
void SwitchOp::print(OpAsmPrinter &p) {
- p << ' ';
- p << getArg();
+ p << ' ' << getArg();
SmallVector<StringRef, 2> elidedAttrs;
elidedAttrs.push_back("cases");
p.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
p << ' ';
printSwitchCases(p, *this, getCasesAttr(), getCaseRegions());
p.printNewline();
- p << "default";
- p << ' ';
+ p << "default ";
p.printRegion(getDefaultRegion(), /*printEntryBlockArgs=*/true,
/*printBlockTerminators=*/true);
}
@@ -1207,6 +1205,7 @@ static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion,
.attachNote(yield.getLoc())
<< "see yield operation here";
}
+
return success();
}
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index ff5515a3bf7c4a..9f11845739546d 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -467,9 +467,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
os << "\nswitch (" << emitter.getOrCreateName(switchOp.getArg()) << ") {";
for (auto pair : llvm::zip(switchOp.getCases(), switchOp.getCaseRegions())) {
- os << "\ncase "
- << "(" << std::get<0>(pair) << ")"
- << ": {\n";
+ os << "\ncase (" << std::get<0>(pair) << "): {\n";
os.indent();
if (failed(emitSwitchCase(emitter, os, std::get<1>(pair))))
>From 37046074bc48f11104775e0e2beb07b76fe49a33 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 14:03:46 +0300
Subject: [PATCH 17/25] [mlir][emitc] Delete unused function
'isSwitchOperandType'
---
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 5 -----
1 file changed, 5 deletions(-)
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 3342b191f9c70a..3e76bc2387c1bb 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -131,11 +131,6 @@ bool mlir::emitc::isPointerWideType(Type type) {
type);
}
-bool mlir::emitc::isSwitchOperandType(Type type) {
- return isa<emitc::OpaqueType, IndexType>(type) ||
- isSupportedIntegerType(type);
-}
-
/// Check that the type of the initial value is compatible with the operations
/// result type.
static LogicalResult verifyInitializationAttribute(Operation *op,
>From 64e58a8d71d22bf1f0f27807e0692c7560e2500c Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 14:06:55 +0300
Subject: [PATCH 18/25] [mlir][emitc] Fix missing arguments for the
'lowerRegion' call
---
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index 63933515810d44..b87ee3f0641319 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -167,11 +167,11 @@ LogicalResult IfLowering::matchAndRewrite(IfOp ifOp,
rewriter.create<emitc::IfOp>(loc, ifOp.getCondition(), false, false);
Region &loweredThenRegion = loweredIf.getThenRegion();
- lowerRegion(thenRegion, loweredThenRegion);
+ lowerRegion(resultVariables, rewriter, thenRegion, loweredThenRegion);
if (hasElseBlock) {
Region &loweredElseRegion = loweredIf.getElseRegion();
- lowerRegion(elseRegion, loweredElseRegion);
+ lowerRegion(resultVariables, rewriter, elseRegion, loweredElseRegion);
}
rewriter.replaceOp(ifOp, resultVariables);
@@ -204,11 +204,12 @@ IndexSwitchOpLowering::matchAndRewrite(IndexSwitchOp indexSwitchOp,
// Lowering all case regions.
for (auto pair : llvm::zip(indexSwitchOp.getCaseRegions(),
loweredSwitch.getCaseRegions())) {
- lowerRegion(std::get<0>(pair), std::get<1>(pair));
+ lowerRegion(resultVariables, rewriter, std::get<0>(pair),
+ std::get<1>(pair));
}
// Lowering default region.
- lowerRegion(indexSwitchOp.getDefaultRegion(),
+ lowerRegion(resultVariables, rewriter, indexSwitchOp.getDefaultRegion(),
loweredSwitch.getDefaultRegion());
rewriter.replaceOp(indexSwitchOp, resultVariables);
>From c9a974492a174f153499fe859bd88a6e93f2b4b1 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 14:12:20 +0300
Subject: [PATCH 19/25] [mlir][emitc] NFC. Delete parentheses aroound a case
value
---
mlir/lib/Target/Cpp/TranslateToCpp.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
index 9f11845739546d..8e112e6f7dda65 100644
--- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp
+++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp
@@ -467,7 +467,7 @@ static LogicalResult printOperation(CppEmitter &emitter,
os << "\nswitch (" << emitter.getOrCreateName(switchOp.getArg()) << ") {";
for (auto pair : llvm::zip(switchOp.getCases(), switchOp.getCaseRegions())) {
- os << "\ncase (" << std::get<0>(pair) << "): {\n";
+ os << "\ncase " << std::get<0>(pair) << ": {\n";
os.indent();
if (failed(emitSwitchCase(emitter, os, std::get<1>(pair))))
>From 626ed80894c5c8b4182fca65f7b2dec5dc8974d2 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 15:28:19 +0300
Subject: [PATCH 20/25] [mlir][emitc] NFC. Tests adjusted for updates
---
mlir/test/Target/Cpp/switch.mlir | 428 +++++++++++++++++++------------
1 file changed, 262 insertions(+), 166 deletions(-)
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index f301b7d2fe17a9..06c00532d1e356 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -1,22 +1,203 @@
// 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
+// CPP-DEFAULT-LABEL: void emitc_switch_ptrdiff_t() {
+// CPP-DEFAULT: ptrdiff_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case 2: {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case 5: {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_ptrdiff_t() {
+// CPP-DECLTOP: ptrdiff_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: int32_t v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
+func.func @emitc_switch_ptrdiff_t() {
+ %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ptrdiff_t
+
+ emitc.switch %0 : !emitc.ptrdiff_t
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CPP-DEFAULT-LABEL: void emitc_switch_ssize_t() {
+// CPP-DEFAULT: ssize_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case 2: {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case 5: {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_ssize_t() {
+// CPP-DECLTOP: ssize_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: int32_t v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
+func.func @emitc_switch_ssize_t() {
+ %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ssize_t
+
+ emitc.switch %0 : !emitc.ssize_t
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// CPP-DEFAULT-LABEL: void emitc_switch_size_t() {
+// CPP-DEFAULT: size_t v1 = 1;
+// CPP-DEFAULT: switch (v1) {
+// CPP-DEFAULT: case 2: {
+// CPP-DEFAULT: int32_t v2 = func_b();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: case 5: {
+// CPP-DEFAULT: int32_t v3 = func_a();
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: default: {
+// CPP-DEFAULT: float v4 = 4.200000000e+01f;
+// CPP-DEFAULT: func2(v4);
+// CPP-DEFAULT: break;
+// CPP-DEFAULT: }
+// CPP-DEFAULT: return;
+// CPP-DEFAULT: }
+
+// CPP-DECLTOP-LABEL: void emitc_switch_size_t() {
+// CPP-DECLTOP: size_t v1;
+// CPP-DECLTOP: float v2;
+// CPP-DECLTOP: int32_t v3;
+// CPP-DECLTOP: int32_t v4;
+// CPP-DECLTOP: v1 = 1;
+// CPP-DECLTOP: switch (v1) {
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: default: {
+// CPP-DECLTOP: v2 = 4.200000000e+01f;
+// CPP-DECLTOP: func2(v2);
+// CPP-DECLTOP: break;
+// CPP-DECLTOP: }
+// CPP-DECLTOP: return;
+// CPP-DECLTOP: }
+func.func @emitc_switch_size_t() {
+ %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.size_t
+
+ emitc.switch %0 : !emitc.size_t
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
// CPP-DEFAULT-LABEL: void emitc_switch_index() {
// CPP-DEFAULT: size_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -25,31 +206,28 @@
// CPP-DECLTOP-LABEL: void emitc_switch_index() {
// CPP-DECLTOP: size_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
// CPP-DECLTOP: }
func.func @emitc_switch_index() {
%0 = "emitc.variable"(){value = 1 : index} : () -> index
-
+
emitc.switch %0 : index
case 2: {
%1 = emitc.call_opaque "func_b" () : () -> i32
@@ -61,10 +239,7 @@ func.func @emitc_switch_index() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -73,19 +248,17 @@ func.func @emitc_switch_index() {
// CPP-DEFAULT-LABEL: void emitc_switch_opaque() {
// CPP-DEFAULT: size_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -94,24 +267,21 @@ func.func @emitc_switch_index() {
// CPP-DECLTOP-LABEL: void emitc_switch_opaque() {
// CPP-DECLTOP: size_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -131,10 +301,7 @@ func.func @emitc_switch_opaque() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -143,19 +310,17 @@ func.func @emitc_switch_opaque() {
// CPP-DEFAULT-LABEL: void emitc_switch_i1() {
// CPP-DEFAULT: bool v1 = true;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -164,24 +329,21 @@ func.func @emitc_switch_opaque() {
// CPP-DECLTOP-LABEL: void emitc_switch_i1() {
// CPP-DECLTOP: bool v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = true;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -200,10 +362,7 @@ func.func @emitc_switch_i1() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -212,19 +371,17 @@ func.func @emitc_switch_i1() {
// CPP-DEFAULT-LABEL: void emitc_switch_i8() {
// CPP-DEFAULT: int8_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -233,24 +390,21 @@ func.func @emitc_switch_i1() {
// CPP-DECLTOP-LABEL: void emitc_switch_i8() {
// CPP-DECLTOP: int8_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -269,10 +423,7 @@ func.func @emitc_switch_i8() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -281,19 +432,17 @@ func.func @emitc_switch_i8() {
// CPP-DEFAULT-LABEL: void emitc_switch_ui8() {
// CPP-DEFAULT: uint8_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -302,24 +451,21 @@ func.func @emitc_switch_i8() {
// CPP-DECLTOP-LABEL: void emitc_switch_ui8() {
// CPP-DECLTOP: uint8_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -338,10 +484,7 @@ func.func @emitc_switch_ui8() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -350,19 +493,17 @@ func.func @emitc_switch_ui8() {
// CPP-DEFAULT-LABEL: void emitc_switch_i16() {
// CPP-DEFAULT: int16_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -371,24 +512,21 @@ func.func @emitc_switch_ui8() {
// CPP-DECLTOP-LABEL: void emitc_switch_i16() {
// CPP-DECLTOP: int16_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -407,10 +545,7 @@ func.func @emitc_switch_i16() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -419,19 +554,17 @@ func.func @emitc_switch_i16() {
// CPP-DEFAULT-LABEL: void emitc_switch_ui16() {
// CPP-DEFAULT: uint16_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -440,24 +573,21 @@ func.func @emitc_switch_i16() {
// CPP-DECLTOP-LABEL: void emitc_switch_ui16() {
// CPP-DECLTOP: uint16_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -476,10 +606,7 @@ func.func @emitc_switch_ui16() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -488,19 +615,17 @@ func.func @emitc_switch_ui16() {
// CPP-DEFAULT-LABEL: void emitc_switch_i32() {
// CPP-DEFAULT: int32_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -509,24 +634,21 @@ func.func @emitc_switch_ui16() {
// CPP-DECLTOP-LABEL: void emitc_switch_i32() {
// CPP-DECLTOP: int32_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -545,10 +667,7 @@ func.func @emitc_switch_i32() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -557,19 +676,17 @@ func.func @emitc_switch_i32() {
// CPP-DEFAULT-LABEL: void emitc_switch_ui32() {
// CPP-DEFAULT: uint32_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -578,24 +695,21 @@ func.func @emitc_switch_i32() {
// CPP-DECLTOP-LABEL: void emitc_switch_ui32() {
// CPP-DECLTOP: uint32_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -614,10 +728,7 @@ func.func @emitc_switch_ui32() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -626,19 +737,17 @@ func.func @emitc_switch_ui32() {
// CPP-DEFAULT-LABEL: void emitc_switch_i64() {
// CPP-DEFAULT: int64_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -647,24 +756,21 @@ func.func @emitc_switch_ui32() {
// CPP-DECLTOP-LABEL: void emitc_switch_i64() {
// CPP-DECLTOP: int64_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -683,10 +789,7 @@ func.func @emitc_switch_i64() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
@@ -695,19 +798,17 @@ func.func @emitc_switch_i64() {
// CPP-DEFAULT-LABEL: void emitc_switch_ui64() {
// CPP-DEFAULT: uint64_t v1 = 1;
// CPP-DEFAULT: switch (v1) {
-// CPP-DEFAULT: case (2): {
+// CPP-DEFAULT: case 2: {
// CPP-DEFAULT: int32_t v2 = func_b();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
-// CPP-DEFAULT: case (5): {
+// CPP-DEFAULT: case 5: {
// CPP-DEFAULT: int32_t v3 = func_a();
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: default: {
// CPP-DEFAULT: float v4 = 4.200000000e+01f;
-// CPP-DEFAULT: float v5 = 4.200000000e+01f;
// CPP-DEFAULT: func2(v4);
-// CPP-DEFAULT: func3(v5, v4);
// CPP-DEFAULT: break;
// CPP-DEFAULT: }
// CPP-DEFAULT: return;
@@ -716,24 +817,21 @@ func.func @emitc_switch_i64() {
// CPP-DECLTOP-LABEL: void emitc_switch_ui64() {
// CPP-DECLTOP: uint64_t v1;
// CPP-DECLTOP: float v2;
-// CPP-DECLTOP: float v3;
+// CPP-DECLTOP: int32_t v3;
// CPP-DECLTOP: int32_t v4;
-// CPP-DECLTOP: int32_t v5;
// CPP-DECLTOP: v1 = 1;
// CPP-DECLTOP: switch (v1) {
-// CPP-DECLTOP: case (2): {
-// CPP-DECLTOP: v4 = func_b();
+// CPP-DECLTOP: case 2: {
+// CPP-DECLTOP: v3 = func_b();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
-// CPP-DECLTOP: case (5): {
-// CPP-DECLTOP: v5 = func_a();
+// CPP-DECLTOP: case 5: {
+// CPP-DECLTOP: v4 = func_a();
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: default: {
// CPP-DECLTOP: v2 = 4.200000000e+01f;
-// CPP-DECLTOP: v3 = 4.200000000e+01f;
// CPP-DECLTOP: func2(v2);
-// CPP-DECLTOP: func3(v3, v2);
// CPP-DECLTOP: break;
// CPP-DECLTOP: }
// CPP-DECLTOP: return;
@@ -752,11 +850,9 @@ func.func @emitc_switch_ui64() {
}
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
emitc.yield
}
return
}
+
>From 453d1271b2a3d1fc5b5fbae78e827c8048da90d1 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 15:30:12 +0300
Subject: [PATCH 21/25] [mlir][emitc] Fix op's description
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index a0cb177fc5216e..d5e263e44b3774 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1311,7 +1311,8 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
let description = [{
The `emitc.switch` is a control-flow operation that branches to one of
the given regions based on the values of the argument and the cases.
- The operand to a switch operation is a opaque or integral value.
+ The operand to a switch operation is a opaque, integral or pointer
+ wide types.
The operation always has a "default" region and any number of case regions
denoted by integer constants. Control-flow transfers to the case region
>From f6ba7a92b9f3430488ecde0e4b7ea25183f8f718 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Mon, 12 Aug 2024 15:35:20 +0300
Subject: [PATCH 22/25] [mlir][emitc] Moved some test from 'invalid' to
'invalid_ops'
---
mlir/test/Dialect/EmitC/invalid_ops.mlir | 108 ++++++++++++++++++++
mlir/test/Target/Cpp/invalid.mlir | 120 -----------------------
2 files changed, 108 insertions(+), 120 deletions(-)
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 66da0a06a1ac95..dd438e4f55234e 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -466,3 +466,111 @@ func.func @member_of_ptr(%arg0: i32) {
%0 = "emitc.member_of_ptr" (%arg0) {member = "a"} : (i32) -> i32
return
}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+
+ // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
+ emitc.switch %0 : ui16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+
+ // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
+ emitc.switch %0 : ui16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 5: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ // expected-error at +1 {{custom op 'emitc.switch' expected integer value}}
+ case : {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
+ }
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 3: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ // expected-error at +1 {{custom op 'emitc.switch' expected 'default'}}
+ return
+}
+
+// -----
+
+func.func @emitc_switch() {
+ %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+
+ // expected-error at +1 {{'emitc.switch' op has duplicate case value: 2}}
+ emitc.switch %0 : i16
+ case 2: {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 2: {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default: {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ emitc.yield
+ }
+ return
+}
diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir
index 8db4b7e5ed8f01..4e777239fba662 100644
--- a/mlir/test/Target/Cpp/invalid.mlir
+++ b/mlir/test/Target/Cpp/invalid.mlir
@@ -86,123 +86,3 @@ func.func @ptr_to_array() {
%v = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.ptr<!emitc.array<9xi16>>
return
}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
-
- // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
- emitc.switch %0 : ui16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
-}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
-
- // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
- emitc.switch %0 : ui16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- }
- return
-}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
-
- emitc.switch %0 : i16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- // expected-error at +1 {{custom op 'emitc.switch' expected integer value}}
- case : {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
-}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
-
- emitc.switch %0 : i16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 3: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- // expected-error at +1 {{custom op 'emitc.switch' expected 'default'}}
- return
-}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
-
- // expected-error at +1 {{'emitc.switch' op has duplicate case value: 2}}
- emitc.switch %0 : i16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 2: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- %4 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
-
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.call_opaque "func3" (%3, %4) { args = [1 : index, 0 : index] } : (f32, f32) -> ()
- emitc.yield
- }
- return
-}
>From 3c0971a59f42e592aa759057a3ec3f91d0f655d2 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Tue, 13 Aug 2024 19:00:35 +0300
Subject: [PATCH 23/25] [mlir][emitc] Switching to custom assembly in tablegen
similar to the scf dialect
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 12 ++-
mlir/lib/Dialect/EmitC/IR/EmitC.cpp | 63 +--------------
mlir/test/Conversion/SCFToEmitC/switch.mlir | 22 +++---
mlir/test/Dialect/EmitC/invalid_ops.mlir | 60 +++++---------
mlir/test/Dialect/EmitC/ops.mlir | 20 +++++
mlir/test/Target/Cpp/switch.mlir | 86 ++++++++++-----------
6 files changed, 100 insertions(+), 163 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index d5e263e44b3774..45e5aafd138722 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1320,8 +1320,9 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
not equal any of the case values, control-flow transfer to the "default"
region.
- The operation does not return any value. Moreover, case regions and
- default region must be explicitly terminated using the `emitc.yield` operation.
+ The operation does not return any value. Moreover, case regions must be
+ explicitly terminated using the `emitc.yield` operation. Default region is
+ yielded implicitly.
Example:
@@ -1339,7 +1340,6 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
default: {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.yield
}
// Output:
@@ -1365,6 +1365,11 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
let regions = (region SizedRegion<1>:$defaultRegion,
VariadicRegion<SizedRegion<1>>:$caseRegions);
+ let assemblyFormat = [{
+ $arg `:` type($arg) attr-dict custom<SwitchCases>($cases, $caseRegions) `\n`
+ `` `default` $defaultRegion
+ }];
+
let extraClassDeclaration = [{
/// Get the number of cases.
unsigned getNumCases();
@@ -1376,7 +1381,6 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
Block &getCaseBlock(unsigned idx);
}];
- let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
}
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
index 3e76bc2387c1bb..d731a6756ff630 100644
--- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -1108,8 +1108,7 @@ parseSwitchCases(OpAsmParser &parser, DenseI64ArrayAttr &cases,
while (succeeded(parser.parseOptionalKeyword("case"))) {
int64_t value;
Region ®ion = *caseRegions.emplace_back(std::make_unique<Region>());
-
- if (parser.parseInteger(value) || parser.parseColon() ||
+ if (parser.parseInteger(value) ||
parser.parseRegion(region, /*arguments=*/{}))
return failure();
caseValues.push_back(value);
@@ -1123,69 +1122,11 @@ static void printSwitchCases(OpAsmPrinter &p, Operation *op,
DenseI64ArrayAttr cases, RegionRange caseRegions) {
for (auto [value, region] : llvm::zip(cases.asArrayRef(), caseRegions)) {
p.printNewline();
- p << "case " << value << ": ";
+ p << "case " << value << ' ';
p.printRegion(*region, /*printEntryBlockArgs=*/false);
}
}
-ParseResult SwitchOp::parse(OpAsmParser &parser, OperationState &result) {
- OpAsmParser::UnresolvedOperand arg;
- DenseI64ArrayAttr casesAttr;
- SmallVector<std::unique_ptr<Region>, 2> caseRegionsRegions;
- std::unique_ptr<Region> defaultRegionRegion = std::make_unique<Region>();
-
- if (parser.parseOperand(arg))
- return failure();
-
- Type argType;
- // Parse the case's type.
- if (parser.parseColon() || parser.parseType(argType))
- return failure();
-
- auto loc = parser.getCurrentLocation();
- if (parser.parseOptionalAttrDict(result.attributes))
- return failure();
-
- if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
- return parser.emitError(loc)
- << "'" << result.name.getStringRef() << "' op ";
- })))
- return failure();
-
- auto odsResult = parseSwitchCases(parser, casesAttr, caseRegionsRegions);
- if (odsResult)
- return failure();
-
- result.getOrAddProperties<SwitchOp::Properties>().cases = casesAttr;
-
- if (parser.parseKeyword("default") || parser.parseColon())
- return failure();
-
- if (parser.parseRegion(*defaultRegionRegion))
- return failure();
-
- result.addRegion(std::move(defaultRegionRegion));
- result.addRegions(caseRegionsRegions);
-
- if (parser.resolveOperand(arg, argType, result.operands))
- return failure();
-
- return success();
-}
-
-void SwitchOp::print(OpAsmPrinter &p) {
- p << ' ' << getArg();
- SmallVector<StringRef, 2> elidedAttrs;
- elidedAttrs.push_back("cases");
- p.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
- p << ' ';
- printSwitchCases(p, *this, getCasesAttr(), getCaseRegions());
- p.printNewline();
- p << "default ";
- p.printRegion(getDefaultRegion(), /*printEntryBlockArgs=*/true,
- /*printBlockTerminators=*/true);
-}
-
static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion,
const Twine &name) {
auto yield = dyn_cast<emitc::YieldOp>(region.front().back());
diff --git a/mlir/test/Conversion/SCFToEmitC/switch.mlir b/mlir/test/Conversion/SCFToEmitC/switch.mlir
index ef6018e0405618..659d9f43963efa 100644
--- a/mlir/test/Conversion/SCFToEmitC/switch.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/switch.mlir
@@ -3,17 +3,16 @@
// CHECK-LABEL: func.func @switch_no_result(
// CHECK-SAME: %[[VAL_0:.*]]: index) {
// CHECK: emitc.switch %[[VAL_0]]
-// CHECK: case 2: {
+// CHECK: case 2 {
// CHECK: %[[VAL_1:.*]] = arith.constant 10 : i32
// CHECK: emitc.yield
// CHECK: }
-// CHECK: case 5: {
+// CHECK: case 5 {
// CHECK: %[[VAL_2:.*]] = arith.constant 20 : i32
// CHECK: emitc.yield
// CHECK: }
// CHECK: default {
// CHECK: %[[VAL_3:.*]] = arith.constant 30 : i32
-// CHECK: emitc.yield
// CHECK: }
// CHECK: return
// CHECK: }
@@ -29,21 +28,20 @@ func.func @switch_no_result(%arg0 : index) {
}
default {
%3 = arith.constant 30 : i32
- scf.yield
}
return
}
// CHECK-LABEL: func.func @switch_one_result(
// CHECK-SAME: %[[VAL_0:.*]]: index) {
-// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> i32
+// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
// CHECK: emitc.switch %[[VAL_0]]
-// CHECK: case 2: {
+// CHECK: case 2 {
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : i32
// CHECK: emitc.assign %[[VAL_2]] : i32 to %[[VAL_1]] : i32
// CHECK: emitc.yield
// CHECK: }
-// CHECK: case 5: {
+// CHECK: case 5 {
// CHECK: %[[VAL_3:.*]] = arith.constant 20 : i32
// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : i32
// CHECK: emitc.yield
@@ -51,7 +49,6 @@ func.func @switch_no_result(%arg0 : index) {
// CHECK: default {
// CHECK: %[[VAL_4:.*]] = arith.constant 30 : i32
// CHECK: emitc.assign %[[VAL_4]] : i32 to %[[VAL_1]] : i32
-// CHECK: emitc.yield
// CHECK: }
// CHECK: return
// CHECK: }
@@ -74,17 +71,17 @@ 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 = #[[?]]<"">}> : () -> i32
-// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> f32
+// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
+// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
// CHECK: emitc.switch %[[VAL_0]]
-// CHECK: case 2: {
+// 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.yield
// CHECK: }
-// CHECK: case 5: {
+// 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
@@ -96,7 +93,6 @@ func.func @switch_one_result(%arg0 : index) {
// 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.yield
// CHECK: }
// CHECK: return
// CHECK: }
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index dd438e4f55234e..4b5bcf46c1aab9 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -470,18 +470,18 @@ func.func @member_of_ptr(%arg0: i32) {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+ %0 = "emitc.variable"(){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 : ui16
- case 2: {
+ emitc.switch %0 : i16
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -492,41 +492,19 @@ func.func @emitc_switch() {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
+ %0 = "emitc.variable"(){value = 1 : i32} : () -> i32
- // expected-error at +1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
- emitc.switch %0 : ui16
- case 2: {
- %1 = emitc.call_opaque "func_b" () : () -> i32
- emitc.yield
- }
- case 5: {
- %2 = emitc.call_opaque "func_a" () : () -> i32
- emitc.yield
- }
- default: {
- %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
- emitc.call_opaque "func2" (%3) : (f32) -> ()
- }
- return
-}
-
-// -----
-
-func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
-
- emitc.switch %0 : i16
- case 2: {
+ emitc.switch %0 : i32
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
// expected-error at +1 {{custom op 'emitc.switch' expected integer value}}
- case : {
+ case {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -537,14 +515,14 @@ func.func @emitc_switch() {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+ %0 = "emitc.variable"(){value = 1 : i8} : () -> i8
- emitc.switch %0 : i16
- case 2: {
+ emitc.switch %0 : i8
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 3: {
+ case 3 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
@@ -555,19 +533,19 @@ func.func @emitc_switch() {
// -----
func.func @emitc_switch() {
- %0 = "emitc.variable"(){value = 1 : i16} : () -> i16
+ %0 = "emitc.variable"(){value = 1 : i64} : () -> i64
// expected-error at +1 {{'emitc.switch' op has duplicate case value: 2}}
- emitc.switch %0 : i16
- case 2: {
+ emitc.switch %0 : i64
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 2: {
+ case 2 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
index 20ac077e4402b4..64f22e8ad6b983 100644
--- a/mlir/test/Dialect/EmitC/ops.mlir
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -261,3 +261,23 @@ func.func @member_access(%arg0: !emitc.opaque<"mystruct">, %arg1: !emitc.opaque<
%2 = "emitc.member_of_ptr" (%arg2) {member = "a"} : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
return
}
+
+func.func @switch() {
+ %0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ptrdiff_t
+
+ emitc.switch %0 : !emitc.ptrdiff_t
+ case 1 {
+ %1 = emitc.call_opaque "func_b" () : () -> i32
+ emitc.yield
+ }
+ case 2 {
+ %2 = emitc.call_opaque "func_a" () : () -> i32
+ emitc.yield
+ }
+ default {
+ %3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
+ emitc.call_opaque "func2" (%3) : (f32) -> ()
+ }
+
+ return
+}
diff --git a/mlir/test/Target/Cpp/switch.mlir b/mlir/test/Target/Cpp/switch.mlir
index 06c00532d1e356..0f2e716a98f16b 100644
--- a/mlir/test/Target/Cpp/switch.mlir
+++ b/mlir/test/Target/Cpp/switch.mlir
@@ -46,18 +46,17 @@ func.func @emitc_switch_ptrdiff_t() {
%0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ptrdiff_t
emitc.switch %0 : !emitc.ptrdiff_t
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
- emitc.yield
}
return
}
@@ -107,15 +106,15 @@ func.func @emitc_switch_ssize_t() {
%0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ssize_t
emitc.switch %0 : !emitc.ssize_t
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -168,15 +167,15 @@ func.func @emitc_switch_size_t() {
%0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.size_t
emitc.switch %0 : !emitc.size_t
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -229,15 +228,15 @@ func.func @emitc_switch_index() {
%0 = "emitc.variable"(){value = 1 : index} : () -> index
emitc.switch %0 : index
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -291,15 +290,15 @@ func.func @emitc_switch_opaque() {
: () -> !emitc.opaque<"size_t">
emitc.switch %0 : !emitc.opaque<"size_t">
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -352,15 +351,15 @@ func.func @emitc_switch_i1() {
%0 = "emitc.variable"(){value = 1 : i1} : () -> i1
emitc.switch %0 : i1
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -413,15 +412,15 @@ func.func @emitc_switch_i8() {
%0 = "emitc.variable"(){value = 1 : i8} : () -> i8
emitc.switch %0 : i8
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -474,15 +473,15 @@ func.func @emitc_switch_ui8() {
%0 = "emitc.variable"(){value = 1 : ui8} : () -> ui8
emitc.switch %0 : ui8
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -535,15 +534,15 @@ func.func @emitc_switch_i16() {
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
emitc.switch %0 : i16
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -596,15 +595,15 @@ func.func @emitc_switch_ui16() {
%0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
emitc.switch %0 : ui16
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -657,15 +656,15 @@ func.func @emitc_switch_i32() {
%0 = "emitc.variable"(){value = 1 : i32} : () -> i32
emitc.switch %0 : i32
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -718,15 +717,15 @@ func.func @emitc_switch_ui32() {
%0 = "emitc.variable"(){value = 1 : ui32} : () -> ui32
emitc.switch %0 : ui32
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -779,15 +778,15 @@ func.func @emitc_switch_i64() {
%0 = "emitc.variable"(){value = 1 : i64} : () -> i64
emitc.switch %0 : i64
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
@@ -840,19 +839,18 @@ func.func @emitc_switch_ui64() {
%0 = "emitc.variable"(){value = 1 : ui64} : () -> ui64
emitc.switch %0 : ui64
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
emitc.yield
}
return
}
-
>From 33a8667f11e587d9f6d530fab0f998d07d618d95 Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Wed, 14 Aug 2024 12:26:00 +0300
Subject: [PATCH 24/25] [mlir][emitc] NFC
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 45e5aafd138722..1bd18a95764ca9 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1329,26 +1329,26 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
```mlir
// Example:
emitc.switch %0 : i32
- case 2: {
+ case 2 {
%1 = emitc.call_opaque "func_b" () : () -> i32
emitc.yield
}
- case 5: {
+ case 5 {
%2 = emitc.call_opaque "func_a" () : () -> i32
emitc.yield
}
- default: {
+ default {
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
}
// Output:
switch (v1) {
- case (2): {
+ case 2: {
int32_t v2 = func_b();
break;
}
- case (5): {
+ case 5: {
int32_t v3 = func_a();
break;
}
>From 408f667f04c6410a500e9ad628a9cc20b5c17fab Mon Sep 17 00:00:00 2001
From: EtoAndruwa <timonina1909 at gmail.com>
Date: Thu, 15 Aug 2024 18:38:29 +0300
Subject: [PATCH 25/25] [mlir][emitc] NFC
---
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td | 5 +++--
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
index 1bd18a95764ca9..40903b4e288ca6 100644
--- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -1341,8 +1341,9 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
emitc.call_opaque "func2" (%3) : (f32) -> ()
}
-
- // Output:
+ ```
+ ```c++
+ // Code emitted for the operations above.
switch (v1) {
case 2: {
int32_t v2 = func_b();
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index b87ee3f0641319..ede811c6e1bb1e 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -95,7 +95,7 @@ static void lowerYield(SmallVector<Value> &resultVariables,
}
// Lower the contents of an scf::if/scf::index_switch regions to an
-// emitc::if/emitc::switch regions. The contents of the lowering region is
+// emitc::if/emitc::switch region. The contents of the lowering region is
// moved into the respective lowered region, but the scf::yield is replaced not
// only with an emitc::yield, but also with a sequence of emitc::assign ops that
// set the yielded values into the result variables.
More information about the Mlir-commits
mailing list