Trouble Creating a Simple Constant Tensor

Hello, I’m having trouble simply generating two constant tensors and adding them, before lowering to llvm. Using build from commit 02cc8d698c4941f8f0120. Consider the following snippet:

    auto ten_ty = // ... get 4xf32 tensor
    auto mem_ty = // ... get 4xf32 memref

    mlir::DenseElementsAttr attrValue = mlir::DenseElementsAttr::get(ten_ty, llvm::ArrayRef<float>((float*)e.v.constVals, e.v.shape.ntotal()));

#if 0
    // Branch 1
    {
      mlir::OpBuilder::InsertionGuard g(coder.builder);
      coder.builder.setInsertionPointToStart(coder.mod.getBody());
      coder.builder.create<mlir::memref::GlobalOp>(
          coder.builder.getUnknownLoc(),
          mlir::StringAttr::get(&coder.ctx, name),
          nullptr,
          mlir::TypeAttr::get(mem_ty),
          attrValue,
          mlir::UnitAttr::get(&coder.ctx),
          nullptr);
    }
    auto as_memref = coder.builder.create<mlir::memref::GetGlobalOp>(coder.builder.getUnknownLoc(), mem_ty,
        mlir::FlatSymbolRefAttr::get(&coder.ctx, name));
    auto as_tensor = coder.builder.create<mlir::bufferization::ToTensorOp>(coder.builder.getUnknownLoc(), as_memref);
#else
    // Branch 2
    auto as_tensor = coder.builder.create<mlir::ConstantOp>(coder.builder.getUnknownLoc(), ten_ty, attrValue);
#endif
    return as_tensor;

The code under branch 2 results in the following error:

‘std.constant’ op unsupported ‘value’ attribute: dense<[0.000000e+00, 1.000000e+00, 0.000000e+00, 2.000000e+00]> : tensor<4xf32>

And the seemingly correct IR:

%cst = constant dense<[0.000000e+00, 1.000000e+00, 0.000000e+00, 2.000000e+00]> : tensor<4xf32>

There are other posts on this forum that suggest exactly the above IR (although a vector instead of a tensor), so I don’t know why I’m getting this error.
The first branch gets further and throws no error. However, while lowering to MLIR-LLVM, it results in having two lines:

%17 = builtin.unrealized_conversion_cast %16 : !llvm.struct<(ptr<f32>, ptr<f32>, i64, array<1 x i64>, array<1 x i64>)> to memref<4xf32>
%18 = bufferization.to_tensor %17 : memref<4xf32>

Which result in an error:

cannot be converted to LLVM IR: missing LLVMTranslationDialectInterface registration for dialect for op: builtin.unrealized_conversion_cast

This builtin.unrealized_conversion_cast comes out of nowhere and I’m not sure what it’s doing or how to fix the LLVM lowering.

There’s also a few follow up issues I have after solving these.
Thanks!

Ended up resolving the issues.
As for the std.constant, it does not appear to support tensors. However arith.constant does, which is sort of confusing and doesn’t appear to be documented.

The bigger problem was that I was not adding all proper passes before and after llvm lowering. The get_global vs arith.constant definitions both work after adding all proper passes, which for anyone facing a similar problem were:

  mlir::PassManager pm1(&ctx);
  pm1.addPass(mlir::createInlinerPass());
  pm1.addPass(mlir::tosa::createTosaToStandard());
  pm1.addNestedPass<mlir::FuncOp>(mlir::tosa::createTosaToLinalg());
  pm1.addPass(mlir::tosa::createTosaToSCF());
  pm1.addPass(mlir::createTensorConstantBufferizePass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createCanonicalizerPass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::arith::createConvertArithmeticToLLVMPass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::arith::createConvertArithmeticToLLVMPass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createSCFBufferizePass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createLinalgBufferizePass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createStdBufferizePass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createTensorBufferizePass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createCSEPass());
  pm1.addPass(mlir::createFuncBufferizePass());
  //pm1.addPass(mlir::createBufferizationToMemRefPass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::bufferization::createFinalizingBufferizePass());
  pm1.addPass(mlir::createLowerAffinePass());
  pm1.addPass(mlir::createConvertLinalgToStandardPass());
  pm1.addPass(mlir::createConvertLinalgToLLVMPass());
  pm1.addNestedPass<mlir::FuncOp>(mlir::createConvertMathToLLVMPass());
  pm1.addPass(mlir::createMemRefToLLVMPass());
  pm1.addPass(mlir::createLowerToLLVMPass());
  pm1.addPass(mlir::createReconcileUnrealizedCastsPass());

It does appear that the changes to std.constant as part of factoring out the standard dialect have not been reflected in updates to the documentation: https://mlir.llvm.org/docs/Dialects/Standard/#:~:text=tensor/vector%20constants. The constant op is one of the oldest and still has custom C++ verification for things that should really have declarative type constraints (which would then be reflected in the generated documentation).