[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