This is the first step towards refactoring the x86 vector shuffle code. The

general idea here is to have a group of x86 target specific nodes which are
going to be selected during lowering and then directly matched in isel.

The commit includes the addition of those specific nodes and a *bunch* of
patterns, and incrementally we're going to switch between them and what we
have right now. Both the patterns and target specific nodes can change as
we move forward with this work.

llvm-svn: 111691
This commit is contained in:
Bruno Cardoso Lopes 2010-08-20 22:55:05 +00:00
parent 31ab7e6b8c
commit 28d9071635
5 changed files with 494 additions and 1 deletions

View File

@ -603,7 +603,7 @@ namespace ISD {
/// which do not reference a specific memory location should be less than
/// this value. Those that do must not be less than this value, and can
/// be used with SelectionDAG::getMemIntrinsicNode.
static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+100;
static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+150;
//===--------------------------------------------------------------------===//
/// MemIndexedMode enum - This enum defines the load / store indexed

View File

@ -8093,6 +8093,41 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM";
case X86ISD::PTEST: return "X86ISD::PTEST";
case X86ISD::TESTP: return "X86ISD::TESTP";
case X86ISD::PALIGN: return "X86ISD::PALIGN";
case X86ISD::PSHUFD: return "X86ISD::PSHUFD";
case X86ISD::PSHUFHW: return "X86ISD::PSHUFHW";
case X86ISD::PSHUFHW_LD: return "X86ISD::PSHUFHW_LD";
case X86ISD::PSHUFLW: return "X86ISD::PSHUFLW";
case X86ISD::PSHUFLW_LD: return "X86ISD::PSHUFLW_LD";
case X86ISD::SHUFPS: return "X86ISD::SHUFPS";
case X86ISD::SHUFPD: return "X86ISD::SHUFPD";
case X86ISD::MOVLHPS: return "X86ISD::MOVLHPS";
case X86ISD::MOVHLPS: return "X86ISD::MOVHLPS";
case X86ISD::MOVLHPD: return "X86ISD::MOVLHPD";
case X86ISD::MOVHLPD: return "X86ISD::MOVHLPD";
case X86ISD::MOVHPS: return "X86ISD::MOVHPS";
case X86ISD::MOVLPS: return "X86ISD::MOVLPS";
case X86ISD::MOVHPD: return "X86ISD::MOVHPD";
case X86ISD::MOVLPD: return "X86ISD::MOVLPD";
case X86ISD::MOVDDUP: return "X86ISD::MOVDDUP";
case X86ISD::MOVSHDUP: return "X86ISD::MOVSHDUP";
case X86ISD::MOVSLDUP: return "X86ISD::MOVSLDUP";
case X86ISD::MOVSHDUP_LD: return "X86ISD::MOVSHDUP_LD";
case X86ISD::MOVSLDUP_LD: return "X86ISD::MOVSLDUP_LD";
case X86ISD::MOVSD: return "X86ISD::MOVSD";
case X86ISD::MOVSS: return "X86ISD::MOVSS";
case X86ISD::UNPCKLPS: return "X86ISD::UNPCKLPS";
case X86ISD::UNPCKLPD: return "X86ISD::UNPCKLPD";
case X86ISD::UNPCKHPS: return "X86ISD::UNPCKHPS";
case X86ISD::UNPCKHPD: return "X86ISD::UNPCKHPD";
case X86ISD::PUNPCKLBW: return "X86ISD::PUNPCKLBW";
case X86ISD::PUNPCKLWD: return "X86ISD::PUNPCKLWD";
case X86ISD::PUNPCKLDQ: return "X86ISD::PUNPCKLDQ";
case X86ISD::PUNPCKLQDQ: return "X86ISD::PUNPCKLQDQ";
case X86ISD::PUNPCKHBW: return "X86ISD::PUNPCKHBW";
case X86ISD::PUNPCKHWD: return "X86ISD::PUNPCKHWD";
case X86ISD::PUNPCKHDQ: return "X86ISD::PUNPCKHDQ";
case X86ISD::PUNPCKHQDQ: return "X86ISD::PUNPCKHQDQ";
case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS";
case X86ISD::MINGW_ALLOCA: return "X86ISD::MINGW_ALLOCA";
}

