Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Comb][Canonicalize] keep attributes during op width narrowing #5532

Merged
merged 1 commit into from
Jul 6, 2023

Conversation

7FM
Copy link
Contributor

@7FM 7FM commented Jul 3, 2023

Fixes #5531.
TLDR: narrowOperationWidth() copies attributes to a comb.concat operation, which is optimized away in a later step.
The fix is simple: do not copy the attributes to the intermediate comb.concat op but instead to the width narrowed operation.

@7FM 7FM changed the title [Comb] Canonicalization: keep attributes during op width narrowing [Comb][Canonicalize] keep attributes during op width narrowing Jul 3, 2023
// https://github.com/llvm/circt/issues/5531
// CHECK-LABEL: @Issue5531
hw.module @Issue5531(%arg0: i64, %arg1: i64) -> (out: i32) {
// CHECK: %2 = comb.mul %0, %1 {sv.namehint = "hint"} : i32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One tricky issue here is that strictly speaking %2 after canonicalization is not equal to %3. Actually it makes sense to me to propagate names even when they are not accurate, but we should also consider deriving names from original namehints, such as hint_0_to_32 for this example.

Copy link
Contributor Author

@7FM 7FM Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One tricky issue here is that strictly speaking %2 after canonicalization is not equal to %3.

When considering the possibility of overflows, then technically the same could be said about the previous behavior with %newop = comb.concat %c0_i32, %mul_32_res {sv.namehint = "hint"} : i32, i32 :D
Also, it is a different operation type altogether that gets the name hint (before being optimized away).
But I agree that it is not perfectly accurate.

The reason that I am bringing this up, is that we (@jopperm) use custom annotations for some comb operations in our out-of-tree workflow, and it would be great if they would still exist after -canonicalize :)

Copy link
Member

@uenoku uenoku Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, preserving optional attributes is hard problem and MLIR doesn't provide a good solution for it (Links for previous discussion on forums: https://discourse.llvm.org/t/canonicalization-passes-dont-keep-attributes/59750/2). Currently we treat sv.namhint specially and are manually propagating hints, and other optional attributes are not propagated at all. I think it would be unsafe to propagate optional attributes freely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, preserving optional attributes is hard problem and MLIR doesn't provide a good solution for it

Too bad, anyway, thanks for the link.

other optional attributes are not propagated at all.

Is this a comb specific decision? At least in other dialects, I have seen multiple occasions with newOp->setDialectAttrs(op->getDialectAttrs()); in their lowering passes.

I think it would be unsafe to propagate optional attributes freely.

Agreed, this is very much dependent on the intended semantics of the attributes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@uenoku In general, dialect attributes should be propagated best effort, so I think it's appropriate to propagated them through the canonicalizers where it's obvious what the destination/source op is. If that's unsafe in some way, it's the dialect's responsibility to detect that situation, IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a comb specific decision? At least in other dialects, I have seen multiple occasions with newOp->setDialectAttrs(op->getDialectAttrs()); in their lowering passes.

Yeah, good point. I kind of feel it's generally safe to use newOp->setDialectAttrs(op->getDialectAttrs()) in lowering passes, since in that case there is some direct mapping from source to target operations (e.g. seq.reg -> sv.reg, hwarith.add -> comb.add). But I feel it's too aggressive to propagate all unknown attributes in canonicalizers since I guess attributes could be moved to random operations.

In general, dialect attributes should be propagated best effort, so I think it's appropriate to propagated them through the canonicalizers where it's obvious what the destination/source op is. If that's unsafe in some way, it's the dialect's responsibility to detect that situation, IMO.

I agree that it's ok to propagate attributes when the dest/src are clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, all attributes is definitely not safe. That's what dialect attributes are for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's ok to propagate attributes when the dest/src are clear.

So it should be fine here? Both op and newOp are of the template type OpTy.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, probably. It's still a bit concerning that types are different though. Any thought? @darthscsi

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When considering the possibility of overflows, then technically the same could be said about the previous behavior with %newop = comb.concat %c0_i32, %mul_32_res {sv.namehint = "hint"} : i32, i32 :D

Yea, it's moving the result of the later extract (in this case) into the visibility of mul's value. On the firrtl side, we would not have propagated a name in this case. (Actually, we would have rooted the pattern at the extract and preserved its name)

I don't know if there is a general rule we can depend on, but it does seem like width-narrowing is a case where propagating the dialect attributes makes sense.

@uenoku uenoku requested a review from darthscsi July 5, 2023 09:42
Copy link
Contributor

@darthscsi darthscsi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Width narrowing seems a clear instance where best-effort means moving the dialect attributes. As pointed out, the existing pattern already was changing the visible value for a particular name, so this is not obviously worse.

@7FM 7FM added the Comb Involving the `comb` dialect label Jul 6, 2023
@7FM 7FM merged commit 2c49116 into main Jul 6, 2023
5 checks passed
@7FM 7FM deleted the dev/7FM/comb_keep_attrs branch July 6, 2023 08:45
calebmkim pushed a commit to andrewb1999/circt that referenced this pull request Jul 12, 2023
…5532)

Fixes llvm#5531.
TLDR: `narrowOperationWidth()` copies attributes to a `comb.concat` operation, which is optimized away in a later step.
The fix is simple: do not copy the attributes to the intermediate `comb.concat` op but instead to the width narrowed operation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Comb Involving the `comb` dialect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Comb] canonicalize with narrowOperationWidth looses attributes
4 participants