diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp index 0a382d812f362..7f7f4025f1c0d 100644 --- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp +++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp @@ -67,7 +67,7 @@ struct ConvertAlloca final : public OpConversionPattern { LogicalResult matchAndRewrite(memref::AllocaOp op, OpAdaptor operands, ConversionPatternRewriter &rewriter) const override { - + auto memRefType = op.getType(); if (!op.getType().hasStaticShape()) { return rewriter.notifyMatchFailure( op.getLoc(), "cannot transform alloca with dynamic shape"); @@ -80,12 +80,47 @@ struct ConvertAlloca final : public OpConversionPattern { op.getLoc(), "cannot transform alloca with alignment requirement"); } - auto resultTy = getTypeConverter()->convertType(op.getType()); - if (!resultTy) { - return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); + if (op.getType().getRank() == 0 || + llvm::is_contained(memRefType.getShape(), 0)) { + return rewriter.notifyMatchFailure( + op.getLoc(), "cannot transform alloca with rank 0 or zero-sized dim"); + } + + auto convertedTy = getTypeConverter()->convertType(memRefType); + if (!convertedTy) { + return rewriter.notifyMatchFailure(op.getLoc(), + "cannot convert memref type"); } + + auto arrayTy = emitc::ArrayType::get(memRefType.getShape(), + memRefType.getElementType()); + auto elemTy = memRefType.getElementType(); + auto noInit = emitc::OpaqueAttr::get(getContext(), ""); - rewriter.replaceOpWithNewOp(op, resultTy, noInit); + auto arrayVar = + emitc::VariableOp::create(rewriter, op.getLoc(), arrayTy, noInit); + + // Build zero indices for the base subscript. + SmallVector indices; + for (unsigned i = 0; i < memRefType.getRank(); ++i) { + auto zero = emitc::ConstantOp::create(rewriter, + op.getLoc(), rewriter.getIndexType(), rewriter.getIndexAttr(0)); + indices.push_back(zero); + } + + auto current = emitc::SubscriptOp::create(rewriter, + op.getLoc(), emitc::LValueType::get(elemTy), arrayVar.getResult(), + indices); + + auto ptrElemTy = emitc::PointerType::get(elemTy); + auto addrOf = emitc::AddressOfOp::create(rewriter, op.getLoc(), ptrElemTy, + current.getResult()); + + auto ptrArrayTy = emitc::PointerType::get(arrayTy); + auto casted = emitc::CastOp::create(rewriter,op.getLoc(), ptrArrayTy, + addrOf.getResult()); + + rewriter.replaceOp(op, casted.getResult()); return success(); } }; @@ -122,24 +157,6 @@ static Value calculateMemrefTotalSizeBytes(Location loc, MemRefType memrefType, return totalSizeBytes.getResult(); } -static emitc::AddressOfOp -createPointerFromEmitcArray(Location loc, OpBuilder &builder, - TypedValue arrayValue) { - - emitc::ConstantOp zeroIndex = emitc::ConstantOp::create( - builder, loc, builder.getIndexType(), builder.getIndexAttr(0)); - - emitc::ArrayType arrayType = arrayValue.getType(); - llvm::SmallVector indices(arrayType.getRank(), zeroIndex); - emitc::SubscriptOp subPtr = - emitc::SubscriptOp::create(builder, loc, arrayValue, ValueRange(indices)); - emitc::AddressOfOp ptr = emitc::AddressOfOp::create( - builder, loc, emitc::PointerType::get(arrayType.getElementType()), - subPtr); - - return ptr; -} - struct ConvertAlloc final : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult @@ -194,8 +211,9 @@ struct ConvertAlloc final : public OpConversionPattern { emitc::PointerType::get( emitc::OpaqueType::get(rewriter.getContext(), "void")), allocFunctionName, args); - - emitc::PointerType targetPointerType = emitc::PointerType::get(elementType); + emitc::ArrayType arrayType = + emitc::ArrayType::get(memrefType.getShape(), elementType); + emitc::PointerType targetPointerType = emitc::PointerType::get(arrayType); emitc::CastOp castOp = emitc::CastOp::create( rewriter, loc, targetPointerType, allocCall.getResult(0)); @@ -223,20 +241,10 @@ struct ConvertCopy final : public OpConversionPattern { return rewriter.notifyMatchFailure( loc, "incompatible target memref type for EmitC conversion"); - auto srcArrayValue = - cast>(operands.getSource()); - emitc::AddressOfOp srcPtr = - createPointerFromEmitcArray(loc, rewriter, srcArrayValue); - - auto targetArrayValue = - cast>(operands.getTarget()); - emitc::AddressOfOp targetPtr = - createPointerFromEmitcArray(loc, rewriter, targetArrayValue); - emitc::CallOpaqueOp memCpyCall = emitc::CallOpaqueOp::create( rewriter, loc, TypeRange{}, "memcpy", ValueRange{ - targetPtr.getResult(), srcPtr.getResult(), + operands.getTarget(), operands.getSource(), calculateMemrefTotalSizeBytes(loc, srcMemrefType, rewriter)}); rewriter.replaceOp(copyOp, memCpyCall.getResults()); @@ -264,11 +272,14 @@ struct ConvertGlobal final : public OpConversionPattern { "currently not supported"); } - Type resultTy = convertMemRefType(opTy, getTypeConverter()); - - if (!resultTy) { - return rewriter.notifyMatchFailure(op.getLoc(), - "cannot convert result type"); + Type elemTy = getTypeConverter()->convertType(opTy.getElementType()); + Type globalType; + if (opTy.getRank() == 0) { + globalType = elemTy; + } else { + SmallVector shape(opTy.getShape().begin(), + opTy.getShape().end()); + globalType = emitc::ArrayType::get(shape, elemTy); } SymbolTable::Visibility visibility = SymbolTable::getSymbolVisibility(op); @@ -292,7 +303,7 @@ struct ConvertGlobal final : public OpConversionPattern { initialValue = {}; rewriter.replaceOpWithNewOp( - op, operands.getSymName(), resultTy, initialValue, externSpecifier, + op, operands.getSymName(), globalType, initialValue, externSpecifier, staticSpecifier, operands.getConstant()); return success(); } @@ -307,48 +318,147 @@ struct ConvertGetGlobal final ConversionPatternRewriter &rewriter) const override { MemRefType opTy = op.getType(); + Location loc = op.getLoc(); + + Type elemTy = getTypeConverter()->convertType(opTy.getElementType()); + if (!elemTy) + return rewriter.notifyMatchFailure(loc, "cannot convert element type"); + Type resultTy = convertMemRefType(opTy, getTypeConverter()); if (!resultTy) { return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert result type"); } + Type globalType; + if (opTy.getRank() == 0) { + globalType = elemTy; + } else { + SmallVector shape(opTy.getShape().begin(), + opTy.getShape().end()); + globalType = emitc::ArrayType::get(shape, elemTy); + } if (opTy.getRank() == 0) { - emitc::LValueType lvalueType = emitc::LValueType::get(resultTy); + emitc::LValueType lvalueType = emitc::LValueType::get(globalType); emitc::GetGlobalOp globalLValue = emitc::GetGlobalOp::create( rewriter, op.getLoc(), lvalueType, operands.getNameAttr()); - emitc::PointerType pointerType = emitc::PointerType::get(resultTy); - rewriter.replaceOpWithNewOp(op, pointerType, - globalLValue); + emitc::PointerType pointerType = emitc::PointerType::get(globalType); + auto addrOf = emitc::AddressOfOp::create(rewriter, + loc, pointerType, globalLValue.getResult()); + + auto arrayTy = emitc::ArrayType::get({1}, globalType); + auto ptrArrayTy = emitc::PointerType::get(arrayTy); + auto casted = + emitc::CastOp::create(rewriter,loc, ptrArrayTy, addrOf.getResult()); + rewriter.replaceOp(op, casted.getResult()); return success(); } - rewriter.replaceOpWithNewOp(op, resultTy, - operands.getNameAttr()); + + auto getGlobal = emitc::GetGlobalOp::create(rewriter, + loc, globalType, operands.getNameAttr()); + + SmallVector indices; + for (unsigned i = 0; i < opTy.getRank(); ++i) { + auto zero = emitc::ConstantOp::create(rewriter, + loc, rewriter.getIndexType(), rewriter.getIndexAttr(0)); + indices.push_back(zero); + } + + auto current = emitc::SubscriptOp::create(rewriter, + loc, emitc::LValueType::get(elemTy), getGlobal.getResult(), indices); + + auto ptrElemTy = emitc::PointerType::get(opTy.getElementType()); + auto addrOf = emitc::AddressOfOp::create(rewriter, + loc, ptrElemTy, current.getResult()); + + auto casted = + emitc::CastOp::create(rewriter, loc, resultTy, addrOf.getResult()); + + rewriter.replaceOp(op, casted.getResult()); return success(); } }; + +// Helper to compute a flattened linear index for multi-dimensional memrefs +// and generate a single subscript access in EmitC. + +static Value getFlattenedSubscript(ConversionPatternRewriter &rewriter, + Location loc, + Value memrefVal, + ValueRange indices, + Type elementTy) { + auto module = memrefVal.getDefiningOp() ? memrefVal.getDefiningOp()->getParentOfType() + : rewriter.getBlock()->getParentOp()->getParentOfType(); + + // Inject mt_index template once per module to compute flattened indices. + if (module && !module->getAttr("emitc.macros_inserted")) { + OpBuilder::InsertionGuard guard(rewriter); + rewriter.setInsertionPointToStart(module.getBody()); + // The template is used to avoid emitting repeated + // index arithmetic and keeps the generated C/C++ code readable and reusable. + std::string templateDef = + "\n/* Generalized Indexing Template */\n" + "template constexpr T mt_index(T i_last) { return i_last; }\n" + "template \n" + "constexpr T mt_index(T idx, T stride, Args... rest) {\n" + " return (idx * stride) + mt_index(rest...);\n" + "}\n"; + + emitc::VerbatimOp::create(rewriter, loc, rewriter.getStringAttr(templateDef)); + module->setAttr("emitc.macros_inserted", rewriter.getUnitAttr()); + } + + auto ptrTy = cast(memrefVal.getType()); + auto arrayTy = cast(ptrTy.getPointee()); + ArrayRef shape = arrayTy.getShape(); + unsigned rank = indices.size(); + + // Compute static row-major strides from the array shape. + SmallVector strideValues(rank, 1); + for (int i = (int)rank - 2; i >= 0; --i) { + strideValues[i] = strideValues[i + 1] * shape[i + 1]; + } + // build the argument list (index, stride, …) used to invoke it for a given + // memref access. + SmallVector macroArgs; + for (unsigned i = 0; i < rank; ++i) { + macroArgs.push_back(indices[i]); + if (i < rank - 1) { + auto sVal = emitc::ConstantOp::create(rewriter, loc, + rewriter.getIndexType(), + rewriter.getIndexAttr(strideValues[i])); + macroArgs.push_back(sVal.getResult()); + } + } + + auto flatIndex = emitc::CallOpaqueOp::create(rewriter, loc, + rewriter.getIndexType(), + "mt_index", macroArgs); + + auto elemPtrTy = emitc::PointerType::get(elementTy); + auto flatPtr = emitc::CastOp::create(rewriter, loc, elemPtrTy, memrefVal); + auto lvalueTy = emitc::LValueType::get(elementTy); + auto subscript = emitc::SubscriptOp::create(rewriter, loc, + lvalueTy, flatPtr.getResult(), + flatIndex.getResult(0)); + + return subscript.getResult(); +} struct ConvertLoad final : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult matchAndRewrite(memref::LoadOp op, OpAdaptor operands, ConversionPatternRewriter &rewriter) const override { - auto resultTy = getTypeConverter()->convertType(op.getType()); - if (!resultTy) { - return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); - } + if (!resultTy) return failure(); - auto arrayValue = - dyn_cast>(operands.getMemref()); - if (!arrayValue) { - return rewriter.notifyMatchFailure(op.getLoc(), "expected array type"); - } - - auto subscript = emitc::SubscriptOp::create( - rewriter, op.getLoc(), arrayValue, operands.getIndices()); + Value subscript = getFlattenedSubscript(rewriter, op.getLoc(), + operands.getMemref(), + operands.getIndices(), + resultTy); rewriter.replaceOpWithNewOp(op, resultTy, subscript); return success(); @@ -361,16 +471,14 @@ struct ConvertStore final : public OpConversionPattern { LogicalResult matchAndRewrite(memref::StoreOp op, OpAdaptor operands, ConversionPatternRewriter &rewriter) const override { - auto arrayValue = - dyn_cast>(operands.getMemref()); - if (!arrayValue) { - return rewriter.notifyMatchFailure(op.getLoc(), "expected array type"); - } - auto subscript = emitc::SubscriptOp::create( - rewriter, op.getLoc(), arrayValue, operands.getIndices()); - rewriter.replaceOpWithNewOp(op, subscript, - operands.getValue()); + Value valueToStore = operands.getValue(); + Type elementTy = valueToStore.getType(); + Value subscript = getFlattenedSubscript(rewriter, op.getLoc(), + operands.getMemref(), + operands.getIndices(), + elementTy); + rewriter.replaceOpWithNewOp(op, subscript, valueToStore); return success(); } }; @@ -386,8 +494,10 @@ void mlir::populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter) { typeConverter.convertType(memRefType.getElementType()); if (!convertedElementType) return {}; - return emitc::ArrayType::get(memRefType.getShape(), - convertedElementType); + Type innerArrayType = + emitc::ArrayType::get(memRefType.getShape(), convertedElementType); + return emitc::PointerType::get(innerArrayType); + }); auto materializeAsUnrealizedCast = [](OpBuilder &builder, Type resultType, diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp index 15c23c60d0b86..5eea08ec3cc82 100644 --- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp +++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp @@ -1409,6 +1409,7 @@ CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop, labelInScopeCount.push(0); } + void CppEmitter::cacheDeferredOpResult(Value value, StringRef str) { if (!valueMapper.count(value)) valueMapper.insert(value, str.str()); @@ -1827,9 +1828,8 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { // Never emit a semicolon for some operations, especially if endening with // `}`. trailingSemicolon &= - !isa(op); + !isa(op); os << (trailingSemicolon ? ";\n" : "\n"); @@ -1847,6 +1847,17 @@ LogicalResult CppEmitter::emitVariableDeclaration(Location loc, Type type, } return success(); } + // Handle pointer-to-array types: e.g., int (*ptr)[4][8]; + if (auto pType = dyn_cast(type)) { + if (auto arrayPointee = dyn_cast(pType.getPointee())) { + if (failed(emitType(loc, arrayPointee.getElementType()))) + return failure(); + os << " (*" << name << ")"; + for (auto dim : arrayPointee.getShape()) + os << "[" << dim << "]"; + return success(); + } + } if (failed(emitType(loc, type))) return failure(); os << " " << name; @@ -1930,8 +1941,21 @@ LogicalResult CppEmitter::emitType(Location loc, Type type) { if (auto lType = dyn_cast(type)) return emitType(loc, lType.getValueType()); if (auto pType = dyn_cast(type)) { - if (isa(pType.getPointee())) - return emitError(loc, "cannot emit pointer to array type ") << type; + if (auto arrayPointee = dyn_cast(pType.getPointee())) { + if (!arrayPointee.hasStaticShape()) + return emitError( + loc, "cannot emit pointer to array type with non-static shape"); + if (arrayPointee.getShape().empty()) + return emitError(loc, "cannot emit pointer to empty array type"); + + if (failed(emitType(loc, arrayPointee.getElementType()))) + return failure(); + + os << " (*)"; + for (int64_t dim : arrayPointee.getShape()) + os << "[" << dim << "]"; + return success(); + } if (failed(emitType(loc, pType.getPointee()))) return failure(); os << "*"; diff --git a/mlir/test/Conversion/ConvertToEmitC/tosa.mlir b/mlir/test/Conversion/ConvertToEmitC/tosa.mlir index 158018374e72c..d4d20f74429a8 100644 --- a/mlir/test/Conversion/ConvertToEmitC/tosa.mlir +++ b/mlir/test/Conversion/ConvertToEmitC/tosa.mlir @@ -19,22 +19,34 @@ // RUN: mlir-opt --pass-pipeline=%{pipeline} %s | FileCheck %s // ----- +// CHECK: emitc.verbatim "\0A/* Generalized Indexing Template */ +// CHECK-SAME: template constexpr T mt_index(T i_last) +// CHECK-SAME:{ return i_last; }\0Atemplate +// CHECK-SAME: \0Aconstexpr T mt_index(T idx, T stride, Args... rest) +// CHECK-SAME: {\0A return (idx * stride) + mt_index(rest...);\0A}\0A" +// CHECK: emitc.func private @main(%[[ARG0:.*]]: !emitc.ptr>, %[[ARG1:.*]]: !emitc.ptr>, +// CHECK-SAME: %[[ARG2:.*]]: !emitc.ptr>) attributes {specifiers = ["static"]} { +// CHECK-DAG: [[VAR_0_:%.+]] = "emitc.constant"() <{value = 0 : index}> : () -> !emitc.size_t +// CHECK-DAG: [[VAR_1_:%.+]] = "emitc.constant"() <{value = 2 : index}> : () -> !emitc.size_t +// CHECK-DAG: [[VAR_2_:%.+]] = "emitc.constant"() <{value = 1 : index}> : () -> !emitc.size_t +// CHECK: for [[I_0_:%.+]] = [[VAR_0_]] to [[VAR_1_]] step [[VAR_2_]] : !emitc.size_t { +// CHECK-DAG: [[OPAQUE_INDEX_1:%.+]] = call_opaque "mt_index"([[I_0_]]) : (!emitc.size_t) -> index +// CHECK-DAG: [[VAR_9_:%.+]] = cast %[[ARG0]] : !emitc.ptr> to !emitc.ptr +// CHECK: [[SUBSCRIPT_1:%.+]] = subscript [[VAR_9_]]{{.}}[[OPAQUE_INDEX_1]]{{.}} : (!emitc.ptr, index) -> !emitc.lvalue +// CHECK-DAG: [[LOAD_MEM_1:%.+]] = load [[SUBSCRIPT_1]] : +// CHECK-DAG: [[OPAQUE_INDEX_2:%.+]] = call_opaque "mt_index"([[I_0_]]) : (!emitc.size_t) -> index +// CHECK-DAG: [[CAST_1:%.+]] = cast %[[ARG1]] : !emitc.ptr> to !emitc.ptr +// CHECK: [[SUBSCRIPT_2:%.+]] = subscript [[CAST_1]]{{.}}[[OPAQUE_INDEX_2]]{{.}} : (!emitc.ptr, index) -> !emitc.lvalue +// CHECK: [[LOAD_MEM_2:%.+]] = load [[SUBSCRIPT_2]] : +// CHECK-DAG: [[ADD:%.+]] = add [[LOAD_MEM_1]], [[LOAD_MEM_2]] : (f32, f32) -> f32 +// CHECK-DAG: [[OPAQUE_INDEX_3:%.+]] = call_opaque "mt_index"([[I_0_]]) : (!emitc.size_t) -> index +// CHECK-DAG: [[CAST_2:%.+]] = cast %[[ARG2]] : !emitc.ptr> to !emitc.ptr +// CHECK: [[SUBSCRIPT_3:%.+]] = subscript [[CAST_2]]{{.}}[[OPAQUE_INDEX_3]]{{.}} : (!emitc.ptr, index) -> !emitc.lvalue +// CHECK: assign [[ADD]] : f32 to [[SUBSCRIPT_3]] : +// CHECK: } +// CHECK: return +// CHECK: } -// CHECK: emitc.func private @main(%[[ARG0:.*]]: !emitc.array<2xf32>, %[[ARG1:.*]]: !emitc.array<2xf32>, %[[RES:.*]]: !emitc.array<2xf32>) -// CHECK-DAG: %[[C0:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> !emitc.size_t -// CHECK-DAG: %[[C1:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> !emitc.size_t -// CHECK-DAG: %[[C2:.*]] = "emitc.constant"() <{value = 2 : index}> : () -> !emitc.size_t -// CHECK-NEXT: for %[[INDEX:.*]] = %[[C0]] to %[[C2]] step %[[C1]] : !emitc.size_t { -// CHECK-NEXT: %[[V0_LVALUE:.*]] = subscript %[[ARG0]][%[[INDEX]]] : (!emitc.array<2xf32>, !emitc.size_t) -> !emitc.lvalue -// CHECK-NEXT: %[[V0:.*]] = load %[[V0_LVALUE]] : -// CHECK-NEXT: %[[V1_LVALUE:.*]] = subscript %[[ARG1]][%[[INDEX]]] : (!emitc.array<2xf32>, !emitc.size_t) -> !emitc.lvalue -// CHECK-NEXT: %[[V1:.*]] = load %[[V1_LVALUE]] : -// CHECK-NEXT: %[[VADD:.*]] = add %[[V0]], %[[V1]] : (f32, f32) -> f32 -// CHECK-NEXT: %[[RES_LVALUE:.*]] = subscript %[[RES]][%[[INDEX]]] : (!emitc.array<2xf32>, !emitc.size_t) -> !emitc.lvalue -// CHECK-NEXT: assign %[[VADD]] : f32 to %[[RES_LVALUE]] : -// CHECK-NEXT: } -// CHECK-NEXT: return -// CHECK-NEXT: } func.func private @main(%arg0: tensor<2xf32>, %arg1: tensor<2xf32>) -> tensor<2xf32> { %0 = tosa.add %arg0, %arg1 : (tensor<2xf32>, tensor<2xf32>) -> tensor<2xf32> return %0 : tensor<2xf32> diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-copy.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-copy.mlir index 19e1c7ae4263e..4d2b596ccd012 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-copy.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-copy.mlir @@ -7,7 +7,7 @@ func.func @alloc_copy(%arg0: memref<999xi32>) { %alloc_1 = memref.alloc() : memref<999xi32> memref.copy %arg0, %alloc_1 : memref<999xi32> to memref<999xi32> return -} +} // NOCPP: emitc.include <"stdlib.h"> // NOCPP-NEXT: emitc.include <"string.h"> @@ -15,40 +15,25 @@ func.func @alloc_copy(%arg0: memref<999xi32>) { // CPP: emitc.include <"cstdlib"> // CPP-NEXT: emitc.include <"cstring"> -// CHECK-LABEL: func.func @alloc_copy( -// CHECK-SAME: %[[ARG0:.*]]: memref<999xi32>) { -// CHECK: %[[UNREALIZED_CONVERSION_CAST_0:.*]] = builtin.unrealized_conversion_cast %[[ARG0]] : memref<999xi32> to !emitc.array<999xi32> -// CHECK: %[[CALL_OPAQUE_0:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t -// CHECK: %[[VAL_0:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index -// CHECK: %[[MUL_0:.*]] = emitc.mul %[[CALL_OPAQUE_0]], %[[VAL_0]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: %[[CALL_OPAQUE_1:.*]] = emitc.call_opaque "malloc"(%[[MUL_0]]) : (!emitc.size_t) -> !emitc.ptr> -// CHECK: %[[CAST_0:.*]] = emitc.cast %[[CALL_OPAQUE_1]] : !emitc.ptr> to !emitc.ptr -// CHECK: %[[UNREALIZED_CONVERSION_CAST_1:.*]] = builtin.unrealized_conversion_cast %[[CAST_0]] : !emitc.ptr to !emitc.array<999xi32> -// CHECK: %[[VAL_1:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK: %[[SUBSCRIPT_0:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_0]]{{\[}}%[[VAL_1]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[ADDRESS_OF_0:.*]] = emitc.address_of %[[SUBSCRIPT_0]] : !emitc.lvalue -// CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK: %[[SUBSCRIPT_1:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_1]]{{\[}}%[[VAL_2]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[ADDRESS_OF_1:.*]] = emitc.address_of %[[SUBSCRIPT_1]] : !emitc.lvalue -// CHECK: %[[CALL_OPAQUE_2:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t -// CHECK: %[[VAL_3:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index -// CHECK: %[[MUL_1:.*]] = emitc.mul %[[CALL_OPAQUE_2]], %[[VAL_3]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: emitc.call_opaque "memcpy"(%[[ADDRESS_OF_1]], %[[ADDRESS_OF_0]], %[[MUL_1]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () -// CHECK: %[[CALL_OPAQUE_3:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t -// CHECK: %[[VAL_4:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index -// CHECK: %[[MUL_2:.*]] = emitc.mul %[[CALL_OPAQUE_3]], %[[VAL_4]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: %[[CALL_OPAQUE_4:.*]] = emitc.call_opaque "malloc"(%[[MUL_2]]) : (!emitc.size_t) -> !emitc.ptr> -// CHECK: %[[CAST_1:.*]] = emitc.cast %[[CALL_OPAQUE_4]] : !emitc.ptr> to !emitc.ptr -// CHECK: %[[UNREALIZED_CONVERSION_CAST_2:.*]] = builtin.unrealized_conversion_cast %[[CAST_1]] : !emitc.ptr to !emitc.array<999xi32> -// CHECK: %[[VAL_5:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK: %[[SUBSCRIPT_2:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_0]]{{\[}}%[[VAL_5]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[ADDRESS_OF_2:.*]] = emitc.address_of %[[SUBSCRIPT_2]] : !emitc.lvalue -// CHECK: %[[VAL_6:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK: %[[SUBSCRIPT_3:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_2]]{{\[}}%[[VAL_6]]] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK: %[[ADDRESS_OF_3:.*]] = emitc.address_of %[[SUBSCRIPT_3]] : !emitc.lvalue -// CHECK: %[[CALL_OPAQUE_5:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t -// CHECK: %[[VAL_7:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index -// CHECK: %[[MUL_3:.*]] = emitc.mul %[[CALL_OPAQUE_5]], %[[VAL_7]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: emitc.call_opaque "memcpy"(%[[ADDRESS_OF_3]], %[[ADDRESS_OF_2]], %[[MUL_3]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () -// CHECK: return -// CHECK: } +// CHECK-LABEL: alloc_copy +// CHECK-SAME: %[[arg0:.*]]: memref<999xi32> +// CHECK: builtin.unrealized_conversion_cast %arg0 : memref<999xi32> to !emitc.ptr> +// CHECK-NEXT: emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t +// CHECK-NEXT: "emitc.constant"() <{value = 999 : index}> : () -> index +// CHECK-NEXT: emitc.mul %1, %2 : (!emitc.size_t, index) -> !emitc.size_t +// CHECK-NEXT: emitc.call_opaque "malloc"(%3) : (!emitc.size_t) -> !emitc.ptr> +// CHECK-NEXT: emitc.cast %4 : !emitc.ptr> to !emitc.ptr> +// CHECK-NEXT: emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t +// CHECK-NEXT: "emitc.constant"() <{value = 999 : index}> : () -> index +// CHECK-NEXT: emitc.mul %6, %7 : (!emitc.size_t, index) -> !emitc.size_t +// CHECK-NEXT: emitc.call_opaque "memcpy"(%5, %0, %8) : (!emitc.ptr>, !emitc.ptr>, !emitc.size_t) -> () +// CHECK-NEXT: emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t +// CHECK-NEXT: "emitc.constant"() <{value = 999 : index}> : () -> index +// CHECK-NEXT: emitc.mul %9, %10 : (!emitc.size_t, index) -> !emitc.size_t +// CHECK-NEXT: emitc.call_opaque "malloc"(%11) : (!emitc.size_t) -> !emitc.ptr> +// CHECK-NEXT: emitc.cast %12 : !emitc.ptr> to !emitc.ptr> +// CHECK-NEXT: emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t +// CHECK-NEXT: "emitc.constant"() <{value = 999 : index}> : () -> index +// CHECK-NEXT: emitc.mul %14, %15 : (!emitc.size_t, index) -> !emitc.size_t +// CHECK-NEXT: emitc.call_opaque "memcpy"(%13, %0, %16) : (!emitc.ptr>, !emitc.ptr>, !emitc.size_t) -> () +// CHECK-NEXT: return diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir index e391a893bc44a..9336faafb0dfd 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir @@ -13,7 +13,7 @@ func.func @alloc() { // CPP-NEXT: %[[ALLOC_SIZE:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index // CPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t // CPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "malloc"(%[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t) -> !emitc.ptr> -// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr +// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr> // CPP-NEXT: return // NOCPP: module { @@ -23,7 +23,7 @@ func.func @alloc() { // NOCPP-NEXT: %[[ALLOC_SIZE:.*]] = "emitc.constant"() <{value = 999 : index}> : () -> index // NOCPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t // NOCPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "malloc"(%[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t) -> !emitc.ptr> -// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr +// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr> // NOCPP-NEXT: return func.func @alloc_aligned() { @@ -37,7 +37,7 @@ func.func @alloc_aligned() { // CPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t // CPP-NEXT: %[[ALIGNMENT:.*]] = "emitc.constant"() <{value = 64 : index}> : () -> !emitc.size_t // CPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "aligned_alloc"(%[[ALIGNMENT]], %[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t, !emitc.size_t) -> !emitc.ptr> -// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr +// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr> // CPP-NEXT: return // NOCPP-LABEL: alloc_aligned @@ -46,7 +46,7 @@ func.func @alloc_aligned() { // NOCPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t // NOCPP-NEXT: %[[ALIGNMENT:.*]] = "emitc.constant"() <{value = 64 : index}> : () -> !emitc.size_t // NOCPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "aligned_alloc"(%[[ALIGNMENT]], %[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t, !emitc.size_t) -> !emitc.ptr> -// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr +// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr> // NOCPP-NEXT: return func.func @allocating_multi() { @@ -59,7 +59,7 @@ func.func @allocating_multi() { // CPP-NEXT: %[[ALLOC_SIZE:.*]] = "emitc.constant"() <{value = 6993 : index}> : () -> index // CPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t // CPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "malloc"(%[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t) -> !emitc.ptr -// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr +// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr> // CPP-NEXT: return // NOCPP-LABEL: allocating_multi @@ -67,6 +67,6 @@ func.func @allocating_multi() { // NOCPP-NEXT: %[[ALLOC_SIZE:.*]] = "emitc.constant"() <{value = 6993 : index}> : () -> index // NOCPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t // NOCPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "malloc"(%[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t) -> !emitc.ptr> -// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr +// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr> to !emitc.ptr> // NOCPP-NEXT: return diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir index 3de2d25f2b0d4..f82ecf9c6e17c 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir @@ -10,21 +10,15 @@ func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) { // NOCPP: emitc.include <"string.h"> // CPP: emitc.include <"cstring"> -// CHECK-LABEL: func.func @copying( -// CHECK-SAME: %[[ARG0:.*]]: memref<9x4x5x7xf32>, -// CHECK-SAME: %[[ARG1:.*]]: memref<9x4x5x7xf32>) { -// CHECK: %[[UNREALIZED_CONVERSION_CAST_0:.*]] = builtin.unrealized_conversion_cast %[[ARG1]] : memref<9x4x5x7xf32> to !emitc.array<9x4x5x7xf32> -// CHECK: %[[UNREALIZED_CONVERSION_CAST_1:.*]] = builtin.unrealized_conversion_cast %[[ARG0]] : memref<9x4x5x7xf32> to !emitc.array<9x4x5x7xf32> -// CHECK: %[[VAL_0:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK: %[[SUBSCRIPT_0:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_1]]{{\[}}%[[VAL_0]], %[[VAL_0]], %[[VAL_0]], %[[VAL_0]]] : (!emitc.array<9x4x5x7xf32>, index, index, index, index) -> !emitc.lvalue -// CHECK: %[[ADDRESS_OF_0:.*]] = emitc.address_of %[[SUBSCRIPT_0]] : !emitc.lvalue -// CHECK: %[[VAL_1:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK: %[[SUBSCRIPT_1:.*]] = emitc.subscript %[[UNREALIZED_CONVERSION_CAST_0]]{{\[}}%[[VAL_1]], %[[VAL_1]], %[[VAL_1]], %[[VAL_1]]] : (!emitc.array<9x4x5x7xf32>, index, index, index, index) -> !emitc.lvalue -// CHECK: %[[ADDRESS_OF_1:.*]] = emitc.address_of %[[SUBSCRIPT_1]] : !emitc.lvalue -// CHECK: %[[CALL_OPAQUE_0:.*]] = emitc.call_opaque "sizeof"() {args = [f32]} : () -> !emitc.size_t -// CHECK: %[[VAL_2:.*]] = "emitc.constant"() <{value = 1260 : index}> : () -> index -// CHECK: %[[MUL_0:.*]] = emitc.mul %[[CALL_OPAQUE_0]], %[[VAL_2]] : (!emitc.size_t, index) -> !emitc.size_t -// CHECK: emitc.call_opaque "memcpy"(%[[ADDRESS_OF_1]], %[[ADDRESS_OF_0]], %[[MUL_0]]) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () -// CHECK: return -// CHECK: } +// CHECK-LABEL: copying +// CHECK-SAME: %[[arg0:.*]]: memref<9x4x5x7xf32>, %[[arg1:.*]]: memref<9x4x5x7xf32> +// CHECK-NEXT: %0 = builtin.unrealized_conversion_cast %arg1 : memref<9x4x5x7xf32> to !emitc.ptr> +// CHECK-NEXT: %1 = builtin.unrealized_conversion_cast %arg0 : memref<9x4x5x7xf32> to !emitc.ptr> +// CHECK-NEXT: %2 = emitc.call_opaque "sizeof"() {args = [f32]} : () -> !emitc.size_t +// CHECK-NEXT: %3 = "emitc.constant"() <{value = 1260 : index}> : () -> index +// CHECK-NEXT: %4 = emitc.mul %2, %3 : (!emitc.size_t, index) -> !emitc.size_t +// CHECK-NEXT: emitc.call_opaque "memcpy"(%0, %1, %4) : (!emitc.ptr>, !emitc.ptr>, !emitc.size_t) -> () +// CHECK-NEXT: return +// CHECK-NEXT: } +// CHECK-NEXT:} diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir index c7b043b8e2370..61e27014127ae 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir @@ -3,20 +3,32 @@ // CHECK-LABEL: alloca() func.func @alloca() { - // CHECK-NEXT: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<2xf32> + // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<2xf32> + // CHECK-NEXT: [[CONST:%.+]] = "emitc.constant"() <{value = 0 : index}> : () -> index + // CHECK-NEXT: [[SUBSCRIPT:%.+]] = emitc.subscript %[[ALLOCA]]{{.}}[[CONST]]{{.}} : (!emitc.array<2xf32>, index) -> !emitc.lvalue + // CHECK-NEXT: [[ADDR_OF:%.+]] = emitc.address_of [[SUBSCRIPT]] : !emitc.lvalue + // CHECK-NEXT: [[CAST:%.+]] = emitc.cast [[ADDR_OF]] : !emitc.ptr to !emitc.ptr> %0 = memref.alloca() : memref<2xf32> return } // ----- +// CHECK: emitc.verbatim "\0A/* Generalized Indexing Template */ +// CHECK-SAME:\0Atemplate constexpr T mt_index(T i_last) +// CHECK-SAME: { return i_last; }\0Atemplate +// CHECK-SAME: \0Aconstexpr T mt_index(T idx, T stride, Args... rest) +// CHECK-SAME: {\0A return (idx * stride) + mt_index(rest...);\0A}\0A" // CHECK-LABEL: memref_store -// CHECK-SAME: %[[buff:.*]]: memref<4x8xf32>, %[[v:.*]]: f32, %[[i:.*]]: index, %[[j:.*]]: index +// CHECK-SAME: ([[BUFF:%.+]]: memref<4x8xf32>, [[PARAM_1_:%.+]]: f32, [[INDEX_1_:%.+]]: index, [[INDEX_2_:%.+]]: index) { func.func @memref_store(%buff : memref<4x8xf32>, %v : f32, %i: index, %j: index) { - // CHECK-NEXT: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.array<4x8xf32> - - // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue - // CHECK-NEXT: emitc.assign %[[v]] : f32 to %[[SUBSCRIPT]] : +// CHECK-DAG: [[BUFFER:%.+]] = builtin.unrealized_conversion_cast [[BUFF]] : memref<4x8xf32> to !emitc.ptr> +// CHECK-DAG: [[CONST_1:%.+]] = "emitc.constant"() <{value = 8 : index}> : () -> index +// CHECK-DAG: [[CALL_OPAQUE:%.+]] = emitc.call_opaque "mt_index"([[INDEX_1_]], [[CONST_1]], [[INDEX_2_]]) : (index, index, index) -> index +// CHECK-DAG: [[CAST:%.+]] = emitc.cast [[BUFFER]] : !emitc.ptr> to !emitc.ptr +// CHECK: [[SUBSCRIPT:%.+]] = emitc.subscript [[CAST]]{{.}}[[CALL_OPAQUE]]{{.}} : (!emitc.ptr, index) -> !emitc.lvalue +// CHECK: emitc.assign [[PARAM_1_]] : f32 to [[SUBSCRIPT]] : + memref.store %v, %buff[%i, %j] : memref<4x8xf32> return } @@ -26,12 +38,13 @@ func.func @memref_store(%buff : memref<4x8xf32>, %v : f32, %i: index, %j: index) // CHECK-LABEL: memref_load // CHECK-SAME: %[[buff:.*]]: memref<4x8xf32>, %[[i:.*]]: index, %[[j:.*]]: index func.func @memref_load(%buff : memref<4x8xf32>, %i: index, %j: index) -> f32 { - // CHECK-NEXT: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.array<4x8xf32> - - // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue - // CHECK-NEXT: %[[LOAD:.*]] = emitc.load %[[SUBSCRIPT]] : +// CHECK-DAG: [[BUFFER:%.+]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.ptr> +// CHECK-DAG: [[CONST_1:%.+]] = "emitc.constant"() <{value = 8 : index}> : () -> index +// CHECK-DAG: [[CALL_OPAQUE:%.+]] = emitc.call_opaque "mt_index"(%[[i]], [[CONST_1]], %[[j]]) : (index, index, index) -> index +// CHECK-DAG: [[CAST:%.+]] = emitc.cast [[BUFFER]] : !emitc.ptr> to !emitc.ptr +// CHECK: [[SUBSCRIPT:%.+]] = emitc.subscript [[CAST]]{{.}}[[CALL_OPAQUE]]{{.}} : (!emitc.ptr, index) -> !emitc.lvalue +// CHECK: [[LOAD_SUBSCRIPT:%.+]] = emitc.load [[SUBSCRIPT]] : %1 = memref.load %buff[%i, %j] : memref<4x8xf32> - // CHECK-NEXT: return %[[LOAD]] : f32 return %1 : f32 } @@ -51,9 +64,15 @@ module @globals { // CHECK-LABEL: use_global func.func @use_global() { // CHECK-NEXT: emitc.get_global @public_global : !emitc.array<3x7xf32> + // CHECK-NEXT: "emitc.constant"() <{value = 0 : index}> : () -> index + // CHECK-NEXT: "emitc.constant"() <{value = 0 : index}> : () -> index + // CHECK: emitc.subscript %0[%1, %2] : (!emitc.array<3x7xf32>, index, index) -> !emitc.lvalue + // CHECK-NEXT: emitc.address_of %3 : !emitc.lvalue + // CHECK-NEXT: emitc.cast %4 : !emitc.ptr to !emitc.ptr> %0 = memref.get_global @public_global : memref<3x7xf32> // CHECK-NEXT: emitc.get_global @__constant_xi32 : !emitc.lvalue - // CHECK-NEXT: emitc.address_of %1 : !emitc.lvalue + // CHECK-NEXT: emitc.address_of %6 : !emitc.lvalue + // CHECK-NEXT: emitc.cast %7 : !emitc.ptr to !emitc.ptr> %1 = memref.get_global @__constant_xi32 : memref return } diff --git a/mlir/test/Target/Cpp/common-cpp.mlir b/mlir/test/Target/Cpp/common-cpp.mlir index f397a4ae9709f..ff6487defa96d 100644 --- a/mlir/test/Target/Cpp/common-cpp.mlir +++ b/mlir/test/Target/Cpp/common-cpp.mlir @@ -97,7 +97,7 @@ func.func @apply() -> !emitc.ptr { %1 = emitc.apply "&"(%0) : (!emitc.lvalue) -> !emitc.ptr // CHECK-NEXT: int32_t [[V3:[^ ]*]]; %2 = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue - // CHECK-NEXT: int32_t [[V4:[^ ]*]] = *[[V2]]; + // CHECK-NEXT: int32_t [[V4:[^ ]+]] = *[[V2]]; %3 = emitc.apply "*"(%1) : (!emitc.ptr) -> i32 // CHECK-NEXT: [[V3]] = [[V4]]; emitc.assign %3 : i32 to %2 : !emitc.lvalue @@ -136,3 +136,10 @@ func.func @call_opaque_with_template_arg() { // CHECK-NEXT: return return } + +// CHECK : void ptr_to_array() { +func.func @ptr_to_array() { + // CHECK: int16_t (*)[9] v1 = NULL; + %v = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.lvalue>> + return +} diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir index df4627a158319..c01869ed6706b 100644 --- a/mlir/test/Target/Cpp/invalid.mlir +++ b/mlir/test/Target/Cpp/invalid.mlir @@ -65,12 +65,6 @@ func.func @tensor_of_array(%arg0 : tensor<4x!emitc.array<4xf32>>) { return } -// ----- - -// expected-error@+1 {{cannot emit pointer to array type}} -func.func @pointer_to_array(%arg0 : !emitc.ptr>) { - return -} // ----- @@ -86,10 +80,3 @@ func.func @array_as_result(%arg: !emitc.array<4xi8>) -> (!emitc.array<4xi8>) { return %arg : !emitc.array<4xi8> } -// ----- - -func.func @ptr_to_array() { - // expected-error@+1 {{cannot emit pointer to array type '!emitc.ptr>'}} - %v = "emitc.variable"(){value = #emitc.opaque<"NULL">} : () -> !emitc.lvalue>> - return -} diff --git a/mlir/test/Target/Cpp/lvalue.mlir b/mlir/test/Target/Cpp/lvalue.mlir index 2aa438eb6371c..3cd36305e2d73 100644 --- a/mlir/test/Target/Cpp/lvalue.mlir +++ b/mlir/test/Target/Cpp/lvalue.mlir @@ -2,7 +2,7 @@ emitc.func @lvalue_variables(%v1: i32, %v2: i32) -> i32 { %val = emitc.mul %v1, %v2 : (i32, i32) -> i32 - %variable = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue + %variable = "emitc.variable"() {value = #emitc.opaque<"">} : () -> !emitc.lvalue emitc.assign %val : i32 to %variable : !emitc.lvalue %addr = emitc.apply "&"(%variable) : (!emitc.lvalue) -> !emitc.ptr emitc.call @zero (%addr) : (!emitc.ptr) -> () @@ -16,10 +16,10 @@ emitc.func @lvalue_variables(%v1: i32, %v2: i32) -> i32 { // CHECK-NEXT: int32_t [[VAL:[^ ]*]] = [[V1]] * [[V2]]; // CHECK-NEXT: int32_t [[VAR:[^ ]*]]; // CHECK-NEXT: [[VAR]] = [[VAL]]; -// CHECK-NEXT: int32_t* [[VAR_PTR:[^ ]*]] = &[[VAR]]; +// CHECK: int32_t* [[VAR_PTR:.*]] = &[[VAR:.*]]; // CHECK-NEXT: zero([[VAR_PTR]]); -// CHECK-NEXT: int32_t [[VAR_LOAD:[^ ]*]] = [[VAR]]; -// CHECK-NEXT: int32_t [[NEG_ONE:[^ ]*]] = -1; +// CHECK: int32_t [[VAR_LOAD:[^ ]*]] = [[VAR:.*]]; +// CHECK-NEXT: int32_t [[NEG_ONE:[^ ]*]] = -1; // CHECK-NEXT: [[VAR]] = [[NEG_ONE]]; // CHECK-NEXT: return [[VAR_LOAD]];