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> 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> , %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> 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> , %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> 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> , %bc1 + %res = bitcast <4 x i16> %xor to double + ret double %res +}