This is an archive of the discontinued LLVM Phabricator instance.

[mlir][complex] Custom attribute comlex.number.
ClosedPublic

Authored by Lewuathe on Jul 19 2022, 11:58 PM.

Details

Summary

Add custom attribute for complex dialect. Although this commit does not have significant impact on the conversion framework, it will lead us to construct complex numbers in a readable and tidy manner.

Related discussion: https://reviews.llvm.org/D127476

Diff Detail

Event Timeline

Lewuathe created this revision.Jul 19 2022, 11:58 PM
Lewuathe requested review of this revision.Jul 19 2022, 11:58 PM
Lewuathe edited the summary of this revision. (Show Details)Jul 19 2022, 11:59 PM
pifon2a added inline comments.Jul 20 2022, 4:23 AM
mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.td
38

shouldn't it be

AttributeSelfTypeParameter<"">:$type,
APFloatParameter<"">:$lhs,
APFloatParameter<"">:$rhs

and then we probably need some verification similar to BuiltinAttributes.cpp:293 that checks that both the types of $lhs, $rhs and $type match?

40

In that case the assemblyFormat should also have $type.

let assemblyFormat = "`<` $real `,` $imag `>` `:` $type
Lewuathe added inline comments.Jul 20 2022, 7:45 PM
mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.td
38

Looks like simply using APFloatParameter does not work. Do we need to provide the custom field parser for APFloatParameter?

/Users/sasakikai/dev/llvm-project/build/tools/mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.cpp.inc:84:26: error: implicit instantiation of undefined template 'mlir::FieldParser<llvm::APFloat>'
  _result_real = ::mlir::FieldParser<::llvm::APFloat>::parse(odsParser);
                         ^
/Users/sasakikai/dev/llvm-project/mlir/include/mlir/IR/DialectImplementation.h:58:8: note: template is declared here
struct FieldParser;
       ^
In file included from /Users/sasakikai/dev/llvm-project/mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp:45:
/Users/sasakikai/dev/llvm-project/build/tools/mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.cpp.inc:93:26: error: implicit instantiation of undefined template 'mlir::FieldParser<llvm::APFloat>'
  _result_imag = ::mlir::FieldParser<::llvm::APFloat>::parse(odsParser);
                         ^
/Users/sasakikai/dev/llvm-project/mlir/include/mlir/IR/DialectImplementation.h:58:8: note: template is declared here
struct FieldParser;
       ^
2 errors generated.
40

Using type in the assembly format may not be allowed?

error: unexpected self type parameter in assembly format
`<` $real `,` $imag `>` `:` $type
Lewuathe updated this revision to Diff 446361.Jul 20 2022, 11:33 PM

Add verifier checking the given types.

pifon2a added inline comments.Jul 20 2022, 11:45 PM
mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.td
38

Yes, in that case we need to have a custom print/parser. Take a look at CombiningKindAttr in VectorOps.h. There is

void print(AsmPrinter &p) const;
static Attribute parse(AsmParser &parser, Type type);

defined for it.

If FloatAttr is used, then we store the type twice for no good reason.

@pifon2a Thank you so much. Let me have a look.

Lewuathe updated this revision to Diff 447191.Jul 24 2022, 10:54 PM

Update to use APFloatParameter for real and imaginary parts.

pifon2a accepted this revision.Jul 25 2022, 3:14 AM
pifon2a added inline comments.
mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp
54

Float semantics of imag and real should be verified, I think:

  // Verify that the type semantics match that of the `real` and `imag` values.
auto typeFloatSemantics = type.cast<FloatType>().getFloatSemantics() ;
if (&typeFloatSemantics != &real.getSemantics()) 
  return emitError()  << "type doesn't match the type implied by its `real` value";
if (&typeFloatSemantics != &imag.getSemantics()) 
  return emitError()  << "type doesn't match the type implied by its `imag` value";
64

interesting. The type is not printed here, but it is present in the test output.

This revision is now accepted and ready to land.Jul 25 2022, 3:14 AM

Thank you @Lewuathe ! This looks good.

I think it may also help to look at DenseArrayAttr as an example. It uses this syntax:
[:f64 0, 2]

