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

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 18 17:00:38 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);
----------------
topperc wrote:

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.

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


More information about the llvm-commits mailing list