[llvm] [SelectionDAGISel] Don't merge input chains if it would put a token factor in the way of a glue. (PR #167805)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 13 07:34:26 PST 2025


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/167805

>From 712fd9fb4449a32fe598cdfb95fd97eba6908de7 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 12 Nov 2025 17:04:12 -0800
Subject: [PATCH 1/3] [SelectionDAGISel] Don't merge input chains if it would
 put a token factor in the way of a glue.

In the new test, we're trying to fold a load and a X86ISD::CALL.
The call has a CopyToReg glued to it. The load and the call have
different input chains so they need to be merged. This results in
a TokenFactor that gets put between the CopyToReg and the final CALLm
instruction. The DAG scheduler can't handle that.

The load here was created by legalization of the extract_element
using a stack temporary store and load. A normal IR load would
be chained into call sequence by SelectionDAGBuilder. This would usually
have the load chained in before the CopyToReg. The store/load created by
legalization don't get chained into the rest of the DAG.

Fixes #63790
---
 .../CodeGen/SelectionDAG/SelectionDAGISel.cpp    | 16 ++++++++++++----
 llvm/test/CodeGen/X86/pr63790.ll                 | 10 ++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/X86/pr63790.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index e78dfb12505c7..9aac0ff3cd8a7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2783,7 +2783,7 @@ void SelectionDAGISel::UpdateChains(
 /// be used as the input node chain for the generated nodes.
 static SDValue
 HandleMergeInputChains(SmallVectorImpl<SDNode*> &ChainNodesMatched,
-                       SelectionDAG *CurDAG) {
+                       SDValue InputGlue, SelectionDAG *CurDAG) {
 
   SmallPtrSet<const SDNode *, 16> Visited;
   SmallVector<const SDNode *, 8> Worklist;
@@ -2826,8 +2826,16 @@ HandleMergeInputChains(SmallVectorImpl<SDNode*> &ChainNodesMatched,
   // node that is both the predecessor and successor of the
   // to-be-merged nodes. Fail.
   Visited.clear();
-  for (SDValue V : InputChains)
+  for (SDValue V : InputChains) {
+    // If we need to create a TokenFactor, and any of the input chains will
+    // also be glued to the output, we cannot merge the chains. The TokenFactor
+    // would prevent the glue from being honored.
+    if (InputChains.size() != 1 &&
+        V->getValueType(V->getNumValues()-1) == MVT::Glue &&
+        InputGlue.getNode() == V.getNode())
+      return SDValue();
     Worklist.push_back(V.getNode());
+  }
 
   for (auto *N : ChainNodesMatched)
     if (SDNode::hasPredecessorHelper(N, Visited, Worklist, Max, true))
@@ -3989,7 +3997,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
       }
 
       // Merge the input chains if they are not intra-pattern references.
-      InputChain = HandleMergeInputChains(ChainNodesMatched, CurDAG);
+      InputChain = HandleMergeInputChains(ChainNodesMatched, InputGlue, CurDAG);
 
       if (!InputChain.getNode())
         break;  // Failed to merge.
@@ -4033,7 +4041,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
         break;
 
       // Merge the input chains if they are not intra-pattern references.
-      InputChain = HandleMergeInputChains(ChainNodesMatched, CurDAG);
+      InputChain = HandleMergeInputChains(ChainNodesMatched, InputGlue, CurDAG);
 
       if (!InputChain.getNode())
         break;  // Failed to merge.
diff --git a/llvm/test/CodeGen/X86/pr63790.ll b/llvm/test/CodeGen/X86/pr63790.ll
new file mode 100644
index 0000000000000..608d3ff41d164
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr63790.ll
@@ -0,0 +1,10 @@
+; RUN: llc < %s -mtriple=x86_64 | FileCheck %s
+
+define void @f(ptr %0, i64 %1) {
+BB:
+  %fps = load <2 x ptr>, ptr %0
+  %fp = extractelement <2 x ptr> %fps, i64 %1
+  %p = call ptr %fp(i32 42)
+  store <2 x ptr> %fps, ptr %p
+  ret void
+}

>From 2caeb4a745443ac760d1338a64958d671660ee0f Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 12 Nov 2025 17:51:29 -0800
Subject: [PATCH 2/3] fixup! clang-format

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 9aac0ff3cd8a7..efc49941e14db 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2782,7 +2782,7 @@ void SelectionDAGISel::UpdateChains(
 /// induce cycles in the DAG) and if so, creating a TokenFactor node. that will
 /// be used as the input node chain for the generated nodes.
 static SDValue
-HandleMergeInputChains(SmallVectorImpl<SDNode*> &ChainNodesMatched,
+HandleMergeInputChains(SmallVectorImpl<SDNode *> &ChainNodesMatched,
                        SDValue InputGlue, SelectionDAG *CurDAG) {
 
   SmallPtrSet<const SDNode *, 16> Visited;
@@ -2831,7 +2831,7 @@ HandleMergeInputChains(SmallVectorImpl<SDNode*> &ChainNodesMatched,
     // also be glued to the output, we cannot merge the chains. The TokenFactor
     // would prevent the glue from being honored.
     if (InputChains.size() != 1 &&
-        V->getValueType(V->getNumValues()-1) == MVT::Glue &&
+        V->getValueType(V->getNumValues() - 1) == MVT::Glue &&
         InputGlue.getNode() == V.getNode())
       return SDValue();
     Worklist.push_back(V.getNode());

>From 1c7edce021f41bdb996ba693649a6b03e4d1695c Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Thu, 13 Nov 2025 07:34:06 -0800
Subject: [PATCH 3/3] fixup! Add CHECK lines

---
 llvm/test/CodeGen/X86/pr63790.ll | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/llvm/test/CodeGen/X86/pr63790.ll b/llvm/test/CodeGen/X86/pr63790.ll
index 608d3ff41d164..e4e7a3c536d07 100644
--- a/llvm/test/CodeGen/X86/pr63790.ll
+++ b/llvm/test/CodeGen/X86/pr63790.ll
@@ -1,6 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc < %s -mtriple=x86_64 | FileCheck %s
 
 define void @f(ptr %0, i64 %1) {
+; CHECK-LABEL: f:
+; CHECK:       # %bb.0: # %BB
+; CHECK-NEXT:    subq $40, %rsp
+; CHECK-NEXT:    .cfi_def_cfa_offset 48
+; CHECK-NEXT:    andl $1, %esi
+; CHECK-NEXT:    movaps (%rdi), %xmm0
+; CHECK-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; CHECK-NEXT:    movaps %xmm0, {{[0-9]+}}(%rsp)
+; CHECK-NEXT:    movl $42, %edi
+; CHECK-NEXT:    callq *16(%rsp,%rsi,8)
+; CHECK-NEXT:    movaps (%rsp), %xmm0 # 16-byte Reload
+; CHECK-NEXT:    movaps %xmm0, (%rax)
+; CHECK-NEXT:    addq $40, %rsp
+; CHECK-NEXT:    .cfi_def_cfa_offset 8
+; CHECK-NEXT:    retq
 BB:
   %fps = load <2 x ptr>, ptr %0
   %fp = extractelement <2 x ptr> %fps, i64 %1



More information about the llvm-commits mailing list