[llvm] Make RAUW skip instances where operand is the replacement node (PR #212724)

Soham Karandikar via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 29 09:48:58 PDT 2026


https://github.com/skadewdl3 updated https://github.com/llvm/llvm-project/pull/212724

>From c4374fbec02417ee051c81e57ffa1020abc67165 Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 03:12:26 -0500
Subject: [PATCH 1/7] Fixed self-referential token factor not being found in
 cse map

forgot to uncommnt the fix lol
---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 679fa3fe36e27..87844f31afeab 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -13301,6 +13301,15 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
   RAUWUpdateListener Listener(*this, UI, UE);
   while (UI != UE) {
     SDNode *User = UI->getUser();
+    
+    if (User == To.getNode()) {
+      do {
+        ++UI;
+      } while (UI != UE && UI->getUser() == User);
+      continue;
+    }
+
+
     bool UserRemovedFromCSEMaps = false;
 
     // A user can appear in a use list multiple times, and when this

>From 08e2ee6e72b5ade151bbaad0d75d909ecc4490f2 Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 04:22:08 -0500
Subject: [PATCH 2/7] Added a test and comment

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  3 +++
 .../X86/dagcombine-tokenfactor-cse-crash.ll    | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 87844f31afeab..cb79b69d9f1f3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -13302,6 +13302,9 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
   while (UI != UE) {
     SDNode *User = UI->getUser();
     
+    // Don't replace uses of the To node if is is self-referential.
+    // If CSE tries to merge the Use with another node post-replacement
+    // it'll try to remove the same node from the CSE map twice, causing a crash.
     if (User == To.getNode()) {
       do {
         ++UI;
diff --git a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
new file mode 100644
index 0000000000000..5e9eee133ad6a
--- /dev/null
+++ b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
@@ -0,0 +1,18 @@
+; RUN: llc < %s -mtriple=x86_64 -mattr=+avx2 -o /dev/null
+;
+; Verify that CSE-reusing a TokenFactor during broadcast-load combining does not
+; introduce a self-reference while replacing the old chain.
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i32 @f18() #0 {
+entry:
+  %0 = load <15 x i64>, ptr null, align 128
+  %shuffle = shufflevector <15 x i64> %0, <15 x i64> zeroinitializer, <16 x i32> <i32 7, i32 6, i32 4, i32 12, i32 9, i32 5, i32 3, i32 5, i32 12, i32 13, i32 0, i32 14, i32 7, i32 8, i32 4, i32 2>
+  %shuffle1 = shufflevector <16 x i64> %shuffle, <16 x i64> zeroinitializer, <16 x i32> <i32 1, i32 5, i32 4, i32 2, i32 7, i32 13, i32 3, i32 2, i32 5, i32 10, i32 8, i32 4, i32 0, i32 8, i32 7, i32 6>
+  store <16 x i64> %shuffle1, ptr null, align 128
+  ret i32 0
+}
+
+attributes #0 = { "target-features"="+avx2" }

>From d6fe377f40ca1f6ca06c4e1628127ecc4d3740f4 Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 04:29:50 -0500
Subject: [PATCH 3/7] ran clang-format, removed target triple from the RUN
 command in lit test

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp            | 6 +++---
 llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index cb79b69d9f1f3..913e09108b549 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -13301,10 +13301,11 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
   RAUWUpdateListener Listener(*this, UI, UE);
   while (UI != UE) {
     SDNode *User = UI->getUser();
-    
+
     // Don't replace uses of the To node if is is self-referential.
     // If CSE tries to merge the Use with another node post-replacement
-    // it'll try to remove the same node from the CSE map twice, causing a crash.
+    // it'll try to remove the same node from the CSE map twice, causing a
+    // crash.
     if (User == To.getNode()) {
       do {
         ++UI;
@@ -13312,7 +13313,6 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
       continue;
     }
 
-
     bool UserRemovedFromCSEMaps = false;
 
     // A user can appear in a use list multiple times, and when this
diff --git a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
index 5e9eee133ad6a..8829c36d9f80f 100644
--- a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
+++ b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mtriple=x86_64 -mattr=+avx2 -o /dev/null
+; RUN: llc < %s -mattr=+avx2 -o /dev/null
 ;
 ; Verify that CSE-reusing a TokenFactor during broadcast-load combining does not
 ; introduce a self-reference while replacing the old chain.

>From 71be48cec196ce1c43c68fc36096ebd6d4c18310 Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 04:31:16 -0500
Subject: [PATCH 4/7] Removed target features from RUN command in lit test

---
 llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
index 8829c36d9f80f..03a1817d9bf65 100644
--- a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
+++ b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -mattr=+avx2 -o /dev/null
+; RUN: llc < %s -o /dev/null
 ;
 ; Verify that CSE-reusing a TokenFactor during broadcast-load combining does not
 ; introduce a self-reference while replacing the old chain.

>From cd5444a8744f4f54b999f1dc7d8eaba5418aba38 Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 11:30:36 -0500
Subject: [PATCH 5/7] Removed a suspicious assert for the invariant that the
 DAG should contain a cycle

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 232cd609251db..3c0ecd2393f60 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18381,7 +18381,7 @@ SDValue DAGCombiner::visitFREEZE(SDNode *N) {
     DAG.ReplaceAllUsesOfValueWith(N0, FrozenN0);
     // ReplaceAllUsesOfValueWith will have also updated the use in N, thus
     // creating a cycle in a DAG. Let's undo that by mutating the freeze.
-    assert(N->getOperand(0) == FrozenN0 && "Expected cycle in DAG");
+    // assert(N->getOperand(0) == FrozenN0 && "Expected cycle in DAG");
     DAG.UpdateNodeOperands(N, N0);
     // Revisit the node.
     AddToWorklist(N);

>From e65750be280d6c6760402f5d80de74f4a4f7fbeb Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 11:32:36 -0500
Subject: [PATCH 6/7] Removed UB from test

---
 llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
index 03a1817d9bf65..a0bd6fe44cdd5 100644
--- a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
+++ b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
@@ -6,9 +6,11 @@
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
+ at g28 = dso_local local_unnamed_addr global <16 x i64> zeroinitializer, align 128
+
 define i32 @f18() #0 {
 entry:
-  %0 = load <15 x i64>, ptr null, align 128
+  %0 = load <15 x i64>, ptr @g28, align 128
   %shuffle = shufflevector <15 x i64> %0, <15 x i64> zeroinitializer, <16 x i32> <i32 7, i32 6, i32 4, i32 12, i32 9, i32 5, i32 3, i32 5, i32 12, i32 13, i32 0, i32 14, i32 7, i32 8, i32 4, i32 2>
   %shuffle1 = shufflevector <16 x i64> %shuffle, <16 x i64> zeroinitializer, <16 x i32> <i32 1, i32 5, i32 4, i32 2, i32 7, i32 13, i32 3, i32 2, i32 5, i32 10, i32 8, i32 4, i32 0, i32 8, i32 7, i32 6>
   store <16 x i64> %shuffle1, ptr null, align 128

>From 2ce6d2f33586c13162b9a1693d96d1fb6d959523 Mon Sep 17 00:00:00 2001
From: Soham Karandikar <sohamk10 at gmail.com>
Date: Wed, 29 Jul 2026 11:48:39 -0500
Subject: [PATCH 7/7] Generate checks for lit test

---
 .../X86/dagcombine-tokenfactor-cse-crash.ll   | 35 ++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
index a0bd6fe44cdd5..cab380803278a 100644
--- a/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
+++ b/llvm/test/CodeGen/X86/dagcombine-tokenfactor-cse-crash.ll
@@ -1,4 +1,5 @@
-; RUN: llc < %s -o /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s | FileCheck %s
 ;
 ; Verify that CSE-reusing a TokenFactor during broadcast-load combining does not
 ; introduce a self-reference while replacing the old chain.
@@ -9,6 +10,38 @@ target triple = "x86_64-unknown-linux-gnu"
 @g28 = dso_local local_unnamed_addr global <16 x i64> zeroinitializer, align 128
 
 define i32 @f18() #0 {
+; CHECK-LABEL: f18:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vmovaps g28+32(%rip), %ymm0
+; CHECK-NEXT:    vmovaps g28+64(%rip), %xmm1
+; CHECK-NEXT:    vunpckhpd {{.*#+}} xmm1 = xmm1[1],mem[1]
+; CHECK-NEXT:    vpermpd {{.*#+}} ymm2 = ymm1[0,1,2,1]
+; CHECK-NEXT:    vbroadcastsd g28+24(%rip), %ymm3
+; CHECK-NEXT:    vblendps {{.*#+}} ymm2 = ymm2[0,1,2,3],ymm3[4,5],ymm2[6,7]
+; CHECK-NEXT:    vmovddup {{.*#+}} xmm3 = mem[0,0]
+; CHECK-NEXT:    vpermpd {{.*#+}} ymm4 = ymm0[3,2,0,3]
+; CHECK-NEXT:    vbroadcastsd g28+96(%rip), %ymm5
+; CHECK-NEXT:    vblendps {{.*#+}} ymm6 = ymm4[0,1,2,3,4,5],ymm5[6,7]
+; CHECK-NEXT:    vperm2f128 {{.*#+}} ymm7 = ymm5[0,1],mem[0,1]
+; CHECK-NEXT:    vblendps {{.*#+}} ymm0 = ymm0[0,1,2,3],ymm6[4,5,6,7]
+; CHECK-NEXT:    vshufps {{.*#+}} ymm0 = ymm0[2,3,0,1,6,7,4,5]
+; CHECK-NEXT:    vblendps {{.*#+}} ymm0 = ymm0[0,1],ymm3[2,3],ymm0[4,5,6,7]
+; CHECK-NEXT:    vpermpd {{.*#+}} ymm3 = ymm1[0,1,0,1]
+; CHECK-NEXT:    vshufps {{.*#+}} ymm6 = ymm6[2,3,0,1,6,7,4,5]
+; CHECK-NEXT:    vblendps {{.*#+}} ymm3 = ymm6[0,1],ymm3[2,3,4,5],ymm6[6,7]
+; CHECK-NEXT:    vshufps {{.*#+}} ymm2 = ymm2[2,3,0,1,6,7,4,5]
+; CHECK-NEXT:    vblendps {{.*#+}} ymm2 = ymm4[0,1,2,3],ymm2[4,5,6,7]
+; CHECK-NEXT:    vblendps {{.*#+}} ymm2 = ymm2[0,1],ymm5[2,3],ymm2[4,5,6,7]
+; CHECK-NEXT:    vpermpd {{.*#+}} ymm1 = ymm1[1,1,2,0]
+; CHECK-NEXT:    vpermpd {{.*#+}} ymm4 = ymm7[0,2,0,3]
+; CHECK-NEXT:    vblendps {{.*#+}} ymm1 = ymm1[0,1],ymm4[2,3,4,5],ymm1[6,7]
+; CHECK-NEXT:    vmovaps %ymm1, 64
+; CHECK-NEXT:    vmovaps %ymm3, 0
+; CHECK-NEXT:    vmovaps %ymm0, 32
+; CHECK-NEXT:    vmovaps %ymm2, 96
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    retq
 entry:
   %0 = load <15 x i64>, ptr @g28, align 128
   %shuffle = shufflevector <15 x i64> %0, <15 x i64> zeroinitializer, <16 x i32> <i32 7, i32 6, i32 4, i32 12, i32 9, i32 5, i32 3, i32 5, i32 12, i32 13, i32 0, i32 14, i32 7, i32 8, i32 4, i32 2>



More information about the llvm-commits mailing list