diff options
Diffstat (limited to 'lib/Target')
| -rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 55 | 
1 files changed, 40 insertions, 15 deletions
| diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 3564ce3..296bcf6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -9350,11 +9350,49 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget *Subtarget,    if (Swap)      std::swap(Op0, Op1); +  // Since SSE has no unsigned integer comparisons, we need to flip  the sign +  // bits of the inputs before performing those operations. +  if (FlipSigns) { +    EVT EltVT = VT.getVectorElementType(); +    SDValue SignBit = DAG.getConstant(APInt::getSignBit(EltVT.getSizeInBits()), +                                      EltVT); +    std::vector<SDValue> SignBits(VT.getVectorNumElements(), SignBit); +    SDValue SignVec = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &SignBits[0], +                                    SignBits.size()); +    Op0 = DAG.getNode(ISD::XOR, dl, VT, Op0, SignVec); +    Op1 = DAG.getNode(ISD::XOR, dl, VT, Op1, SignVec); +  } +    // Check that the operation in question is available (most are plain SSE2,    // but PCMPGTQ and PCMPEQQ have different requirements).    if (VT == MVT::v2i64) { -    if (Opc == X86ISD::PCMPGT && !Subtarget->hasSSE42()) -      return SDValue(); +    if (Opc == X86ISD::PCMPGT && !Subtarget->hasSSE42()) { +      assert(Subtarget->hasSSE2() && "Don't know how to lower!"); + +      // First cast everything to the right type, +      Op0 = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, Op0); +      Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, Op1); + +      // Emulate PCMPGTQ with (hi1 > hi2) | ((hi1 == hi2) & (lo1 > lo2)) +      SDValue GT = DAG.getNode(X86ISD::PCMPGT, dl, MVT::v4i32, Op0, Op1); +      SDValue EQ = DAG.getNode(X86ISD::PCMPEQ, dl, MVT::v4i32, Op0, Op1); + +      // Create masks for only the low parts/high parts of the 64 bit integers. +      const int MaskHi[] = { 1, 1, 3, 3 }; +      const int MaskLo[] = { 0, 0, 2, 2 }; +      SDValue EQHi = DAG.getVectorShuffle(MVT::v4i32, dl, EQ, EQ, MaskHi); +      SDValue GTLo = DAG.getVectorShuffle(MVT::v4i32, dl, GT, GT, MaskLo); +      SDValue GTHi = DAG.getVectorShuffle(MVT::v4i32, dl, GT, GT, MaskHi); + +      SDValue Result = DAG.getNode(ISD::AND, dl, MVT::v4i32, EQHi, GTLo); +      Result = DAG.getNode(ISD::OR, dl, MVT::v4i32, Result, GTHi); + +      if (Invert) +        Result = DAG.getNOT(dl, Result, MVT::v4i32); + +      return DAG.getNode(ISD::BITCAST, dl, VT, Result); +    } +      if (Opc == X86ISD::PCMPEQ && !Subtarget->hasSSE41()) {        // If pcmpeqq is missing but pcmpeqd is available synthesize pcmpeqq with        // pcmpeqd + pshufd + pand. @@ -9379,19 +9417,6 @@ static SDValue LowerVSETCC(SDValue Op, const X86Subtarget *Subtarget,      }    } -  // Since SSE has no unsigned integer comparisons, we need to flip  the sign -  // bits of the inputs before performing those operations. -  if (FlipSigns) { -    EVT EltVT = VT.getVectorElementType(); -    SDValue SignBit = DAG.getConstant(APInt::getSignBit(EltVT.getSizeInBits()), -                                      EltVT); -    std::vector<SDValue> SignBits(VT.getVectorNumElements(), SignBit); -    SDValue SignVec = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &SignBits[0], -                                    SignBits.size()); -    Op0 = DAG.getNode(ISD::XOR, dl, VT, Op0, SignVec); -    Op1 = DAG.getNode(ISD::XOR, dl, VT, Op1, SignVec); -  } -    SDValue Result = DAG.getNode(Opc, dl, VT, Op0, Op1);    // If the logical-not of the result is required, perform that now. | 