View File

@ -251,6 +251,43 @@ namespace llvm {
// TESTP - Vector packed fp sign bitwise comparisons
TESTP,
// Several flavors of instructions with vector shuffle behaviors.
PALIGN,
PSHUFD,
PSHUFHW,
PSHUFLW,
PSHUFHW_LD,
PSHUFLW_LD,
SHUFPD,
SHUFPS,
MOVDDUP,
MOVSHDUP,
MOVSLDUP,
MOVSHDUP_LD,
MOVSLDUP_LD,
MOVLHPS,
MOVHLPS,
MOVLHPD,
MOVHLPD,
MOVHPS,
MOVHPD,
MOVLPS,
MOVLPD,
MOVSD,
MOVSS,
UNPCKLPS,
UNPCKLPD,
UNPCKHPS,
UNPCKHPD,
PUNPCKLBW,
PUNPCKLWD,
PUNPCKLDQ,
PUNPCKLQDQ,
PUNPCKHBW,
PUNPCKHWD,
PUNPCKHDQ,
PUNPCKHQDQ,
// VASTART_SAVE_XMM_REGS - Save xmm argument registers to the stack,
// according to %al. An operator is needed so that this can be expanded
// with control flow.

View File

@ -122,6 +122,78 @@ def SDTX86CmpPTest : SDTypeProfile<1, 2, [SDTCisVT<0, i32>,
def X86ptest : SDNode<"X86ISD::PTEST", SDTX86CmpPTest>;
def X86testp : SDNode<"X86ISD::TESTP", SDTX86CmpPTest>;
// Specific shuffle nodes - At some point ISD::VECTOR_SHUFFLE will always get
// translated into one of the target nodes below during lowering.
// Note: this is a work in progress...
def SDTShuff1Op : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0,1>]>;
def SDTShuff2Op : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>]>;
def SDTShuff2OpI : SDTypeProfile<1, 2, [SDTCisVec<0>,
SDTCisSameAs<0,1>, SDTCisInt<2>]>;
def SDTShuff3OpI : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0,1>,
SDTCisSameAs<0,2>, SDTCisInt<3>]>;
def SDTShuff1OpLd : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisPtrTy<1>]>;
def SDTShuff2OpLd : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0,1>,
SDTCisPtrTy<2>]>;
def SDTShuff2OpLdI : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisPtrTy<1>,
SDTCisInt<2>]>;
def X86PAlign : SDNode<"X86ISD::PALIGN", SDTShuff3OpI>;
def X86PShufd : SDNode<"X86ISD::PSHUFD", SDTShuff2OpI>;
def X86PShufhw : SDNode<"X86ISD::PSHUFHW", SDTShuff2OpI>;
def X86PShuflw : SDNode<"X86ISD::PSHUFLW", SDTShuff2OpI>;
def X86PShufhwLd : SDNode<"X86ISD::PSHUFHW_LD", SDTShuff2OpLdI>;
def X86PShuflwLd : SDNode<"X86ISD::PSHUFLW_LD", SDTShuff2OpLdI>;
def X86Shufpd : SDNode<"X86ISD::SHUFPD", SDTShuff3OpI>;
def X86Shufps : SDNode<"X86ISD::SHUFPS", SDTShuff3OpI>;
def X86Movddup : SDNode<"X86ISD::MOVDDUP", SDTShuff1Op>;
def X86Movshdup : SDNode<"X86ISD::MOVSHDUP", SDTShuff1Op>;
def X86Movsldup : SDNode<"X86ISD::MOVSLDUP", SDTShuff1Op>;
def X86MovshdupLd : SDNode<"X86ISD::MOVSHDUP_LD", SDTShuff1OpLd,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def X86MovsldupLd : SDNode<"X86ISD::MOVSLDUP_LD", SDTShuff1OpLd,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def X86Movsd : SDNode<"X86ISD::MOVSD", SDTShuff2Op>;
def X86Movss : SDNode<"X86ISD::MOVSS", SDTShuff2Op>;
def X86Movlhps : SDNode<"X86ISD::MOVLHPS", SDTShuff2Op>;
def X86Movhlps : SDNode<"X86ISD::MOVHLPS", SDTShuff2Op>;
def X86Movlhpd : SDNode<"X86ISD::MOVLHPD", SDTShuff2Op>;
def X86Movhlpd : SDNode<"X86ISD::MOVHLPD", SDTShuff2Op>;
def X86MovhpsLd : SDNode<"X86ISD::MOVHPS", SDTShuff2OpLd,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def X86MovhpdLd : SDNode<"X86ISD::MOVHPD", SDTShuff2OpLd,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def X86MovlpsLd : SDNode<"X86ISD::MOVLPS", SDTShuff2OpLd,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def X86MovlpdLd : SDNode<"X86ISD::MOVLPD", SDTShuff2OpLd,
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
def X86Unpcklps : SDNode<"X86ISD::UNPCKLPS", SDTShuff2Op>;
def X86Unpcklpd : SDNode<"X86ISD::UNPCKLPD", SDTShuff2Op>;
def X86Unpckhps : SDNode<"X86ISD::UNPCKHPS", SDTShuff2Op>;
def X86Unpckhpd : SDNode<"X86ISD::UNPCKHPD", SDTShuff2Op>;
def X86Punpcklbw : SDNode<"X86ISD::PUNPCKLBW", SDTShuff2Op>;
def X86Punpcklwd : SDNode<"X86ISD::PUNPCKLWD", SDTShuff2Op>;
def X86Punpckldq : SDNode<"X86ISD::PUNPCKLDQ", SDTShuff2Op>;
def X86Punpcklqdq : SDNode<"X86ISD::PUNPCKLQDQ", SDTShuff2Op>;
def X86Punpckhbw : SDNode<"X86ISD::PUNPCKHBW", SDTShuff2Op>;
def X86Punpckhwd : SDNode<"X86ISD::PUNPCKHWD", SDTShuff2Op>;
def X86Punpckhdq : SDNode<"X86ISD::PUNPCKHDQ", SDTShuff2Op>;
def X86Punpckhqdq : SDNode<"X86ISD::PUNPCKHQDQ", SDTShuff2Op>;
//===----------------------------------------------------------------------===//
// SSE Complex Patterns
//===----------------------------------------------------------------------===//

