summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Greene <greened@obbligato.org>2011-02-10 16:57:36 +0000
committerDavid Greene <greened@obbligato.org>2011-02-10 16:57:36 +0000
commit74a579d9eb1c822f6dd4689671f9ea100666fa03 (patch)
tree8801374e41478e539054fe4fcc92012aeda8a06c /lib
parent8e5d01cd6efa99a26c8584711a7e8abbcf14c333 (diff)
downloadllvm-74a579d9eb1c822f6dd4689671f9ea100666fa03.tar.gz
llvm-74a579d9eb1c822f6dd4689671f9ea100666fa03.tar.bz2
llvm-74a579d9eb1c822f6dd4689671f9ea100666fa03.tar.xz
[AVX] Implement 256-bit vector lowering for EXTRACT_VECTOR_ELT.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125284 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp36
1 files changed, 35 insertions, 1 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index ea7eef7320..fff006e3b8 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -80,7 +80,9 @@ static SDValue ConcatVectors(SDValue Lower, SDValue Upper, SelectionDAG &DAG);
/// Generate a DAG to grab 128-bits from a vector > 128 bits. This
/// sets things up to match to an AVX VEXTRACTF128 instruction or a
-/// simple subregister reference.
+/// simple subregister reference. Idx is an index in the 128 bits we
+/// want. It need not be aligned to a 128-bit bounday. That makes
+/// lowering EXTRACT_VECTOR_ELT operations easier.
static SDValue Extract128BitVector(SDValue Vec,
SDValue Idx,
SelectionDAG &DAG,
@@ -5917,6 +5919,38 @@ X86TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
if (!isa<ConstantSDNode>(Op.getOperand(1)))
return SDValue();
+ SDValue Vec = Op.getOperand(0);
+ EVT VecVT = Vec.getValueType();
+
+ // If this is a 256-bit vector result, first extract the 128-bit
+ // vector and then extract from the 128-bit vector.
+ if (VecVT.getSizeInBits() > 128) {
+ DebugLoc dl = Op.getNode()->getDebugLoc();
+ unsigned NumElems = VecVT.getVectorNumElements();
+ SDValue Idx = Op.getOperand(1);
+
+ if (!isa<ConstantSDNode>(Idx))
+ return SDValue();
+
+ unsigned ExtractNumElems = NumElems / (VecVT.getSizeInBits() / 128);
+ unsigned IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
+
+ // Get the 128-bit vector.
+ bool Upper = IdxVal >= ExtractNumElems;
+ Vec = Extract128BitVector(Vec, Idx, DAG, dl);
+
+ // Extract from it.
+ SDValue ScaledIdx = Idx;
+ if (Upper)
+ ScaledIdx = DAG.getNode(ISD::SUB, dl, Idx.getValueType(), Idx,
+ DAG.getConstant(ExtractNumElems,
+ Idx.getValueType()));
+ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, Op.getValueType(), Vec,
+ ScaledIdx);
+ }
+
+ assert(Vec.getValueSizeInBits() <= 128 && "Unexpected vector length");
+
if (Subtarget->hasSSE41()) {
SDValue Res = LowerEXTRACT_VECTOR_ELT_SSE4(Op, DAG);
if (Res.getNode())