[llvm] [X86] combineX86FPLogicOp - attempt to fold FAND/FOR/FXOR scalar nodes if they are constant or contain UNDEFs (PR #177947)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 26 04:57:43 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Simon Pilgrim (RKSimon)

<details>
<summary>Changes</summary>

Fixes #<!-- -->177923

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


2 Files Affected:

- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+17-5) 
- (added) llvm/test/CodeGen/X86/pr177923.ll (+72) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 4b184c3443a14..02a9f34503e20 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -55772,14 +55772,26 @@ SDValue X86TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
 static SDValue combineX86FPLogicOp(SDNode *N, SelectionDAG &DAG,
                                    const X86Subtarget &Subtarget) {
   MVT VT = N->getSimpleValueType(0);
-  // If we have integer vector types available, use the integer opcodes.
-  if (!VT.isVector() || !Subtarget.hasSSE2())
+  SDValue Op0 = N->getOperand(0);
+  SDValue Op1 = N->getOperand(1);
+
+  // Check if this will constant fold as a generic op.
+  bool WillFold = false;
+  if (DAG.getTargetLoweringInfo().isCommutativeBinOp(N->getOpcode())) {
+    WillFold |= Op0.isUndef() || Op1.isUndef();
+    WillFold |= Op0.getOpcode() == ISD::ConstantFP &&
+                Op1.getOpcode() == ISD::ConstantFP;
+  }
+
+  // If this will fold away or we have integer vector types available, use the
+  // integer opcodes.
+  if (!WillFold && (!VT.isVector() || !Subtarget.hasSSE2()))
     return SDValue();
 
   SDLoc dl(N);
-  MVT IntVT = VT.changeVectorElementTypeToInteger();
-  SDValue Op0 = DAG.getBitcast(IntVT, N->getOperand(0));
-  SDValue Op1 = DAG.getBitcast(IntVT, N->getOperand(1));
+  MVT IntVT = VT.changeTypeToInteger();
+  Op0 = DAG.getBitcast(IntVT, Op0);
+  Op1 = DAG.getBitcast(IntVT, Op1);
   unsigned IntOpcode;
   switch (N->getOpcode()) {
   // clang-format off
diff --git a/llvm/test/CodeGen/X86/pr177923.ll b/llvm/test/CodeGen/X86/pr177923.ll
new file mode 100644
index 0000000000000..8063af33ee5d7
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr177923.ll
@@ -0,0 +1,72 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; 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 double @PR177923_and() nounwind {
+; X86-LABEL: PR177923_and:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %ebp
+; X86-NEXT:    movl %esp, %ebp
+; X86-NEXT:    andl $-8, %esp
+; X86-NEXT:    subl $8, %esp
+; X86-NEXT:    movl $0, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl $0, (%esp)
+; X86-NEXT:    fldl (%esp)
+; X86-NEXT:    movl %ebp, %esp
+; X86-NEXT:    popl %ebp
+; X86-NEXT:    retl
+;
+; X64-LABEL: PR177923_and:
+; X64:       # %bb.0:
+; X64-NEXT:    xorps %xmm0, %xmm0
+; X64-NEXT:    retq
+  %bc0 = bitcast <8 x i16> <i16 undef, i16 undef, i16 undef, i16 undef, i16 0, i16 0, i16 0, i16 0> to <2 x double>
+  %elt = extractelement <2 x double> %bc0, i64 0
+  %bc1 = bitcast double %elt to <4 x i16>
+  %and = and <4 x i16> <i16 1, i16 1, i16 1, i16 1>, %bc1
+  %res = bitcast <4 x i16> %and to double
+  ret double %res
+}
+
+define double @PR177923_or() nounwind {
+; X86-LABEL: PR177923_or:
+; X86:       # %bb.0:
+; X86-NEXT:    pushl %ebp
+; X86-NEXT:    movl %esp, %ebp
+; X86-NEXT:    andl $-8, %esp
+; X86-NEXT:    subl $8, %esp
+; X86-NEXT:    movl $-1, {{[0-9]+}}(%esp)
+; X86-NEXT:    movl $-1, (%esp)
+; X86-NEXT:    fldl (%esp)
+; X86-NEXT:    movl %ebp, %esp
+; X86-NEXT:    popl %ebp
+; X86-NEXT:    retl
+;
+; X64-LABEL: PR177923_or:
+; X64:       # %bb.0:
+; X64-NEXT:    movsd {{.*#+}} xmm0 = [NaN,0.0E+0]
+; X64-NEXT:    retq
+  %bc0 = bitcast <8 x i16> <i16 undef, i16 undef, i16 undef, i16 undef, i16 0, i16 0, i16 0, i16 0> to <2 x double>
+  %elt = extractelement <2 x double> %bc0, i64 0
+  %bc1 = bitcast double %elt to <4 x i16>
+  %or = or <4 x i16> <i16 1, i16 1, i16 1, i16 1>, %bc1
+  %res = bitcast <4 x i16> %or to double
+  ret double %res
+}
+
+define double @PR177923_xor() nounwind {
+; X86-LABEL: PR177923_xor:
+; X86:       # %bb.0:
+; X86-NEXT:    fldz
+; X86-NEXT:    retl
+;
+; X64-LABEL: PR177923_xor:
+; X64:       # %bb.0:
+; X64-NEXT:    retq
+  %bc0 = bitcast <8 x i16> <i16 undef, i16 undef, i16 undef, i16 undef, i16 0, i16 0, i16 0, i16 0> to <2 x double>
+  %elt = extractelement <2 x double> %bc0, i64 0
+  %bc1 = bitcast double %elt to <4 x i16>
+  %xor = xor <4 x i16> <i16 1, i16 1, i16 1, i16 1>, %bc1
+  %res = bitcast <4 x i16> %xor to double
+  ret double %res
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/177947


More information about the llvm-commits mailing list