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

[SelectionDAG] Add OPC_MoveSibling #73643

Merged
merged 1 commit into from
Dec 12, 2023

Conversation

wangpc-pp
Copy link
Contributor

@wangpc-pp wangpc-pp commented Nov 28, 2023

There are a lot of operations to move current node to parent and
then move to another child.

So OPC_MoveSibling and its space-optimized forms are added to do
this "move to sibling" operations.

These new operations will be generated when optimizing matcher in
ContractNodes. Currently MoveParent+MoveChild will be optimized
to MoveSibling and sequences MoveParent+RecordChild+MoveChild
will be transformed into MoveSibling+RecordNode.

Overall this reduces the llc binary size with all in-tree targets by
about 30K.

@llvmbot llvmbot added the llvm:SelectionDAG SelectionDAGISel as well label Nov 28, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 28, 2023

@llvm/pr-subscribers-llvm-selectiondag

Author: Wang Pengcheng (wangpc-pp)

Changes

There are a lot of operations to move current node to parent and
then move to another child.

So OPC_MoveSibling and its space-optimized forms are added to do
this "move to sibling" operations.

These new operations will be generated when optimizing matcher in
ContractNodes. Currently MoveParent+MoveChild will be optimized
to MoveSibling, but we can do further in the future. For example,
we can transform sequences MoveParent+RecordChild+MoveChild to
MoveSibling+RecordNode.

Overall this reduces the llc binary size with all in-tree targets by
about 26K.


Full diff: https://github.com/llvm/llvm-project/pull/73643.diff

6 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/SelectionDAGISel.h (+9)
  • (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (+23)
  • (modified) llvm/utils/TableGen/DAGISelMatcher.cpp (+4)
  • (modified) llvm/utils/TableGen/DAGISelMatcher.h (+40-19)
  • (modified) llvm/utils/TableGen/DAGISelMatcherEmitter.cpp (+14)
  • (modified) llvm/utils/TableGen/DAGISelMatcherOpt.cpp (+14)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
index aa71be5d1960ff5..b15ac901656e49b 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h
@@ -143,6 +143,15 @@ class SelectionDAGISel : public MachineFunctionPass {
     OPC_MoveChild5,
     OPC_MoveChild6,
     OPC_MoveChild7,
+    OPC_MoveSibling,
+    OPC_MoveSibling0,
+    OPC_MoveSibling1,
+    OPC_MoveSibling2,
+    OPC_MoveSibling3,
+    OPC_MoveSibling4,
+    OPC_MoveSibling5,
+    OPC_MoveSibling6,
+    OPC_MoveSibling7,
     OPC_MoveParent,
     OPC_CheckSame,
     OPC_CheckChild0Same,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index a0af6faa7fbcefb..9e1c32198623757 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3238,6 +3238,29 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
       continue;
     }
 
+    case OPC_MoveSibling:
+    case OPC_MoveSibling0:
+    case OPC_MoveSibling1:
+    case OPC_MoveSibling2:
+    case OPC_MoveSibling3:
+    case OPC_MoveSibling4:
+    case OPC_MoveSibling5:
+    case OPC_MoveSibling6:
+    case OPC_MoveSibling7: {
+      // Pop the current node off the NodeStack.
+      NodeStack.pop_back();
+      assert(!NodeStack.empty() && "Node stack imbalance!");
+      N = NodeStack.back();
+
+      unsigned SiblingNo = Opcode == OPC_MoveSibling
+                               ? MatcherTable[MatcherIndex++]
+                               : Opcode - OPC_MoveSibling0;
+      if (SiblingNo >= N.getNumOperands())
+        break; // Match fails if out of range sibling #.
+      N = N.getOperand(SiblingNo);
+      NodeStack.push_back(N);
+      continue;
+    }
     case OPC_MoveParent:
       // Pop the current node off the NodeStack.
       NodeStack.pop_back();
diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp
index 0609f006763bc5b..1a5c728fafd9ca1 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -145,6 +145,10 @@ void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "MoveChild " << ChildNo << '\n';
 }
 
