Skip to content

[SelectionDAG] Introducing the SelectionDAG pattern matching framework #78654

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

Merged
merged 9 commits into from
Feb 23, 2024

Conversation

mshockwave
Copy link
Member

Akin to llvm::PatternMatch and llvm::MIPatternMatch, the llvm::SDPatternMatch introduced in this patch provides a DSL-alike framework to match SDValue / SDNode with a more succinct syntax.

@mshockwave
Copy link
Member Author

Note: I only added the most basic and hopefully the most common patterns in this patch. Feel free to propose other patterns that you thought are important.

explicit NUses_match(const Pattern &P) : P(P) {}

bool match(const SelectionDAG *DAG, SDValue N) {
return N && N->hasNUsesOfValue(NumUses, N.getResNo()) && P.match(DAG, N);
Copy link
Collaborator

Choose a reason for hiding this comment

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

hasNUsesOfValue can be expensive on nodes with multiple results. It can't return true until it has checked all uses. Uses for all results are stored in the same list.

We try to always check opcode first before checking number of uses. It's better to ask if an opcode is an ISD::ADD first since it only has 1 result. Than to ask for the number of uses without knowing what type of node it is.

Copy link
Member Author

Choose a reason for hiding this comment

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

We try to always check opcode first before checking number of uses. It's better to ask if an opcode is an ISD::ADD first since it only has 1 result. Than to ask for the number of uses without knowing what type of node it is.

I think a simple solution could be swapping hasNUsesOfValue with the succeeding P.match call, as we have to fulfills these two conditions anyway:

P.match(DAG, N) && N->hasNUsesOfValue(NumUses, N.getResNo())

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@RKSimon RKSimon changed the title [SelecitonDAG] Introducing the SelectionDAG pattern matching framework [SelectionDAG] Introducing the SelectionDAG pattern matching framework Jan 19, 2024
@RKSimon RKSimon requested a review from efriedma-quic January 19, 2024 11:31
As SDNode::hasNUsesOfValue is pretty expensive
@RKSimon
Copy link
Collaborator

RKSimon commented Jan 31, 2024

Random question - will this play nice with the template approach taken for VP node (e.g. #80105)?

@RKSimon
Copy link
Collaborator

RKSimon commented Feb 11, 2024

@mshockwave reverse-ping

@mshockwave
Copy link
Member Author

Random question - will this play nice with the template approach taken for VP node (e.g. #80105)?

My apologies for the delay.
I think supporting VPMatchContext::match in SDPatternMatch makes a lot of sense and I'll add that. Though I'm not sure if we should bring VPMatchContext::getNode into SDPatternMatch as well.

@mshockwave
Copy link
Member Author

mshockwave commented Feb 12, 2024

I'd just introduced the concept of match context to SDPatternMatch: now a user can pattern match a SDValue under certain match context using sd_context_match. A match context is really similar to that in DAGCombiner (e.g. VPMatchContext) except it only needs to implement getDAG() and getTLI(); The match(SDValue, unsigned) is optional.
Furthermore, you can use custom contexts only in a sub-pattern via m_Context(<custom context>, <sub pattern>).

Switching to this match context design also solves one of the problem where previously, the user had to provide a SelectionDAG in order to use any TLI hook, which was inconvenient in places lack of SelectionDAG. Now we can independently provide TLI instances to sd_context_match.

Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

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

Please can you add m_Deferred handling?

// Optional trait function(s)

/// Return true if N effectively has opcode Opcode.
// bool match(SDValue N, unsigned Opcode)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why make this optional instead of having a default implementation of N->getOpcode() == Opcode?

Copy link
Member Author

Choose a reason for hiding this comment

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

Users won't necessary inherit BasicContext here to create a new match context. The default implementation for match is implemented in places like Opcode_match::match, toggled by ctx_has_match.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we expect there to be more contexts than BaseContext and VPMatchContext? I don't think that custom context will be common enough that we have to optimize for implementing one method less.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do we expect there to be more contexts than BaseContext and VPMatchContext? I don't think that custom context will be common enough that we have to optimize for implementing one method less.

I'm convinced, I'll change this in the next update.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's fixed now.

@RKSimon RKSimon requested a review from jacquesguan February 14, 2024 16:24
@mshockwave
Copy link
Member Author

mshockwave commented Feb 15, 2024

Please can you add m_Deferred handling?

Of course. I'll add it in the next update.
@RKSimon It's done now.

The major one was simplifying Node_match into Operands_match.
explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}

template <typename MatchContext>
std::enable_if_t<is_detected<ctx_has_match, MatchContext>::value, bool>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think these enable_ifs are not needed anymore now that we have the match() implementation in BasicMatchContext?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh yeah I forgot. It's fixed now.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM, but please wait a bit in case other people have more feedback.

@mshockwave mshockwave merged commit 5874874 into llvm:main Feb 23, 2024
@mshockwave mshockwave deleted the patch/selectiondag-patternmatch branch February 23, 2024 19:03
XChy added a commit that referenced this pull request Mar 12, 2024
…ternMatch (#84759)

Resolves #84745.

Based on SDPatternMatch introduced by #78654, this patch replaces some
of basic patterns in `visitADDLike` with corresponding patterns in
SDPatternMatch.

This patch only replaces original folds, instead of introducing new ones.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants