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

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 13 10:56:04 PDT 2026


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/216134

>From 542ca8dc7d83462312b3f4027ce676eb2f4eb4e6 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Thu, 13 Aug 2026 13:26:33 -0400
Subject: [PATCH 1/2] Pre-commit test

---
 llvm/test/CodeGen/X86/cmp-xor.ll | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/llvm/test/CodeGen/X86/cmp-xor.ll b/llvm/test/CodeGen/X86/cmp-xor.ll
index a8a7da4871ba9..1012c9b4c4a45 100644
--- a/llvm/test/CodeGen/X86/cmp-xor.ll
+++ b/llvm/test/CodeGen/X86/cmp-xor.ll
@@ -54,3 +54,26 @@ define i32 @cmp_xor_i32_commute(i32 %a, i32 %b, i32 %c)
   ret i32 %sel
 }
 
+define zeroext i1 @xor_cmp_rmw_i32(ptr %x) {
+; X86-LABEL: xor_cmp_rmw_i32:
+; 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
+  %load = load i32, ptr %x
+  %xor = xor i32 %load, 7
+  store i32 %xor, ptr %x
+  %cmp = icmp ne i32 %load, 7
+  ret i1 %cmp
+}

>From b5489d849ee500f548672be1e1146a8e55f7a0f6 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Thu, 13 Aug 2026 13:41:54 -0400
Subject: [PATCH 2/2] [X86] Fix XOR folding in EmitCmp

Prevent redundant xors from being emitted.
---
 llvm/lib/Target/X86/X86ISelLowering.cpp | 29 +++++++++++++++++++++++++
 llvm/test/CodeGen/X86/cmp-xor.ll        | 10 +++------
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index eed9416741c17..37eb3715809d0 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59481,6 +59481,34 @@ static SDValue combineX86AddSub(SDNode *N, SelectionDAG &DAG,
                                    /*ZeroSecondOpOnly*/ true);
 }
 
+static SDValue combineX86XOR(SDNode *N, SelectionDAG &DAG,
+                             TargetLowering::DAGCombinerInfo &DCI) {
+  assert(N->getOpcode() == X86ISD::XOR && "Expected X86ISD::XOR");
+
+  SDLoc DL(N);
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+  MVT VT = LHS.getSimpleValueType();
+
+  // If we don't use the flag result, simplify back to a generic op.
+  if (!N->hasAnyUseOfValue(1)) {
+    SDValue Res = DAG.getNode(ISD::XOR, DL, VT, LHS, RHS);
+    return DAG.getMergeValues({Res, DAG.getConstant(0, DL, MVT::i32)}, DL);
+  }
+
+  // Fold any matching generic nodes to reuse this node.
+  auto MatchGeneric = [&](SDValue N0, SDValue N1) {
+    SDValue Ops[] = {N0, N1};
+    SDVTList VTs = DAG.getVTList(N->getValueType(0));
+    if (SDNode *Generic = DAG.getNodeIfExists(ISD::XOR, VTs, Ops))
+      DCI.CombineTo(Generic, SDValue(N, 0));
+  };
+  MatchGeneric(LHS, RHS);
+  MatchGeneric(RHS, LHS);
+
+  return SDValue();
+}
+
 static SDValue combineSBB(SDNode *N, SelectionDAG &DAG) {
   SDValue LHS = N->getOperand(0);
   SDValue RHS = N->getOperand(1);
@@ -63240,6 +63268,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
   case ISD::SUB:            return combineSub(N, DAG, DCI, Subtarget);
   case X86ISD::ADD:
   case X86ISD::SUB:         return combineX86AddSub(N, DAG, DCI, Subtarget);
+  case X86ISD::XOR:         return combineX86XOR(N, DAG, DCI);
   case ISD::SADDSAT:
   case ISD::SSUBSAT:        return combineToHorizontalAddSub(N, DAG, Subtarget);
   case X86ISD::CLOAD:
diff --git a/llvm/test/CodeGen/X86/cmp-xor.ll b/llvm/test/CodeGen/X86/cmp-xor.ll
index 1012c9b4c4a45..eed1951898b1d 100644
--- a/llvm/test/CodeGen/X86/cmp-xor.ll
+++ b/llvm/test/CodeGen/X86/cmp-xor.ll
@@ -58,17 +58,13 @@ define zeroext i1 @xor_cmp_rmw_i32(ptr %x) {
 ; X86-LABEL: xor_cmp_rmw_i32:
 ; 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-LABEL: xor_cmp_rmw_i32:
 ; 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
   %load = load i32, ptr %x



More information about the llvm-commits mailing list