+void MoveSiblingMatcher::printImpl(raw_ostream &OS, unsigned Indent) const {
+  OS.indent(Indent) << "MoveSibling " << SiblingNo << '\n';
+}
+
 void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
   OS.indent(indent) << "MoveParent\n";
 }
diff --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/DAGISelMatcher.h
index e3cf847edd1273b..e69f8fa9c5d30d6 100644
--- a/llvm/utils/TableGen/DAGISelMatcher.h
+++ b/llvm/utils/TableGen/DAGISelMatcher.h
@@ -52,28 +52,29 @@ class Matcher {
 public:
   enum KindTy {
     // Matcher state manipulation.
-    Scope,                // Push a checking scope.
-    RecordNode,           // Record the current node.
-    RecordChild,          // Record a child of the current node.
-    RecordMemRef,         // Record the memref in the current node.
-    CaptureGlueInput,     // If the current node has an input glue, save it.
-    MoveChild,            // Move current node to specified child.
-    MoveParent,           // Move current node to parent.
+    Scope,            // Push a checking scope.
+    RecordNode,       // Record the current node.
+    RecordChild,      // Record a child of the current node.
+    RecordMemRef,     // Record the memref in the current node.
+    CaptureGlueInput, // If the current node has an input glue, save it.
+    MoveChild,        // Move current node to specified child.
+    MoveSibling,      // Move current node to specified sibling.
+    MoveParent,       // Move current node to parent.
 
     // Predicate checking.
-    CheckSame,            // Fail if not same as prev match.
-    CheckChildSame,       // Fail if child not same as prev match.
+    CheckSame,      // Fail if not same as prev match.
+    CheckChildSame, // Fail if child not same as prev match.
     CheckPatternPredicate,
-    CheckPredicate,       // Fail if node predicate fails.
-    CheckOpcode,          // Fail if not opcode.
-    SwitchOpcode,         // Dispatch based on opcode.
-    CheckType,            // Fail if not correct type.
-    SwitchType,           // Dispatch based on type.
-    CheckChildType,       // Fail if child has wrong type.
-    CheckInteger,         // Fail if wrong val.
-    CheckChildInteger,    // Fail if child is wrong val.
-    CheckCondCode,        // Fail if not condcode.
-    CheckChild2CondCode,  // Fail if child is wrong condcode.
+    CheckPredicate,      // Fail if node predicate fails.
+    CheckOpcode,         // Fail if not opcode.
+    SwitchOpcode,        // Dispatch based on opcode.
+    CheckType,           // Fail if not correct type.
+    SwitchType,          // Dispatch based on type.
+    CheckChildType,      // Fail if child has wrong type.
+    CheckInteger,        // Fail if wrong val.
+    CheckChildInteger,   // Fail if child is wrong val.
+    CheckCondCode,       // Fail if not condcode.
+    CheckChild2CondCode, // Fail if child is wrong condcode.
     CheckValueType,
     CheckComplexPat,
     CheckAndImm,
@@ -342,6 +343,26 @@ class MoveChildMatcher : public Matcher {
   }
 };
 
+/// MoveSiblingMatcher - This tells the interpreter to move into the
+/// specified sibling node.
+class MoveSiblingMatcher : public Matcher {
+  unsigned SiblingNo;
+
+public:
+  MoveSiblingMatcher(unsigned SiblingNo)
+      : Matcher(MoveSibling), SiblingNo(SiblingNo) {}
+
+  unsigned getSiblingNo() const { return SiblingNo; }
+
+  static bool classof(const Matcher *N) { return N->getKind() == MoveSibling; }
+
+private:
+  void printImpl(raw_ostream &OS, unsigned Indent) const override;
+  bool isEqualImpl(const Matcher *M) const override {
+    return cast<MoveSiblingMatcher>(M)->getSiblingNo() == getSiblingNo();
+  }
+};
+
 /// MoveParentMatcher - This tells the interpreter to move to the parent
 /// of the current node.
 class MoveParentMatcher : public Matcher {
diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 4da06197658cd0a..ef8b112effe5826 100644
--- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -456,6 +456,17 @@ EmitMatcher(const Matcher *N, const unsigned Indent, unsigned CurrentIdx,
     return (MCM->getChildNo() >= 8) ? 2 : 1;
   }
 
+  case Matcher::MoveSibling: {
+    const auto *MSM = cast<MoveSiblingMatcher>(N);
+
+    OS << "OPC_MoveSibling";
+    // Handle the specialized forms.
+    if (MSM->getSiblingNo() >= 8)
+      OS << ", ";
+    OS << MSM->getSiblingNo() << ",\n";
+    return (MSM->getSiblingNo() >= 8) ? 2 : 1;
+  }
+
   case Matcher::MoveParent:
     OS << "OPC_MoveParent,\n";
     return 1;
@@ -1066,6 +1077,9 @@ static StringRef getOpcodeString(Matcher::KindTy Kind) {
   case Matcher::RecordMemRef: return "OPC_RecordMemRef"; break;
   case Matcher::CaptureGlueInput: return "OPC_CaptureGlueInput"; break;
   case Matcher::MoveChild: return "OPC_MoveChild"; break;
+  case Matcher::MoveSibling:
+    return "OPC_MoveSibling";
+    break;
   case Matcher::MoveParent: return "OPC_MoveParent"; break;
   case Matcher::CheckSame: return "OPC_CheckSame"; break;
   case Matcher::CheckChildSame: return "OPC_CheckChildSame"; break;
diff --git a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
index bf2a24241e84629..f1ee10f183419aa 100644
--- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -155,6 +155,20 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
     CheckType->setNext(Tail);
     return ContractNodes(MatcherPtr, CGP);
   }
+
+  // If we have a MoveParent followed by a MoveChild, we convert it to
+  // MoveSibling.
+  if (auto *MP = dyn_cast<MoveParentMatcher>(N)) {
+    if (auto *MC = dyn_cast<MoveChildMatcher>(MP->getNext())) {
+      auto *MS = new MoveSiblingMatcher(MC->getChildNo());
+      // Insert the new node.
+      MS->setNext(MatcherPtr.release());
+      MatcherPtr.reset(MS);
+      // Remove the old one.
+      MS->setNext(MC->takeNext());
+      return ContractNodes(MatcherPtr, CGP);
+    }
+  }
 }
 
 /// FindNodeWithKind - Scan a series of matchers looking for a matcher with a

@wangpc-pp wangpc-pp force-pushed the main-matcher-table-move-sibling branch from b9f84a8 to a784e31 Compare November 29, 2023 07:09
@wangpc-pp
Copy link
Contributor Author

Ping.

llvm/utils/TableGen/DAGISelMatcherOpt.cpp Outdated Show resolved Hide resolved
@wangpc-pp wangpc-pp force-pushed the main-matcher-table-move-sibling branch from a784e31 to 5e739d0 Compare December 11, 2023 12:21
Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

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

LGTM

There are a lot of operations to move current node to parent and
then move to another child.

So `OPC_MoveSibling` and its space-optimized forms are added to do
this "move to sibling" operations.

These new operations will be generated when optimizing matcher in
`ContractNodes`. Currently `MoveParent+MoveChild` will be optimized
to `MoveSibling`, but we can do further in the future. For example,
we can transform sequences `MoveParent+RecordChild+MoveChild` to
`MoveSibling+RecordNode`.

Overall this reduces the llc binary size with all in-tree targets by
about 26K.
@wangpc-pp wangpc-pp force-pushed the main-matcher-table-move-sibling branch from 5e739d0 to a6a9ad9 Compare December 12, 2023 09:47
@wangpc-pp wangpc-pp merged commit 7144174 into llvm:main Dec 12, 2023
3 of 4 checks passed
@wangpc-pp wangpc-pp deleted the main-matcher-table-move-sibling branch December 12, 2023 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:SelectionDAG SelectionDAGISel as well
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants