diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp index 11f866c103639..814723aa05826 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,48 @@ 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 = + rewriter.create(op.getLoc(), arrayTy, noInit); + + // Build zero indices for the base subscript. + SmallVector indices; + for (unsigned i = 0; i < memRefType.getRank(); ++i) { + auto zero = rewriter.create( + op.getLoc(), rewriter.getIndexType(), rewriter.getIndexAttr(0)); + indices.push_back(zero); + } + + auto current = rewriter.create( + op.getLoc(), emitc::LValueType::get(elemTy), arrayVar.getResult(), + indices); + + auto ptrElemTy = emitc::PointerType::get(elemTy); + auto addrOf = rewriter.create(op.getLoc(), ptrElemTy, + rewriter.getStringAttr("&"), + current.getResult()); + + auto ptrArrayTy = emitc::PointerType::get(arrayTy); + auto casted = rewriter.create(op.getLoc(), ptrArrayTy, + addrOf.getResult()); + + rewriter.replaceOp(op, casted.getResult()); return success(); } }; @@ -122,24 +158,6 @@ static Value calculateMemrefTotalSizeBytes(Location loc, MemRefType memrefType, return totalSizeBytes.getResult(); } -static emitc::ApplyOp -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::ApplyOp ptr = emitc::ApplyOp::create( - builder, loc, emitc::PointerType::get(arrayType.getElementType()), - builder.getStringAttr("&"), subPtr); - - return ptr; -} - struct ConvertAlloc final : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult @@ -194,8 +212,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 +242,10 @@ struct ConvertCopy final : public OpConversionPattern { return rewriter.notifyMatchFailure( loc, "incompatible target memref type for EmitC conversion"); - auto srcArrayValue = - cast>(operands.getSource()); - emitc::ApplyOp srcPtr = - createPointerFromEmitcArray(loc, rewriter, srcArrayValue); - - auto targetArrayValue = - cast>(operands.getTarget()); - emitc::ApplyOp 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 +273,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 +304,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,24 +319,64 @@ 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, rewriter.getStringAttr("&"), globalLValue); + emitc::PointerType pointerType = emitc::PointerType::get(globalType); + auto addrOf = rewriter.create( + loc, pointerType, rewriter.getStringAttr("&"), globalLValue.getResult()); + + auto arrayTy = emitc::ArrayType::get({1}, globalType); + auto ptrArrayTy = emitc::PointerType::get(arrayTy); + auto casted = + rewriter.create(loc, ptrArrayTy, addrOf.getResult()); + rewriter.replaceOp(op, casted.getResult()); return success(); } - rewriter.replaceOpWithNewOp(op, resultTy, - operands.getNameAttr()); + + auto getGlobal = rewriter.create( + loc, globalType, operands.getNameAttr()); + + SmallVector indices; + for (unsigned i = 0; i < opTy.getRank(); ++i) { + auto zero = rewriter.create( + loc, rewriter.getIndexType(), rewriter.getIndexAttr(0)); + indices.push_back(zero); + } + + auto current = rewriter.create( + loc, emitc::LValueType::get(elemTy), getGlobal.getResult(), indices); + + auto ptrElemTy = emitc::PointerType::get(opTy.getElementType()); + auto addrOf = rewriter.create( + loc, ptrElemTy, rewriter.getStringAttr("&"), current.getResult()); + + auto casted = + rewriter.create(loc, resultTy, addrOf.getResult()); + + rewriter.replaceOp(op, casted.getResult()); return success(); } }; @@ -340,13 +392,17 @@ struct ConvertLoad final : public OpConversionPattern { if (!resultTy) { return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); } - - auto arrayValue = - dyn_cast>(operands.getMemref()); - if (!arrayValue) { - return rewriter.notifyMatchFailure(op.getLoc(), "expected array type"); + ImplicitLocOpBuilder b(op.getLoc(), rewriter); + Value memrefVal = operands.getMemref(); + Value deref; + if (auto ptrVal = dyn_cast>(memrefVal)) { + auto arrayTy = dyn_cast(ptrVal.getType().getPointee()); + if (!arrayTy) + return failure(); + deref = emitc::ApplyOp::create(b, arrayTy, b.getStringAttr("*"), ptrVal); } + auto arrayValue = dyn_cast>(deref); auto subscript = emitc::SubscriptOp::create( rewriter, op.getLoc(), arrayValue, operands.getIndices()); @@ -361,16 +417,21 @@ 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"); + ImplicitLocOpBuilder b(op.getLoc(), rewriter); + Value memrefVal = operands.getMemref(); + Value deref; + if (auto ptrVal = dyn_cast>(memrefVal)) { + auto arrayTy = dyn_cast(ptrVal.getType().getPointee()); + if (!arrayTy) + return failure(); + deref = emitc::ApplyOp::create(b, arrayTy, b.getStringAttr("*"), ptrVal); } - + auto arrayValue = dyn_cast>(deref); auto subscript = emitc::SubscriptOp::create( rewriter, op.getLoc(), arrayValue, operands.getIndices()); - rewriter.replaceOpWithNewOp(op, subscript, - operands.getValue()); + Value valueToStore = operands.getOperands()[0]; + + rewriter.replaceOpWithNewOp(op, subscript, valueToStore); return success(); } }; @@ -386,8 +447,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 12435119b98a1..228f37cee42b4 100644 --- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp +++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp @@ -192,6 +192,9 @@ struct CppEmitter { // Returns the textual representation of a subscript operation. std::string getSubscriptName(emitc::SubscriptOp op); + // Returns a string representing the expression of an emitc.apply operation. + std::string getApplyName(emitc::ApplyOp op); + // Returns the textual representation of a member (of object) operation. std::string createMemberAccess(emitc::MemberOp op); @@ -1339,13 +1342,52 @@ CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop, std::string CppEmitter::getSubscriptName(emitc::SubscriptOp op) { std::string out; llvm::raw_string_ostream ss(out); - ss << getOrCreateName(op.getValue()); + Value baseValue = op.getValue(); + + if (auto applyOp = baseValue.getDefiningOp()) { + if (applyOp.getApplicableOperator() == "*") + ss << "(*" << getOrCreateName(applyOp.getOperand()) << ")"; + else + ss << getOrCreateName(baseValue); + } else { + ss << getOrCreateName(baseValue); + } + for (auto index : op.getIndices()) { ss << "[" << getOrCreateName(index) << "]"; } return out; } +std::string CppEmitter::getApplyName(emitc::ApplyOp op) { + std::string expr; + llvm::raw_string_ostream ss(expr); + + StringRef opStr = op.getApplicableOperator(); + Value operand = op.getOperand(); + + if (opStr == "&") { + ss << "&" << getOrCreateName(operand); + return ss.str(); + } + + // Emit '*(&x)' form + if (opStr == "*") { + if (auto innerApply = operand.getDefiningOp()) { + StringRef innerOp = innerApply.getApplicableOperator(); + if (innerOp == "&") { + ss << "*(&" << getOrCreateName(innerApply.getOperand()) << ")"; + return ss.str(); + } + } + ss << "*" << getOrCreateName(operand); + return ss.str(); + } + + ss << getOrCreateName(operand) << opStr; + return ss.str(); +} + std::string CppEmitter::createMemberAccess(emitc::MemberOp op) { std::string out; llvm::raw_string_ostream ss(out); @@ -1753,20 +1795,19 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { .Case( [&](auto op) { return printOperation(*this, op); }) // EmitC ops. - .Case( + .Case( [&](auto op) { return printOperation(*this, op); }) // Func ops. @@ -1796,6 +1837,22 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { cacheDeferredOpResult(op.getResult(), getSubscriptName(op)); return success(); }) + .Case([&](emitc::ApplyOp op) { + if (emittedExpression) { + return printOperation(*this, op); + } + std::string expr = getApplyName(op); + cacheDeferredOpResult(op.getResult(), expr); + // If the result is unused, emit it as a standalone statement. + if (op->use_empty()) { + std::string tmpName = "tmp" + std::to_string(++valueCount); + if (failed(emitType(op->getLoc(), op.getResult().getType()))) + return failure(); + os << " " << tmpName << " = " << expr << ";\n"; + } + return success(); + }) + .Default([&](Operation *) { return op.emitOpError("unable to find printer for op"); }); @@ -1814,9 +1871,9 @@ 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"); @@ -1834,6 +1891,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; @@ -1917,8 +1985,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..a314efd3547db 100644 --- a/mlir/test/Conversion/ConvertToEmitC/tosa.mlir +++ b/mlir/test/Conversion/ConvertToEmitC/tosa.mlir @@ -20,21 +20,24 @@ // RUN: mlir-opt --pass-pipeline=%{pipeline} %s | FileCheck %s // ----- -// 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: } +// CHECK: emitc.func private @main(%[[ARG0:.*]]: !emitc.ptr>, %[[ARG1:.*]]: !emitc.ptr>, %[[RES:.*]]: !emitc.ptr>) +// 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: [[VAR_3_:%.+]] = apply "*"(%[[ARG0]]) : (!emitc.ptr>) -> !emitc.array<2xf32> +// CHECK: [[VAR_4_:%.+]] = subscript [[VAR_3_]]{{.}}[[I_0_]]{{.}} : (!emitc.array<2xf32>, !emitc.size_t) -> !emitc.lvalue +// CHECK-DAG: [[LOAD_VAR_4_MEM_:%.+]] = load [[VAR_4_]] : +// CHECK-DAG: [[VAR_6_:%.+]] = apply "*"(%[[ARG1]]) : (!emitc.ptr>) -> !emitc.array<2xf32> +// CHECK: [[VAR_7_:%.+]] = subscript [[VAR_6_]]{{.}}[[I_0_]]{{.}} : (!emitc.array<2xf32>, !emitc.size_t) -> !emitc.lvalue +// CHECK: [[LOAD_VAR_7_MEM_:%.+]] = load [[VAR_7_]] : +// CHECK-DAG: [[VAR_9_:%.+]] = add [[LOAD_VAR_4_MEM_]], [[LOAD_VAR_7_MEM_]] : (f32, f32) -> f32 +// CHECK-DAG: [[VAR_10_:%.+]] = apply "*"(%[[RES]]) : (!emitc.ptr>) -> !emitc.array<2xf32> +// CHECK: [[VAR_11_:%.+]] = subscript [[VAR_10_]]{{.}}[[I_0_]]{{.}} : (!emitc.array<2xf32>, !emitc.size_t) -> !emitc.lvalue +// CHECK: assign [[VAR_9_]] : f32 to [[VAR_11_]] : +// CHECK: } +// CHECK: return +// CHECK: } 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 c1627a0d4d023..25987630fa248 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-copy.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-copy.mlir @@ -23,28 +23,18 @@ func.func @alloc_copy(%arg0: memref<999xi32>) { // 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: builtin.unrealized_conversion_cast %5 : !emitc.ptr to !emitc.array<999xi32> -// CHECK-NEXT: "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK-NEXT: emitc.subscript %0[%7] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK-NEXT: emitc.apply "&"(%8) : (!emitc.lvalue) -> !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 %12, %13 : (!emitc.size_t, index) -> !emitc.size_t -// CHECK-NEXT: emitc.call_opaque "memcpy"(%11, %9, %14) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () +// 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 %15, %16 : (!emitc.size_t, index) -> !emitc.size_t -// CHECK-NEXT: emitc.call_opaque "malloc"(%17) : (!emitc.size_t) -> !emitc.ptr> -// CHECK-NEXT: emitc.cast %18 : !emitc.ptr> to !emitc.ptr -// CHECK-NEXT: builtin.unrealized_conversion_cast %19 : !emitc.ptr to !emitc.array<999xi32> -// CHECK-NEXT: "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK-NEXT: emitc.subscript %0[%21] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK-NEXT: emitc.apply "&"(%22) : (!emitc.lvalue) -> !emitc.ptr -// CHECK-NEXT: emitc.subscript %20[%21] : (!emitc.array<999xi32>, index) -> !emitc.lvalue -// CHECK-NEXT: emitc.apply "&"(%24) : (!emitc.lvalue) -> !emitc.ptr +// 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 %26, %27 : (!emitc.size_t, index) -> !emitc.size_t -// CHECK-NEXT: emitc.call_opaque "memcpy"(%25, %23, %28) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () +// 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 d151d1bd53458..c74dac6a35497 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir @@ -12,17 +12,12 @@ func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) { // CHECK-LABEL: copying // CHECK-SAME: %[[arg0:.*]]: memref<9x4x5x7xf32>, %[[arg1:.*]]: memref<9x4x5x7xf32> -// CHECK-NEXT: %0 = builtin.unrealized_conversion_cast %arg1 : memref<9x4x5x7xf32> to !emitc.array<9x4x5x7xf32> -// CHECK-NEXT: %1 = builtin.unrealized_conversion_cast %arg0 : memref<9x4x5x7xf32> to !emitc.array<9x4x5x7xf32> -// CHECK-NEXT: %2 = "emitc.constant"() <{value = 0 : index}> : () -> index -// CHECK-NEXT: %3 = emitc.subscript %1[%2, %2, %2, %2] : (!emitc.array<9x4x5x7xf32>, index, index, index, index) -> !emitc.lvalue -// CHECK-NEXT: %4 = emitc.apply "&"(%3) : (!emitc.lvalue) -> !emitc.ptr -// CHECK-NEXT: %5 = emitc.subscript %0[%2, %2, %2, %2] : (!emitc.array<9x4x5x7xf32>, index, index, index, index) -> !emitc.lvalue -// CHECK-NEXT: %6 = emitc.apply "&"(%5) : (!emitc.lvalue) -> !emitc.ptr -// CHECK-NEXT: %7 = emitc.call_opaque "sizeof"() {args = [f32]} : () -> !emitc.size_t -// CHECK-NEXT: %8 = "emitc.constant"() <{value = 1260 : index}> : () -> index -// CHECK-NEXT: %9 = emitc.mul %7, %8 : (!emitc.size_t, index) -> !emitc.size_t -// CHECK-NEXT: emitc.call_opaque "memcpy"(%6, %4, %9) : (!emitc.ptr, !emitc.ptr, !emitc.size_t) -> () +// 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 2b4eda37903d4..b80f3a23c4a91 100644 --- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir @@ -4,6 +4,10 @@ // CHECK-LABEL: alloca() func.func @alloca() { // CHECK-NEXT: %[[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: [[APPLY:%.+]] = emitc.apply "&"([[SUBSCRIPT]]) : (!emitc.lvalue) -> !emitc.ptr + // CHECK-NEXT: [[CAST:%.+]] = emitc.cast [[APPLY]] : !emitc.ptr to !emitc.ptr> %0 = memref.alloca() : memref<2xf32> return } @@ -13,9 +17,10 @@ func.func @alloca() { // CHECK-LABEL: memref_store // CHECK-SAME: %[[buff:.*]]: memref<4x8xf32>, %[[v:.*]]: f32, %[[i:.*]]: index, %[[j:.*]]: 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: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.ptr> - // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue + // CHECK-NEXT: %[[APPLY:.+]] = emitc.apply "*"(%[[BUFFER]]) : (!emitc.ptr>) -> !emitc.array<4x8xf32> + // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[APPLY]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue // CHECK-NEXT: emitc.assign %[[v]] : f32 to %[[SUBSCRIPT]] : memref.store %v, %buff[%i, %j] : memref<4x8xf32> return @@ -26,9 +31,10 @@ 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: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.ptr> - // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue + // CHECK-NEXT: %[[APPLY:.+]] = emitc.apply "*"(%[[BUFFER]]) : (!emitc.ptr>) -> !emitc.array<4x8xf32> + // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[APPLY]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue // CHECK-NEXT: %[[LOAD:.*]] = emitc.load %[[SUBSCRIPT]] : %1 = memref.load %buff[%i, %j] : memref<4x8xf32> // CHECK-NEXT: return %[[LOAD]] : f32 @@ -51,9 +57,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.apply "&"(%3) : (!emitc.lvalue) -> !emitc.ptr + // 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.apply "&"(%1) : (!emitc.lvalue) -> !emitc.ptr + // CHECK-NEXT: emitc.apply "&"(%6) : (!emitc.lvalue) -> !emitc.ptr + // 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 294e6af65bf14..a2dcfd068122b 100644 --- a/mlir/test/Target/Cpp/common-cpp.mlir +++ b/mlir/test/Target/Cpp/common-cpp.mlir @@ -93,15 +93,13 @@ func.func @opaque_types(%arg0: !emitc.opaque<"bool">, %arg1: !emitc.opaque<"char func.func @apply() -> !emitc.ptr { // CHECK-NEXT: int32_t [[V1:[^ ]*]]; %0 = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue - // CHECK-NEXT: int32_t* [[V2:[^ ]*]] = &[[V1]]; + // CHECK: int32_t [[V2:[^ ]*]]; %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]]; %3 = emitc.apply "*"(%1) : (!emitc.ptr) -> i32 - // CHECK-NEXT: [[V3]] = [[V4]]; + // CHECK: [[V2]] = *(&[[V1]]); emitc.assign %3 : i32 to %2 : !emitc.lvalue - // CHECK-NEXT: return [[V2]]; + // CHECK-NEXT: return &[[V1]]; return %1 : !emitc.ptr } @@ -117,3 +115,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..6197754a9faae 100644 --- a/mlir/test/Target/Cpp/lvalue.mlir +++ b/mlir/test/Target/Cpp/lvalue.mlir @@ -16,8 +16,7 @@ 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-NEXT: zero([[VAR_PTR]]); +// CHECK: zero(&[[VAR]]); // CHECK-NEXT: int32_t [[VAR_LOAD:[^ ]*]] = [[VAR]]; // CHECK-NEXT: int32_t [[NEG_ONE:[^ ]*]] = -1; // CHECK-NEXT: [[VAR]] = [[NEG_ONE]];