View File

@ -5585,3 +5585,352 @@ def : Pat<(int_x86_avx_vperm2f128_si_256
VR256:$src1, (memopv8i32 addr:$src2), imm:$src3),
(VPERM2F128rm VR256:$src1, addr:$src2, imm:$src3)>;
//===----------------------------------------------------------------------===//
// SSE Shuffle pattern fragments
//===----------------------------------------------------------------------===//
// This is part of a "work in progress" refactoring. The idea is that all
// vector shuffles are going to be translated into target specific nodes and
// directly matched by the patterns below (which can be changed along the way)
// The AVX version of some but not all of them are described here, and more
// should come in a near future.
// Shuffle with PSHUFD instruction folding loads. The first two patterns match
// SSE2 loads, which are always promoted to v2i64. The last one should match
// the SSE1 case, where the only legal load is v4f32, but there is no PSHUFD
// in SSE2, how does it ever worked? Anyway, the pattern will remain here until
// we investigate further.
def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv2i64 addr:$src1)),
(i8 imm:$imm))),
(VPSHUFDmi addr:$src1, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv2i64 addr:$src1)),
(i8 imm:$imm))),
(PSHUFDmi addr:$src1, imm:$imm)>;
def : Pat<(v4i32 (X86PShufd (bc_v4i32 (memopv4f32 addr:$src1)),
(i8 imm:$imm))),
(PSHUFDmi addr:$src1, imm:$imm)>; // FIXME: has this ever worked?
// Shuffle with PSHUFD instruction.
def : Pat<(v4f32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
(VPSHUFDri VR128:$src1, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
(PSHUFDri VR128:$src1, imm:$imm)>;
def : Pat<(v4i32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
(VPSHUFDri VR128:$src1, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4i32 (X86PShufd VR128:$src1, (i8 imm:$imm))),
(PSHUFDri VR128:$src1, imm:$imm)>;
// Shuffle with SHUFPD instruction.
def : Pat<(v2f64 (X86Shufps VR128:$src1,
(memopv2f64 addr:$src2), (i8 imm:$imm))),
(VSHUFPDrmi VR128:$src1, addr:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v2f64 (X86Shufps VR128:$src1,
(memopv2f64 addr:$src2), (i8 imm:$imm))),
(SHUFPDrmi VR128:$src1, addr:$src2, imm:$imm)>;
def : Pat<(v2i64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(VSHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v2i64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(SHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
def : Pat<(v2f64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(VSHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v2f64 (X86Shufpd VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(SHUFPDrri VR128:$src1, VR128:$src2, imm:$imm)>;
// Shuffle with SHUFPS instruction.
def : Pat<(v4f32 (X86Shufps VR128:$src1,
(memopv4f32 addr:$src2), (i8 imm:$imm))),
(VSHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Shufps VR128:$src1,
(memopv4f32 addr:$src2), (i8 imm:$imm))),
(SHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
def : Pat<(v4f32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(VSHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(SHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
def : Pat<(v4i32 (X86Shufps VR128:$src1,
(bc_v4i32 (memopv2i64 addr:$src2)), (i8 imm:$imm))),
(VSHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4i32 (X86Shufps VR128:$src1,
(bc_v4i32 (memopv2i64 addr:$src2)), (i8 imm:$imm))),
(SHUFPSrmi VR128:$src1, addr:$src2, imm:$imm)>;
def : Pat<(v4i32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(VSHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>, Requires<[HasAVX]>;
def : Pat<(v4i32 (X86Shufps VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(SHUFPSrri VR128:$src1, VR128:$src2, imm:$imm)>;
// Shuffle with MOVLHPS instruction
def : Pat<(v4f32 (X86Movlhps VR128:$src1, VR128:$src2)),
(VMOVLHPSrr (v4f32 VR128:$src1), VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Movlhps VR128:$src1, VR128:$src2)),
(MOVLHPSrr (v4f32 VR128:$src1), VR128:$src2)>;
def : Pat<(v2i64 (X86Movlhps VR128:$src1, VR128:$src2)),
(VMOVLHPSrr (v2i64 VR128:$src1), VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v2i64 (X86Movlhps VR128:$src1, VR128:$src2)),
(MOVLHPSrr (v2i64 VR128:$src1), VR128:$src2)>;
def : Pat<(v4i32 (X86Movlhps VR128:$src1, VR128:$src2)),
(VMOVLHPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v4i32 (X86Movlhps VR128:$src1, VR128:$src2)),
(MOVLHPSrr VR128:$src1, VR128:$src2)>;
// Shuffle with MOVHLPS instruction
def : Pat<(v4f32 (X86Movhlps VR128:$src1, VR128:$src2)),
(MOVHLPSrr VR128:$src1, VR128:$src2)>;
def : Pat<(v4i32 (X86Movhlps VR128:$src1, VR128:$src2)),
(MOVHLPSrr VR128:$src1, VR128:$src2)>;
// Shuffle with MOVDDUP instruction
def : Pat<(X86Movddup (memopv2f64 addr:$src)),
(VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
def : Pat<(X86Movddup (memopv2f64 addr:$src)),
(MOVDDUPrm addr:$src)>;
def : Pat<(X86Movddup (bc_v4f32 (memopv2f64 addr:$src))),
(VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
def : Pat<(X86Movddup (bc_v4f32 (memopv2f64 addr:$src))),
(MOVDDUPrm addr:$src)>;
def : Pat<(X86Movddup (memopv2i64 addr:$src)),
(VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
def : Pat<(X86Movddup (memopv2i64 addr:$src)),
(MOVDDUPrm addr:$src)>;
def : Pat<(X86Movddup (bc_v4i32 (memopv2i64 addr:$src))),
(VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
def : Pat<(X86Movddup (bc_v4i32 (memopv2i64 addr:$src))),
(MOVDDUPrm addr:$src)>;
def : Pat<(X86Movddup (v2f64 (scalar_to_vector (loadf64 addr:$src)))),
(VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
def : Pat<(X86Movddup (v2f64 (scalar_to_vector (loadf64 addr:$src)))),
(MOVDDUPrm addr:$src)>;
def : Pat<(X86Movddup (bc_v2f64
(v2i64 (scalar_to_vector (loadi64 addr:$src))))),
(VMOVDDUPrm addr:$src)>, Requires<[HasAVX]>;
def : Pat<(X86Movddup (bc_v2f64
(v2i64 (scalar_to_vector (loadi64 addr:$src))))),
(MOVDDUPrm addr:$src)>;
// Shuffle with UNPCKLPS
def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))),
(VUNPCKLPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))),
(UNPCKLPSrm VR128:$src1, addr:$src2)>;
def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)),
(VUNPCKLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)),
(UNPCKLPSrr VR128:$src1, VR128:$src2)>;
// Shuffle with UNPCKHPS
def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))),
(VUNPCKHPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))),
(UNPCKHPSrm VR128:$src1, addr:$src2)>;
def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
(VUNPCKHPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v4f32 (X86Unpckhps VR128:$src1, VR128:$src2)),
(UNPCKHPSrr VR128:$src1, VR128:$src2)>;
// Shuffle with UNPCKLPD
def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
(VUNPCKLPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))),
(UNPCKLPSrm VR128:$src1, addr:$src2)>;
def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)),
(VUNPCKLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)),
(UNPCKLPDrr VR128:$src1, VR128:$src2)>;
// Shuffle with UNPCKHPD
def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))),
(VUNPCKLPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>;
def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))),
(UNPCKLPSrm VR128:$src1, addr:$src2)>;
def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
(VUNPCKHPDrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>;
def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, VR128:$src2)),
(UNPCKHPDrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKLBW
def : Pat<(v16i8 (X86Punpcklbw VR128:$src1,
(bc_v16i8 (memopv2i64 addr:$src2)))),
(PUNPCKLBWrm VR128:$src1, addr:$src2)>;
def : Pat<(v16i8 (X86Punpcklbw VR128:$src1, VR128:$src2)),
(PUNPCKLBWrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKLWD
def : Pat<(v8i16 (X86Punpcklwd VR128:$src1,
(bc_v8i16 (memopv2i64 addr:$src2)))),
(PUNPCKLWDrm VR128:$src1, addr:$src2)>;
def : Pat<(v8i16 (X86Punpcklwd VR128:$src1, VR128:$src2)),
(PUNPCKLWDrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKLDQ
def : Pat<(v4i32 (X86Punpckldq VR128:$src1,
(bc_v4i32 (memopv2i64 addr:$src2)))),
(PUNPCKLDQrm VR128:$src1, addr:$src2)>;
def : Pat<(v4i32 (X86Punpckldq VR128:$src1, VR128:$src2)),
(PUNPCKLDQrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKLQDQ
def : Pat<(v2i64 (X86Punpcklqdq VR128:$src1, (memopv2i64 addr:$src2))),
(PUNPCKLQDQrm VR128:$src1, addr:$src2)>;
def : Pat<(v2i64 (X86Punpcklqdq VR128:$src1, VR128:$src2)),
(PUNPCKLQDQrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKHBW
def : Pat<(v16i8 (X86Punpckhbw VR128:$src1,
(bc_v16i8 (memopv2i64 addr:$src2)))),
(PUNPCKHBWrm VR128:$src1, addr:$src2)>;
def : Pat<(v16i8 (X86Punpckhbw VR128:$src1, VR128:$src2)),
(PUNPCKHBWrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKHWD
def : Pat<(v8i16 (X86Punpckhwd VR128:$src1,
(bc_v8i16 (memopv2i64 addr:$src2)))),
(PUNPCKHWDrm VR128:$src1, addr:$src2)>;
def : Pat<(v8i16 (X86Punpckhwd VR128:$src1, VR128:$src2)),
(PUNPCKHWDrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKHDQ
def : Pat<(v4i32 (X86Punpckhdq VR128:$src1,
(bc_v4i32 (memopv2i64 addr:$src2)))),
(PUNPCKHDQrm VR128:$src1, addr:$src2)>;
def : Pat<(v4i32 (X86Punpckhdq VR128:$src1, VR128:$src2)),
(PUNPCKHDQrr VR128:$src1, VR128:$src2)>;
// Shuffle with PUNPCKHQDQ
def : Pat<(v2i64 (X86Punpckhqdq VR128:$src1, (memopv2i64 addr:$src2))),
(PUNPCKHQDQrm VR128:$src1, addr:$src2)>;
def : Pat<(v2i64 (X86Punpckhqdq VR128:$src1, VR128:$src2)),
(PUNPCKHQDQrr VR128:$src1, VR128:$src2)>;
// Shuffle with MOVHPS
def : Pat<(v4f32 (X86MovhpsLd VR128:$src1, addr:$src2)),
(MOVHPSrm VR128:$src1, addr:$src2)>;
def : Pat<(v4i32 (X86MovhpsLd VR128:$src1, addr:$src2)),
(MOVHPSrm VR128:$src1, addr:$src2)>;
// Shuffle with MOVHPD
def : Pat<(v2f64 (X86MovhpdLd VR128:$src1, addr:$src2)),
(MOVHPDrm VR128:$src1, addr:$src2)>;
// Shuffle with MOVLPS
def : Pat<(v4f32 (X86MovlpsLd VR128:$src1, addr:$src2)),
(MOVLPSrm VR128:$src1, addr:$src2)>;
def : Pat<(v4i32 (X86MovlpsLd VR128:$src1, addr:$src2)),
(MOVLPSrm VR128:$src1, addr:$src2)>;
// Shuffle with MOVLPD
def : Pat<(v2f64 (X86MovlpdLd VR128:$src1, addr:$src2)),
(MOVLPDrm VR128:$src1, addr:$src2)>;
def : Pat<(v2i64 (X86MovlpdLd VR128:$src1, addr:$src2)),
(MOVLPDrm VR128:$src1, addr:$src2)>;
// Shuffle with MOVSS
def : Pat<(v4f32 (X86Movss VR128:$src1, (scalar_to_vector FR32:$src2))),
(MOVSSrr VR128:$src1, FR32:$src2)>;
def : Pat<(v4i32 (X86Movss VR128:$src1, VR128:$src2)),
(MOVSSrr (v4i32 VR128:$src1),
(EXTRACT_SUBREG (v4i32 VR128:$src2), sub_ss))>;
def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)),
(MOVSSrr (v4f32 VR128:$src1),
(EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>;
// Shuffle with MOVSD
def : Pat<(v2f64 (X86Movsd VR128:$src1, (scalar_to_vector FR64:$src2))),
(MOVSDrr VR128:$src1, FR64:$src2)>;
def : Pat<(v2i64 (X86Movsd VR128:$src1, VR128:$src2)),
(MOVSDrr (v2i64 VR128:$src1),
(EXTRACT_SUBREG (v2i64 VR128:$src2), sub_sd))>;
def : Pat<(v2f64 (X86Movsd VR128:$src1, VR128:$src2)),
(MOVSDrr (v2f64 VR128:$src1),
(EXTRACT_SUBREG (v2f64 VR128:$src2), sub_sd))>;
def : Pat<(v4f32 (X86Movsd VR128:$src1, VR128:$src2)),
(MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>;
def : Pat<(v4i32 (X86Movsd VR128:$src1, VR128:$src2)),
(MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, sub_sd))>;
// Shuffle with MOVSHDUP
def : Pat<(v4i32 (X86Movshdup VR128:$src)),
(MOVSHDUPrr VR128:$src)>;
def : Pat<(v4i32 (X86MovshdupLd addr:$src)),
(MOVSHDUPrm addr:$src)>;
def : Pat<(v4f32 (X86Movshdup VR128:$src)),
(MOVSHDUPrr VR128:$src)>;
def : Pat<(v4f32 (X86MovshdupLd addr:$src)),
(MOVSHDUPrm addr:$src)>;
// Shuffle with MOVSLDUP
def : Pat<(v4i32 (X86Movsldup VR128:$src)),
(MOVSLDUPrr VR128:$src)>;
def : Pat<(v4i32 (X86MovsldupLd addr:$src)),
(MOVSLDUPrm addr:$src)>;
def : Pat<(v4f32 (X86Movsldup VR128:$src)),
(MOVSLDUPrr VR128:$src)>;
def : Pat<(v4f32 (X86MovsldupLd addr:$src)),
(MOVSLDUPrm addr:$src)>;
// Shuffle with PSHUFHW
def : Pat<(v8i16 (X86PShufhwLd addr:$src, (i8 imm:$imm))),
(PSHUFHWmi addr:$src, imm:$imm)>;
def : Pat<(v8i16 (X86PShufhw VR128:$src, (i8 imm:$imm))),
(PSHUFHWri VR128:$src, imm:$imm)>;
// Shuffle with PSHUFLW
def : Pat<(v8i16 (X86PShuflwLd addr:$src, (i8 imm:$imm))),
(PSHUFLWmi addr:$src, imm:$imm)>;
def : Pat<(v8i16 (X86PShuflw VR128:$src, (i8 imm:$imm))),
(PSHUFLWri VR128:$src, imm:$imm)>;
// Shuffle with PALIGN
def : Pat<(v1i64 (X86PAlign VR64:$src1, VR64:$src2, (i8 imm:$imm))),
(PALIGNR64rr VR64:$src2, VR64:$src1, imm:$imm)>;
def : Pat<(v2i32 (X86PAlign VR64:$src1, VR64:$src2, (i8 imm:$imm))),
(PALIGNR64rr VR64:$src2, VR64:$src1, imm:$imm)>;
def : Pat<(v4i16 (X86PAlign VR64:$src1, VR64:$src2, (i8 imm:$imm))),
(PALIGNR64rr VR64:$src2, VR64:$src1, imm:$imm)>;
def : Pat<(v8i8 (X86PAlign VR64:$src1, VR64:$src2, (i8 imm:$imm))),
(PALIGNR64rr VR64:$src2, VR64:$src1, imm:$imm)>;
def : Pat<(v4i32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
def : Pat<(v4f32 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
def : Pat<(v8i16 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
def : Pat<(v16i8 (X86PAlign VR128:$src1, VR128:$src2, (i8 imm:$imm))),
(PALIGNR128rr VR128:$src2, VR128:$src1, imm:$imm)>;
// Extra patterns to match stores
def : Pat<(store (f64 (vector_extract
(v2f64 (X86Unpckhps VR128:$src, (undef))), (iPTR 0))),addr:$dst),
(MOVHPSmr addr:$dst, VR128:$src)>;
def : Pat<(store (f64 (vector_extract
(v2f64 (X86Unpckhpd VR128:$src, (undef))), (iPTR 0))),addr:$dst),
(MOVHPDmr addr:$dst, VR128:$src)>;
def : Pat<(store (v2f64 (X86MovlpdLd VR128:$src1, addr:$src2)),addr:$src2),
(MOVLPDmr addr:$src2, VR128:$src1)>;
def : Pat<(store (v2i64 (X86MovlpdLd VR128:$src1, addr:$src2)),addr:$src2),
(MOVLPDmr addr:$src2, VR128:$src1)>;
def : Pat<(store (v4f32 (X86MovlpsLd VR128:$src1, addr:$src2)),addr:$src2),
(MOVLPSmr addr:$src2, VR128:$src1)>;
def : Pat<(store (v4i32 (X86MovlpsLd VR128:$src1, addr:$src2)),addr:$src2),
(MOVLPSmr addr:$src2, VR128:$src1)>;