[llvm] [X86] Fix XOR folding in EmitCmp (PR #210546)

Alexander Coffin via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 18 13:40:27 PDT 2026


https://github.com/GreenBeard created https://github.com/llvm/llvm-project/pull/210546

I was having fun investigating some x86 folding of various instructions and am working on a larger change set that I'm not sure I like (I may redo it), but this seemed like a smaller non-controversial piece to upstream.

(This is my first time contributing to LLVM so I apologize if I'm doing anything obviously wrong.)

>From 21bd35d21932eff8c9426b3f3fc7994bf9163fec Mon Sep 17 00:00:00 2001
From: Alexander Coffin <alexcoffin1999 at gmail.com>
Date: Sat, 18 Jul 2026 11:44:58 -0700
Subject: [PATCH 1/2] [X86] Add XOR read, modify, write folding test

---
 llvm/test/CodeGen/X86/xor-fold.ll | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/xor-fold.ll

diff --git a/llvm/test/CodeGen/X86/xor-fold.ll b/llvm/test/CodeGen/X86/xor-fold.ll
new file mode 100644
index 0000000000000..e52a17789537b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/xor-fold.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=X64
+
+define zeroext i1 @foo(ptr %x) {
+; X86-LABEL: foo:
+; X86:       # %bb.0:
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl (%eax), %ecx
+; X86-NEXT:    xorl $7, %ecx
+; X86-NEXT:    movl %ecx, (%eax)
+; X86-NEXT:    setne %al
+; X86-NEXT:    retl
+;
+; X64-LABEL: foo:
+; X64:       # %bb.0:
+; X64-NEXT:    movl (%rdi), %eax
+; X64-NEXT:    xorl $7, %eax
+; X64-NEXT:    movl %eax, (%rdi)
+; X64-NEXT:    setne %al
+; X64-NEXT:    retq
+  %1 = load i32, ptr %x
+  %2 = xor i32 %1, 7
+  store i32 %2, ptr %x
+  %tobool.not = icmp ne i32 %1, 7
+  ret i1 %tobool.not
+}

>From ab732b9e7c15a3f16852a4ff8806ec8cdf7d2e8a Mon Sep 17 00:00:00 2001
From: Alexander Coffin <alexcoffin1999 at gmail.com>
Date: Sat, 18 Jul 2026 10:55:03 -0700
Subject: [PATCH 2/2] [X86] Fix XOR folding in EmitCmp

---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 12 ++++++++++--
 llvm/test/CodeGen/X86/xor-fold.ll       |  8 ++------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 791e04deb9583..79b3e3bc5d9af 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -24077,13 +24077,21 @@ static SDValue EmitCmp(SDValue Op0, SDValue Op1, X86::CondCode X86CC,
   // If we already have an XOR of the ops, use that to check for equality.
   // Else use SUB instead of CMP to enable CSE between SUB and CMP.
   unsigned X86Opc = X86ISD::SUB;
+  SDNode *IsdNode = nullptr;
   if ((X86CC == X86::COND_E || X86CC == X86::COND_NE) &&
-      (DAG.doesNodeExist(ISD::XOR, DAG.getVTList({CmpVT}), {Op0, Op1}) ||
-       DAG.doesNodeExist(ISD::XOR, DAG.getVTList({CmpVT}), {Op1, Op0})))
+      ((IsdNode = DAG.getNodeIfExists(ISD::XOR, DAG.getVTList({CmpVT}),
+                                      {Op0, Op1})) ||
+       (IsdNode =
+            DAG.getNodeIfExists(ISD::XOR, DAG.getVTList({CmpVT}), {Op1, Op0}))))
     X86Opc = X86ISD::XOR;
 
   SDVTList VTs = DAG.getVTList(CmpVT, MVT::i32);
   SDValue CmpOp = DAG.getNode(X86Opc, dl, VTs, Op0, Op1);
+
+  if (IsdNode != nullptr) {
+    DAG.ReplaceAllUsesWith(IsdNode, &CmpOp);
+  }
+
   return CmpOp.getValue(1);
 }
 
diff --git a/llvm/test/CodeGen/X86/xor-fold.ll b/llvm/test/CodeGen/X86/xor-fold.ll
index e52a17789537b..d57326a98637d 100644
--- a/llvm/test/CodeGen/X86/xor-fold.ll
+++ b/llvm/test/CodeGen/X86/xor-fold.ll
@@ -6,17 +6,13 @@ define zeroext i1 @foo(ptr %x) {
 ; X86-LABEL: foo:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    movl (%eax), %ecx
-; X86-NEXT:    xorl $7, %ecx
-; X86-NEXT:    movl %ecx, (%eax)
+; X86-NEXT:    xorl $7, (%eax)
 ; X86-NEXT:    setne %al
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: foo:
 ; X64:       # %bb.0:
-; X64-NEXT:    movl (%rdi), %eax
-; X64-NEXT:    xorl $7, %eax
-; X64-NEXT:    movl %eax, (%rdi)
+; X64-NEXT:    xorl $7, (%rdi)
 ; X64-NEXT:    setne %al
 ; X64-NEXT:    retq
   %1 = load i32, ptr %x



More information about the llvm-commits mailing list