This is an archive of the discontinued LLVM Phabricator instance.

[mlir] GreedyPatternRewriteDriver: Do not CSE or hoist constants
Changes PlannedPublic

Authored by springerm on Jan 30 2023, 9:19 AM.

Details

Summary

Instead, constants are CSE'd and hoisted in the canonicalizer pass, unless cse-constants = false. (Alternatively, the CSE pass also CSE's constants.)

The purpose of this change is to simplify the greedy pattern rewriter and to make it less surprising.

Note: This change may cause constants to be reordered. But we also do not care about other ops being reordered.

Diff Detail

Event Timeline

springerm created this revision.Jan 30 2023, 9:19 AM
Herald added a reviewer: aartbik. · View Herald Transcript
Herald added a project: Restricted Project. · View Herald Transcript
springerm requested review of this revision.Jan 30 2023, 9:19 AM

Note: There is a crash in a Shape dialect test case that I have not fixed yet.

springerm edited the summary of this revision. (Show Details)Jan 30 2023, 9:24 AM

The motivation for this change isn't obvious to me from the description, can you elaborate a bit more?

The motivation for this change isn't obvious to me from the description, can you elaborate a bit more?

This is originally coming from a use case in IREE: We have a dispatch.region op that models a fusion group. The op is not isolated from above. (It will be converted to an "isolated-from-above" variant later in the lowering process.) Ops are moved into the region of the fusion group one-by-one according to some heuristic. (That's just easier to do when the op is not isolated from above yet.) We occasionally want to run a fix point iteration of a few small rewrite patterns to resolve some dynamic shapes; none of these patterns do anything with constants. We can't use the greedy pattern rewriter for that because it hoists constants from the fusion group.

That's just one small use case in a downstream project though. The more important question for me was: Should the GreedyPatternRewriteDriver CSE and hoist constant ops, when its name suggests that it merely applies rewrite patterns and foldings? Especially since we have a dedicated CSE pass for things like that.

Based on the code comments, the reason for this functionality was to prevent constants from being reordered (and not to specifically CSE/hoist constants). I think it's not really a problem in practice -- the number of affected tests is pretty small and users are encouraged to use CHECK-DAG in their tests anyway.

The motivation for this change isn't obvious to me from the description, can you elaborate a bit more?

This is originally coming from a use case in IREE: We have a dispatch.region op that models a fusion group. The op is not isolated from above. (It will be converted to an "isolated-from-above" variant later in the lowering process.) Ops are moved into the region of the fusion group one-by-one according to some heuristic. (That's just easier to do when the op is not isolated from above yet.) We occasionally want to run a fix point iteration of a few small rewrite patterns to resolve some dynamic shapes; none of these patterns do anything with constants. We can't use the greedy pattern rewriter for that because it hoists constants from the fusion group.

I've seen this in the past, but I generally apply a "sink constant" pass afterward to rematerialize constant in dispatched regions.
That said, shouldn't the "scope" mechanism of the driver be enough to support this? That is: we shouldn't hoist constant outside of the provided scope maybe?

That's just one small use case in a downstream project though. The more important question for me was: Should the GreedyPatternRewriteDriver CSE and hoist constant ops, when its name suggests that it merely applies rewrite patterns and foldings? Especially since we have a dedicated CSE pass for things like that.

It depends: it this is "free" and helps with canonicalization, I can see this being something we want to be intertwined in the driver, otherwise we may hit some "pass ordering" issue.

Based on the code comments, the reason for this functionality was to prevent constants from being reordered (and not to specifically CSE/hoist constants). I think it's not really a problem in practice -- the number of affected tests is pretty small and users are encouraged to use CHECK-DAG in their tests anyway.

The order of constant in the absolute may not be a problem, but we really would want canonicalized to stay idempotent.

For anyone tagging along on this review, seems like it comes from: https://reviews.llvm.org/D122692 and https://github.com/llvm/llvm-project/issues/51892

Based on the code comments, the reason for this functionality was to prevent constants from being reordered (and not to specifically CSE/hoist constants). I think it's not really a problem in practice -- the number of affected tests is pretty small and users are encouraged to use CHECK-DAG in their tests anyway.

The order of constant in the absolute may not be a problem, but we really would want canonicalized to stay idempotent.

For anyone tagging along on this review, seems like it comes from: https://reviews.llvm.org/D122692 and https://github.com/llvm/llvm-project/issues/51892

This background is worth adding to the description by the way.

springerm planned changes to this revision.Feb 1 2023, 2:56 AM

Looking at https://reviews.llvm.org/D122692, there seem to be legitimate reasons for preserving the op order. I'll see if I can preserve this part without CSE'ing/hoisting constants.

That said, shouldn't the "scope" mechanism of the driver be enough to support this?

In this particular use case, the region ops themselves are part of the rewrite, so the scope is actually the entire function.

That is: we shouldn't hoist constant outside of the provided scope maybe?

That should already be the case. The OperationFolder never sees any ops/constants that are out of scope, so it shouldn't CSE with those.

I've seen this in the past, but I generally apply a "sink constant" pass afterward to rematerialize constant in dispatched regions.

That should work.