diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 195f11a8264..82ac9f90826 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -17155,6 +17155,41 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, } } + // Try to fold this VSELECT into a MOVSS/MOVSD + if (N->getOpcode() == ISD::VSELECT && + Cond.getOpcode() == ISD::BUILD_VECTOR && !DCI.isBeforeLegalize()) { + if (VT == MVT::v4i32 || VT == MVT::v4f32 || + (Subtarget->hasSSE2() && (VT == MVT::v2i64 || VT == MVT::v2f64))) { + bool CanFold = false; + unsigned NumElems = Cond.getNumOperands(); + SDValue A = LHS; + SDValue B = RHS; + + if (isZero(Cond.getOperand(0))) { + CanFold = true; + + // fold (vselect <0,-1,-1,-1>, A, B) -> (movss A, B) + // fold (vselect <0,-1> -> (movsd A, B) + for (unsigned i = 1, e = NumElems; i != e && CanFold; ++i) + CanFold = isAllOnes(Cond.getOperand(i)); + } else if (isAllOnes(Cond.getOperand(0))) { + CanFold = true; + std::swap(A, B); + + // fold (vselect <-1,0,0,0>, A, B) -> (movss B, A) + // fold (vselect <-1,0> -> (movsd B, A) + for (unsigned i = 1, e = NumElems; i != e && CanFold; ++i) + CanFold = isZero(Cond.getOperand(i)); + } + + if (CanFold) { + if (VT == MVT::v4i32 || VT == MVT::v4f32) + return getTargetShuffleNode(X86ISD::MOVSS, DL, VT, A, B, DAG); + return getTargetShuffleNode(X86ISD::MOVSD, DL, VT, A, B, DAG); + } + } + } + // If we know that this node is legal then we know that it is going to be // matched by one of the SSE/AVX BLEND instructions. These instructions only // depend on the highest bit in each word. Try to use SimplifyDemandedBits |