From 2b2a7013c4f12c078f826e0dd6289c3d2a175a9b Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 23 May 2008 21:23:16 +0000 Subject: Use movlps / movhps to modify low / high half of 16-byet memory location. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51501 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/README-SSE.txt | 40 ---------------------------- lib/Target/X86/X86ISelDAGToDAG.cpp | 54 ++++++++++++++++++++++++-------------- lib/Target/X86/X86InstrSSE.td | 37 ++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 62 deletions(-) (limited to 'lib/Target') diff --git a/lib/Target/X86/README-SSE.txt b/lib/Target/X86/README-SSE.txt index 1f5f203..58b4384 100644 --- a/lib/Target/X86/README-SSE.txt +++ b/lib/Target/X86/README-SSE.txt @@ -505,46 +505,6 @@ nodes which are selected to max / min instructions that are marked commutable. //===---------------------------------------------------------------------===// -We should compile this: -#include -typedef union { - int i[4]; - float f[4]; - __m128 v; -} vector4_t; -void swizzle (const void *a, vector4_t * b, vector4_t * c) { - b->v = _mm_loadl_pi (b->v, (__m64 *) a); - c->v = _mm_loadl_pi (c->v, ((__m64 *) a) + 1); -} - -to: - -_swizzle: - movl 4(%esp), %eax - movl 8(%esp), %edx - movl 12(%esp), %ecx - movlps (%eax), %xmm0 - movlps %xmm0, (%edx) - movlps 8(%eax), %xmm0 - movlps %xmm0, (%ecx) - ret - -not: - -swizzle: - movl 8(%esp), %eax - movaps (%eax), %xmm0 - movl 4(%esp), %ecx - movlps (%ecx), %xmm0 - movaps %xmm0, (%eax) - movl 12(%esp), %eax - movaps (%eax), %xmm0 - movlps 8(%ecx), %xmm0 - movaps %xmm0, (%eax) - ret - -//===---------------------------------------------------------------------===// - We should materialize vector constants like "all ones" and "signbit" with code like: diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index c92e769..576661d 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -363,6 +363,32 @@ static void MoveBelowTokenFactor(SelectionDAG &DAG, SDOperand Load, Store.getOperand(2), Store.getOperand(3)); } +/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. +/// +static bool isRMWLoad(SDOperand N, SDOperand Chain, SDOperand Address, + SDOperand &Load) { + if (N.getOpcode() == ISD::BIT_CONVERT) + N = N.getOperand(0); + + LoadSDNode *LD = dyn_cast(N); + if (!LD || LD->isVolatile()) + return false; + if (LD->getAddressingMode() != ISD::UNINDEXED) + return false; + + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD) + return false; + + if (N.hasOneUse() && + N.getOperand(1) == Address && + N.Val->isOperandOf(Chain.Val)) { + Load = N; + return true; + } + return false; +} + /// PreprocessForRMW - Preprocess the DAG to make instruction selection better. /// This is only run if not in -fast mode (aka -O0). /// This allows the instruction selector to pick more read-modify-write @@ -414,8 +440,8 @@ void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) { SDOperand N1 = I->getOperand(1); SDOperand N2 = I->getOperand(2); - if (MVT::isFloatingPoint(N1.getValueType()) || - MVT::isVector(N1.getValueType()) || + if ((MVT::isFloatingPoint(N1.getValueType()) && + !MVT::isVector(N1.getValueType())) || !N1.hasOneUse()) continue; @@ -429,20 +455,13 @@ void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) { case ISD::OR: case ISD::XOR: case ISD::ADDC: - case ISD::ADDE: { + case ISD::ADDE: + case ISD::VECTOR_SHUFFLE: { SDOperand N10 = N1.getOperand(0); SDOperand N11 = N1.getOperand(1); - if (ISD::isNON_EXTLoad(N10.Val)) - RModW = true; - else if (ISD::isNON_EXTLoad(N11.Val)) { - RModW = true; - std::swap(N10, N11); - } - RModW = RModW && N10.Val->isOperandOf(Chain.Val) && N10.hasOneUse() && - (N10.getOperand(1) == N2) && - (N10.Val->getValueType(0) == N1.getValueType()); - if (RModW) - Load = N10; + RModW = isRMWLoad(N10, Chain, N2, Load); + if (!RModW) + RModW = isRMWLoad(N11, Chain, N2, Load); break; } case ISD::SUB: @@ -456,12 +475,7 @@ void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) { case X86ISD::SHLD: case X86ISD::SHRD: { SDOperand N10 = N1.getOperand(0); - if (ISD::isNON_EXTLoad(N10.Val)) - RModW = N10.Val->isOperandOf(Chain.Val) && N10.hasOneUse() && - (N10.getOperand(1) == N2) && - (N10.Val->getValueType(0) == N1.getValueType()); - if (RModW) - Load = N10; + RModW = isRMWLoad(N10, Chain, N2, Load); break; } } diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index e9c6481..06b7a3a 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -2977,13 +2977,15 @@ def : Pat<(v2f64 (vector_shuffle VR128:$src1, (memop addr:$src2), MOVHP_shuffle_mask)), (MOVHPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, (bc_v4i32 (memopv2i64 addr:$src2)), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2)), MOVLP_shuffle_mask)), (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; def : Pat<(v2i64 (vector_shuffle VR128:$src1, (memop addr:$src2), MOVLP_shuffle_mask)), (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; -def : Pat<(v4i32 (vector_shuffle VR128:$src1, (bc_v4i32 (memopv2i64 addr:$src2)), +def : Pat<(v4i32 (vector_shuffle VR128:$src1, + (bc_v4i32 (memopv2i64 addr:$src2)), MOVHP_shuffle_mask)), (MOVHPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; def : Pat<(v2i64 (vector_shuffle VR128:$src1, (memop addr:$src2), @@ -2991,6 +2993,37 @@ def : Pat<(v2i64 (vector_shuffle VR128:$src1, (memop addr:$src2), (MOVHPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; } +// (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS +// (store (vector_shuffle (load addr), v2, <0, 1, 4, 5>), addr) using MOVHPS +def : Pat<(store (v4f32 (vector_shuffle (memop addr:$src1), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), + (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; +def : Pat<(store (v2f64 (vector_shuffle (memop addr:$src1), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), + (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(store (v4f32 (vector_shuffle (memop addr:$src1), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), + (MOVHPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; +def : Pat<(store (v2f64 (vector_shuffle (memop addr:$src1), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), + (MOVHPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + +def : Pat<(store (v4i32 (vector_shuffle + (bc_v4i32 (memopv2i64 addr:$src1)), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), + (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; +def : Pat<(store (v2i64 (vector_shuffle (memop addr:$src1), VR128:$src2, + MOVLP_shuffle_mask)), addr:$src1), + (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; +def : Pat<(store (v4i32 (vector_shuffle + (bc_v4i32 (memopv2i64 addr:$src1)), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), + (MOVHPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; +def : Pat<(store (v2i64 (vector_shuffle (memop addr:$src1), VR128:$src2, + MOVHP_shuffle_mask)), addr:$src1), + (MOVHPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + + let AddedComplexity = 15 in { // Setting the lowest element in the vector. def : Pat<(v4i32 (vector_shuffle VR128:$src1, VR128:$src2, -- cgit v1.1