// X86 has dedicated pack instructions that can handle specific truncation
// operations: PACKSS and PACKUS.
-static SDValue lowerVectorShuffleWithPACK(const SDLoc &DL, MVT VT,
- ArrayRef<int> Mask, SDValue V1,
- SDValue V2, SelectionDAG &DAG,
- const X86Subtarget &Subtarget) {
+static bool matchVectorShuffleWithPACK(MVT VT, MVT &SrcVT, SDValue &V1,
+ SDValue &V2, unsigned &PackOpcode,
+ ArrayRef<int> TargetMask,
+ SelectionDAG &DAG,
+ const X86Subtarget &Subtarget) {
unsigned NumElts = VT.getVectorNumElements();
unsigned BitSize = VT.getScalarSizeInBits();
MVT PackSVT = MVT::getIntegerVT(BitSize * 2);
MVT PackVT = MVT::getVectorVT(PackSVT, NumElts / 2);
- auto LowerWithPACK = [&](SDValue N1, SDValue N2) {
+ auto MatchPACK = [&](SDValue N1, SDValue N2) {
SDValue VV1 = DAG.getBitcast(PackVT, N1);
SDValue VV2 = DAG.getBitcast(PackVT, N2);
if ((N1.isUndef() || DAG.ComputeNumSignBits(VV1) > BitSize) &&
- (N2.isUndef() || DAG.ComputeNumSignBits(VV2) > BitSize))
- return DAG.getNode(X86ISD::PACKSS, DL, VT, VV1, VV2);
+ (N2.isUndef() || DAG.ComputeNumSignBits(VV2) > BitSize)) {
+ V1 = VV1;
+ V2 = VV2;
+ SrcVT = PackVT;
+ PackOpcode = X86ISD::PACKSS;
+ return true;
+ }
if (Subtarget.hasSSE41() || PackSVT == MVT::i16) {
APInt ZeroMask = APInt::getHighBitsSet(BitSize * 2, BitSize);
if ((N1.isUndef() || DAG.MaskedValueIsZero(VV1, ZeroMask)) &&
- (N2.isUndef() || DAG.MaskedValueIsZero(VV2, ZeroMask)))
- return DAG.getNode(X86ISD::PACKUS, DL, VT, VV1, VV2);
+ (N2.isUndef() || DAG.MaskedValueIsZero(VV2, ZeroMask))) {
+ V1 = VV1;
+ V2 = VV2;
+ SrcVT = PackVT;
+ PackOpcode = X86ISD::PACKUS;
+ return true;
+ }
}
- return SDValue();
+ return false;
};
// Try binary shuffle.
SmallVector<int, 32> BinaryMask;
createPackShuffleMask(VT, BinaryMask, false);
- if (isShuffleEquivalent(V1, V2, Mask, BinaryMask))
- if (SDValue Pack = LowerWithPACK(V1, V2))
- return Pack;
+ if (isTargetShuffleEquivalent(TargetMask, BinaryMask))
+ if (MatchPACK(V1, V2))
+ return true;
// Try unary shuffle.
SmallVector<int, 32> UnaryMask;
createPackShuffleMask(VT, UnaryMask, true);
- if (isShuffleEquivalent(V1, V2, Mask, UnaryMask))
- if (SDValue Pack = LowerWithPACK(V1, V1))
- return Pack;
+ if (isTargetShuffleEquivalent(TargetMask, UnaryMask))
+ if (MatchPACK(V1, V1))
+ return true;
+
+ return false;
+}
+
+static SDValue lowerVectorShuffleWithPACK(const SDLoc &DL, MVT VT,
+ ArrayRef<int> Mask, SDValue V1,
+ SDValue V2, SelectionDAG &DAG,
+ const X86Subtarget &Subtarget) {
+ MVT PackVT;
+ unsigned PackOpcode;
+ if (matchVectorShuffleWithPACK(VT, PackVT, V1, V2, PackOpcode, Mask, DAG,
+ Subtarget))
+ return DAG.getNode(PackOpcode, DL, VT, DAG.getBitcast(PackVT, V1),
+ DAG.getBitcast(PackVT, V2));
return SDValue();
}