So based on this, we could use the custom format
#complex.number<:f64 0, 2>

which would have the nice effect that we know what element type to parse before we parse the elements.
Also, I think it would be preferable if the type of the attribute is of ComplexType, so for example if element type is F64, then ComplexType::get(FloatType::getF64(context))

Good point, Adrian.

I think it may also help to look at DenseArrayAttr as an example. It uses this syntax:
[:f64 0, 2]

So based on this, we could use the custom format
#complex.number<:f64 0, 2>

which would have the nice effect that we know what element type to parse before we parse the elements.
Also, I think it would be preferable if the type of the attribute is of ComplexType, so for example if element type is F64, then ComplexType::get(FloatType::getF64(context))

Lewuathe updated this revision to Diff 447577.Jul 25 2022, 11:31 PM

Refine format to be #complex.number<f64 1.0, 2.0>

Thank you both. I updated the change accordingly. But the following case gets invalid with the semantic validation. f32 is not compatible with the given floating point numbers?

func.func @number_attr_f32() {
  "test.number_attr"() {
    // expected-error @+1 {{unexpected error: type doesn't match the type implied by its `real` value}}
    attr = #complex.number<:f32 1.0, 0.0>
  } : () -> ()

  return
}
akuegel added inline comments.Jul 26 2022, 12:20 AM
mlir/include/mlir/Dialect/Complex/IR/ComplexAttributes.td
37

I wonder whether it would make sense to use FloatAttr here?

Something like:

let parameters = (ins AttributeSelfTypeParameter<"">:$type, "mlir::FloatAttr":$real, "mlir::FloatAttr":$imag);

And then you could have a convenience builder that also allows to build from APFloat:

let builders = [
  AttrBuilderWithInferredContext<
      (ins "ComplexType":$type,
           "APFloat":$real, "APFloat":$imag), [{
    auto elementType = type.getElementType();
    auto realFloat = FloatAttr::get(elementType, real);
    auto imagFloat = FloatAttr::get(elementType, imag);
    return $_get(type.getContext(), type, realFloat, imagFloat);
  }]>
];
mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp
100

I believe you would have to convert the APFloats to the required float semantics. The method signature for this is:

convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo);

APFloat realFloat(real);
bool unused;
realFloat.convert(type.cast<FloatType>().getFloatSemantics(), APFloat::rmNearestTiesToEven, &unused);

But I think this would be taken care of automatically if you use FloatAttr as storage (see other comment).

I wonder whether it would make sense to use FloatAttr here?

@akuegel FloatAttr has two fields

AttributeSelfTypeParameter<"">:$type,
APFloatParameter<"">:$value

I am not sure we want $type to be stored three times.

@akuegel FloatAttr has two fields

AttributeSelfTypeParameter<"">:$type,
APFloatParameter<"">:$value

I am not sure we want $type to be stored three times.

Ok, good point. So I guess then the convert calls need to be done in the complex::NumberAttr::parse like I suggested, so that the correct APFloat is passed.

Lewuathe updated this revision to Diff 447933.Jul 26 2022, 9:54 PM

Support f32 by converting the APFloat.

@pifon2a @akuegel Thank you for the feedback! I updated the patch accordingly, and it's now supporting f32 type too.

akuegel accepted this revision.Jul 27 2022, 2:12 AM

Thank you :)

This revision was automatically updated to reflect the committed changes.
Mogball added a subscriber: Mogball.EditedJul 31 2022, 3:48 PM

Hey, I just saw this. There are quite a few instances of storing complex numbers as an array attribute of two elements [0.0 : f32, 0.0 : f32]. Now that there is a better way of doing that, do you plan on refactoring some of the dialects to use this?

If not, can you file an issue to track that? Thanks!

Hey, I just saw this. There are quite a few instances of storing complex numbers as an array attribute of two elements [0.0 : f32, 0.0 : f32]. Now that there is a better way of doing that, do you plan on refactoring some of the dialects to use this?

If not, can you file an issue to track that? Thanks!

Yes, the plan is to replace ArrayAttr with this new attribute. Lewuathe is already working on it:

https://discourse.llvm.org/t/multiple-type-support-for-input-attribute/64116