Is changing the type and argument of FuncOp with PatternRewriter possible?

Hi,

Let’s say I have a MyOperation and I’m doing some pattern matching and rewriting on this operation.

After that, I need to change the type and argument of the FuncOp, which is the parent of MyOperation.

I don’t know how to do it with PatternRewriter. Does anyone have a good way to solve this ?

Thanks for reading.

This isn’t done with a pattern rewriter, but with the TypeConversion part of the DialectConversion framework: Dialect Conversion - MLIR

One example in the codebase: https://github.com/llvm/llvm-project/blob/main/mlir/lib/Conversion/LLVMCommon/TypeConverter.cpp#L196-L197

1 Like

Thanks ! I’ll look into it.

I still can’t figure out a way to do this.

Here’s my code and my question:

struct MyPattern : OpRewritePattern<MyOp> {
...
  void matchAndRewrite(MyOp op, PatternRewriter &rewriter) const override {
   // matching 
   if (notMatchMyOperation(op))
     return failure();

   // rewriting
   rewriteMyOperation(op);

   // after rewriting, we need to change type of the function
   // for example, we may change it from this:
   //     (i32, i32) -> i32
   // to this...
   //     (i32, i32, i32) -> i32

   // *** My old wrong way ***
   FuncOp funcOp = op.getParentOfType<FuncOp>();
   changeFuncType(funcOp);

   // How can I incorporate `TypeConversion` here ?
  }
}

Thanks for reading :slight_smile:

This isn’t done in the pattern implementation, but added to the RewritePatternSet: https://github.com/llvm/llvm-project/blob/main/mlir/test/lib/Dialect/Test/TestPatterns.cpp#L1162

1 Like

So now I have two things to do:

  • rewrite MyOp
  • change the type of the function (which is the parent of MyOp)

Should I do these with OpRewritePattern and OpConversionPattern separately, or do them both in OpConversionPattern ?

(Or maybe I’m asking the wrong question ?)

Thanks for reading :slight_smile:

It seems that my problem can be solved with only OpConversionPattern. I will update my solution for people who have the same problem

Thanks @mehdi_amini :slight_smile:

I’m getting more confusing. So I want to describe my problem spare no detail.

I have a SourceOp that have two results, and both them are used by a TargetOp :

func @MyFunc() {
    (%0, %1) = SourceOp : () -> (typeA, typeB)
    TargetOp(%0, %1) : (typeA, typB) -> ()
    ...
}

Now I want to change it to something like this:

func @MyFunc(%0: type A, %1: typeB) {
    TargetOp(%0, %1) : (typeA, typeB) -> ()
    ...
}

How can I acheive this with type conversion framework ?

Thanks for reading :slight_smile:

Note you can also set the function type directly:

funcOp.setType(FunctionType::get(...));

Hi, I can give you one way that might be simpler to follow.

The details of your problem are:

  1. You want to change your function
  2. You want replace (%0, %1)

Important details to note are:

  1. Replacing your function with something similar is the same as changing it
  2. You can modify anything inside of your function with the same pattern

So you can take the steps of:

  1. Take a pattern that operates on FuncOp
  2. Create a new FuncOp with the new signature and the same symbol name
  3. Transfer the region from the old func to the new func
  4. Replace %0,%1 inside of the new func with the relevant arguments
  5. Erase the original FuncOp

This might be easier to conceptualize as it is more similar to other patterns not operating on funcs.

Thanks for all of you guys. Problem solved.

Really appreciate :slight_smile: