Lookup within dialect conversion

Hi

I have two dialects and I’m converting from one to the other.

Dialect A:

%a = foo.bar{id = 0 : i32} : !foo.bar
foo.baz(%a) : (!foo.bar) -> ()

Dialect A converted to Dialect B:

%b = goo.bar{id = 0 : i32} : !goo.bar
goo.baz(%b) : (!goo.bar) -> ()

As you can see, I’m converting from foo.bar to goo.bar in the first line.

But when I’m doing the conversion for foo.baz, i have to first lookup foo.bar and then find what it was converted to so that i can pass that relative op(i.e. goo.bar) to goo.baz.

At the moment I’m walking the list and comparing getLoc() for the nodes of the same type. This looks to be working and i wanted to ask if this is the best practice and if not if there is a better way.

Can you convert both in the same pattern?

Unfortunately not. The above example is very simple compared to my own work. there are also intermediary steps involved.

What do you mean by " can pass that relative op(i.e. goo.bar ) to goo.baz" ?

If you want to have the value defined by foo.bar to be used as operand for goo.baz, this is exactly what dialect conversion was designed to do. Inside ConversionPattern::matchAndRewrite(Operation *original, ArrayRef<Value> operands, ConversionPatternRewriter &rewriter), the second argument (operands) contains the values that should be used for operands of the current operation instead of original operands. In this case, it would contain %b (as opposed to original->getOperand(0) that will still contain %a, which can be useful to inspect the original type, for example). Note that the newly created operations must not use operands of the original operation since it may be deleted at the end of the process, and must use values from operands instead.

Thanks a lot. this is exactly what i was looking for :slight_smile:

Is there an internal function that would lookup a type within an ArrayRef:

Does something like exist?

const auto op = [&]() -> Optional<Value> {
      for (const auto val : operands) {
        if (val.getType().isa<MyType>()) {
          return val;
        }
      }
      return llvm::None;
    }();

No.

However, for ODS-generated ops, we have a special class <OpName>OpAdaptor that can be constructed from ArrayRef<Value> and an attribute dictionary. This class has accessors to operands and attributes with exactly the same names as the main <OpName> class. I suppose you are trying to get a converted value that corresponds to a certain operand, and dispatching by type is not the right way to do it. <OpName>OpAdaptor adaptor(operands); adaptor.operand() is the idiomatic way.

Thanks. I’m actually passing the operand’s result. and this doesn’t seem to provide it, right?

no known conversion from 'mlir::MyType' to '::mlir::Value' 

In the above code, I’m doing this after getting the correct operand:

 rewriter.create<FooOp>(loc, op,...);

I don’t know what mlir::MyType is, in particular which classes does it derive. So I can just read the error message: mlir::MyType cannot be converted to mlir::Value by any means known to C++. There is seemingly no relation with the second line.

Sorry for the confusion…

Here is the issue in more detail:

I have the following type definition:

class Foo : public Type::TypeBase<Foo, Type, TypeStorage> {
public:
  using Base::Base;

  static Foo get(MLIRContext *context);
};

and then i define it in ODS:

def Foo : Type<CPred<"$_self.isa<Foo>()">, "Foo">;

and use it in my Operation:

def Foo_CreateOp : My_Op<"foo", [NoSideEffect]> {
    let arguments = (IndexAttr:$id);
    let results = (outs Foo:$out);
}

now when I am converting within matchAndRewrite, i would like to retrieve Foo.

This works:

const auto op = [&]() -> Optional<Value> {
      for (const auto val : operands) {
        if (val.getType().isa<Foo>()) {
          return val;
        }
      }
      return llvm::None;
    }();

However this doesn’t even exist: - as expected

FooOpAdaptor adaptor(operands)

And this only gives me the operands and not the result from its creation:

Foo_CreateOpAdaptor adaptor(operands)

It cannot possibly give you the result because the operation may not exist yet.

If you do create an op, you can just call op.out().getType() to get the type.

I don’t understand why you are trying to get Foo from operands when the definition of Foo_CreateOp has no operands ( IndexAttr is an attribute, not an operand). The loop code you post should not work, unless the definition you are working with is different from what you are showing.