Failed to materialize conversion for result #0 of operation ... that remained live after conversion

I’m stuck on a seemingly trivial problem that I can’t seem to crack even though imo it mirrors the toy tutorial more or less exactly. I have defined a dialect with two operations, constant and print. The former produces a tensor and the latter consumes it. I want to lower this dialect to arith + memref and I have stripped the implementation of my operations so far that the former produces a memref::AllocaOp and the latter does nothing. In IR:

%0 = my_dialect.constant dense<[[1, 2], [3, 4]]> : tensor<2x2xui8>
my_dialect.print %0 : tensor<2x2xui8>

And the lowerings are implemented as such:

struct ConstantOpLowering : OpRewritePattern<ConstantOp> {                       
  using OpRewritePattern<ConstantOp>::OpRewritePattern;                          
                                                                                 
  llvm::LogicalResult                                                                  
  matchAndRewrite(ConstantOp op,                                                 
                  PatternRewriter &rewriter) const override {                    
                                                                                 
    auto loc = op.getLoc();                                                      
                                                                                 
    auto matrixType = llvm::cast<MatrixType>(op.getType());                         
                                                                                    
    auto memRefType = MemRefType::get(matrixType.getShape(),                        
                                                                   matrixType.getElementType());                 
    auto memRefShape = memRefType.getShape();                                       
                                                                                    
    auto allocaOp = rewriter.create<memref::AllocaOp>(loc, memRefType);             
                                                                                 
    rewriter.replaceOp(op, allocaOp);                                            
                                                                                 
    return success();                                                            
  }                                                                              
};  
struct PrintOpLowering : OpConversionPattern<PrintOp> {                          
  using OpConversionPattern<PrintOp>::OpConversionPattern;                       
                                                                                 
  llvm::LogicalResult                                                                  
  matchAndRewrite(PrintOp op,                                                    
                  OpAdaptor adaptor,                                             
                  ConversionPatternRewriter &rewriter) const override {          
                                                                                 
      rewriter.modifyOpInPlace(                                                  
        op,                                                                      
        [&] { op->setOperands(adaptor.getOperands()); });                        
                                                                                 
    return success();                                                            
  }                                                                              
};  

I would expect this to just work, however I am getting this error when trying to lower:

<stdin>:3:10: error: failed to materialize conversion for result #0 of operation 'my_dialect.constant' that remained live after conversion                                                                     
    %0 = my_dialect.constant dense<[[1, 2], [3, 4]]> : tensor<2x2xui8>
         ^
<stdin>:3:10: note: see current operation: %1 = "my_dialect.constant"() <{value = dense<[[1, 2], [3, 4]]> : tensor<2x2xui8>}> : () -> tensor<2x2xui8>                                                          
<stdin>:4:5: note: see existing live user here: my_dialect.print %0 : tensor<2x2xui8>
    my_dialect.print %0 : tensor<2x2xui8>
    ^

What does that mean? I would expect to see this type of error if I had not added the operation adaptation in PrintOpLowering but that does not solve it.

To help debugging this, set ConversionConfig::buildMaterializations = false. Then take a look at the output. You should be seeing builtin.unrealized_conversion_cast ops in the output. These are the reason for the error. Try to change your implementation such that the unrealized_conversion_cast ops disappear. Then the error will disappear.

1 Like

Thank you, that helped me find the issue. I had marked my print operation as legal instead of dynamically legal if none of its operands are of tensor type as in the toy example, so there was an unrealized conversion from memref to tensor. Very useful feature.