[llvm] [SelectionDAG] Introducing the SelectionDAG pattern matching framework (PR #78654)

Min-Yih Hsu via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 19 11:12:46 PST 2024


================
@@ -0,0 +1,612 @@
+//==--------------- llvm/CodeGen/SDPatternMatch.h ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Contains matchers for matching SelectionDAG nodes and values.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_SDPATTERNMATCH_H
+#define LLVM_CODEGEN_SDPATTERNMATCH_H
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGen/TargetLowering.h"
+
+namespace llvm {
+namespace SDPatternMatch {
+
+template <typename Pattern>
+[[nodiscard]] bool sd_match(SDNode *N, const SelectionDAG *DAG, Pattern &&P) {
+  return P.match(DAG, SDValue(N, 0));
+}
+
+template <typename Pattern>
+[[nodiscard]] bool sd_match(SDValue N, const SelectionDAG *DAG, Pattern &&P) {
+  return P.match(DAG, N);
+}
+
+template <typename Pattern>
+[[nodiscard]] bool sd_match(SDNode *N, Pattern &&P) {
+  return P.match(nullptr, SDValue(N, 0));
+}
+
+template <typename Pattern>
+[[nodiscard]] bool sd_match(SDValue N, Pattern &&P) {
+  return P.match(nullptr, N);
+}
+
+// === Utilities ===
+struct Value_match {
+  SDValue MatchVal;
+
+  Value_match() = default;
+
+  explicit Value_match(SDValue Match) : MatchVal(Match) {}
+
+  bool match(const SelectionDAG *, SDValue N) {
+    return (MatchVal && (MatchVal == N)) || N.getNode();
+  }
+};
+
+/// Match any valid SDValue.
+inline Value_match m_Value() { return Value_match(); }
+
+inline Value_match m_Specific(SDValue N) { return Value_match(N); }
+
+struct Opcode_match {
+  unsigned Opcode;
+
+  explicit Opcode_match(unsigned Opc) : Opcode(Opc) {}
+
+  bool match(const SelectionDAG *, SDValue N) {
+    return N && N->getOpcode() == Opcode;
+  }
+};
+
+inline Opcode_match m_Opc(unsigned Opcode) { return Opcode_match(Opcode); }
+
+template <unsigned NumUses, typename Pattern> struct NUses_match {
+  Pattern P;
+
+  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);
----------------
mshockwave wrote:

> 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())
```

https://github.com/llvm/llvm-project/pull/78654


More information about the llvm-commits mailing list