return SDValue();
}
+static SDValue combineVectorPackWithShuffle(SDNode *N, SelectionDAG &DAG) {
+ unsigned Opcode = N->getOpcode();
+ assert((X86ISD::PACKSS == Opcode || X86ISD::PACKUS == Opcode) &&
+ "Unexpected pack opcode");
+
+ EVT VT = N->getValueType(0);
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ unsigned NumDstElts = VT.getVectorNumElements();
+
+ // Attempt to fold PACK(LOSUBVECTOR(SHUFFLE(X)),HISUBVECTOR(SHUFFLE(X)))
+ // to SHUFFLE(PACK(LOSUBVECTOR(X),HISUBVECTOR(X))), this is mainly for
+ // truncation trees that help us avoid lane crossing shuffles.
+ // TODO: There's a lot more we can do for PACK/HADD style shuffle combines.
+ if (N0.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
+ N1.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
+ N0.getConstantOperandAPInt(1) == 0 &&
+ N1.getConstantOperandAPInt(1) == (NumDstElts / 2) &&
+ N0.getOperand(0) == N1.getOperand(0) && VT.is128BitVector() &&
+ N0.getOperand(0).getValueType().is256BitVector()) {
+ // TODO - support target/faux shuffles.
+ SDValue Vec = peekThroughBitcasts(N0.getOperand(0));
+ if (auto *SVN = dyn_cast<ShuffleVectorSDNode>(Vec)) {
+ // To keep the PACK LHS/RHS coherency, we must be able to scale the unary
+ // shuffle to a vXi64 width - we can probably relax this in the future.
+ SmallVector<int, 4> ShuffleMask;
+ if (SVN->getOperand(1).isUndef() &&
+ scaleShuffleElements(SVN->getMask(), 4, ShuffleMask)) {
+ SDLoc DL(N);
+ SDValue Lo, Hi;
+ std::tie(Lo, Hi) = DAG.SplitVector(SVN->getOperand(0), DL);
+ Lo = DAG.getBitcast(N0.getValueType(), Lo);
+ Hi = DAG.getBitcast(N1.getValueType(), Hi);
+ SDValue Res = DAG.getNode(Opcode, DL, VT, Lo, Hi);
+ Res = DAG.getBitcast(MVT::v4i32, Res);
+ Res = DAG.getVectorShuffle(MVT::v4i32, DL, Res, Res, ShuffleMask);
+ return DAG.getBitcast(VT, Res);
+ }
+ }
+ }
+
+ return SDValue();
+}
+
static SDValue combineVectorPack(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const X86Subtarget &Subtarget) {
return getConstVector(Bits, Undefs, VT.getSimpleVT(), DAG, SDLoc(N));
}
- // Attempt to fold PACK(LOSUBVECTOR(SHUFFLE(X)),HISUBVECTOR(SHUFFLE(X)))
- // to SHUFFLE(PACK(LOSUBVECTOR(X),HISUBVECTOR(X))), this is mainly for
- // truncation trees that help us avoid lane crossing shuffles.
- // TODO: There's a lot more we can do for PACK/HADD style shuffle combines.
- if (N0.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
- N1.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
- N0.getConstantOperandAPInt(1) == 0 &&
- N1.getConstantOperandAPInt(1) == (NumDstElts / 2) &&
- N0.getOperand(0) == N1.getOperand(0) && VT.is128BitVector() &&
- N0.getOperand(0).getValueType().is256BitVector()) {
- // TODO - support target/faux shuffles.
- SDValue Vec = peekThroughBitcasts(N0.getOperand(0));
- if (auto *SVN = dyn_cast<ShuffleVectorSDNode>(Vec)) {
- // To keep the PACK LHS/RHS coherency, we must be able to scale the unary
- // shuffle to a vXi64 width - we can probably relax this in the future.
- SmallVector<int, 4> ShuffleMask;
- if (SVN->getOperand(1).isUndef() &&
- scaleShuffleElements(SVN->getMask(), 4, ShuffleMask)) {
- SDLoc DL(N);
- SDValue Lo, Hi;
- std::tie(Lo, Hi) = DAG.SplitVector(SVN->getOperand(0), DL);
- Lo = DAG.getBitcast(N0.getValueType(), Lo);
- Hi = DAG.getBitcast(N1.getValueType(), Hi);
- SDValue Res = DAG.getNode(Opcode, DL, VT, Lo, Hi);
- Res = DAG.getBitcast(MVT::v4i32, Res);
- Res = DAG.getVectorShuffle(MVT::v4i32, DL, Res, Res, ShuffleMask);
- return DAG.getBitcast(VT, Res);
- }
- }
- }
+ // Try to fold PACK(SHUFFLE(),SHUFFLE()) -> SHUFFLE(PACK()).
+ if (SDValue V = combineVectorPackWithShuffle(N, DAG))
+ return V;
// Try to combine a PACKUSWB/PACKSSWB implemented truncate with a regular
// truncate to create a larger truncate.