aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2006-03-31 19:22:53 +0000
committerEvan Cheng <evan.cheng@apple.com>2006-03-31 19:22:53 +0000
commitb067a1e7e68c4446d3512c25d3a5ac55c6dd76f8 (patch)
treead866ba2225e13fe93e926893cd5487c4d85ec6b
parent1eda6e79249d2e5b8ff0593feeb623d2a0a7f237 (diff)
Add support to use pextrw and pinsrw to extract and insert a word element
from a 128-bit vector. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27304 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp38
-rw-r--r--lib/Target/X86/X86ISelLowering.h4
-rw-r--r--lib/Target/X86/X86InstrSSE.td31
3 files changed, 69 insertions, 4 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 8036066d0f..cfc6af84ca 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -255,9 +255,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
setOperationAction(ISD::SUB , (MVT::ValueType)VT, Expand);
setOperationAction(ISD::MUL , (MVT::ValueType)VT, Expand);
setOperationAction(ISD::LOAD, (MVT::ValueType)VT, Expand);
- setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Expand);
+ setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Expand);
setOperationAction(ISD::EXTRACT_VECTOR_ELT, (MVT::ValueType)VT, Expand);
- setOperationAction(ISD::INSERT_VECTOR_ELT, (MVT::ValueType)VT, Expand);
+ setOperationAction(ISD::INSERT_VECTOR_ELT, (MVT::ValueType)VT, Expand);
}
if (Subtarget->hasMMX()) {
@@ -316,6 +316,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8i16, Custom);
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i32, Custom);
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2i64, Custom);
+ setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v8i16, Custom);
+ setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v8i16, Custom);
}
computeRegisterProperties();
@@ -2657,6 +2659,37 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
return SDOperand();
}
+ case ISD::EXTRACT_VECTOR_ELT: {
+ // Transform it so it match pextrw which produces a 32-bit result.
+ MVT::ValueType VT = Op.getValueType();
+ if (MVT::getSizeInBits(VT) == 16) {
+ MVT::ValueType EVT = (MVT::ValueType)(VT+1);
+ SDOperand Extract = DAG.getNode(X86ISD::PEXTRW, EVT,
+ Op.getOperand(0), Op.getOperand(1));
+ SDOperand Assert = DAG.getNode(ISD::AssertZext, EVT, Extract,
+ DAG.getValueType(VT));
+ return DAG.getNode(ISD::TRUNCATE, VT, Assert);
+ }
+
+ return SDOperand();
+ }
+ case ISD::INSERT_VECTOR_ELT: {
+ // Transform it so it match pinsrw which expects a 16-bit value in a R32
+ // as its second argument.
+ MVT::ValueType VT = Op.getValueType();
+ MVT::ValueType BaseVT = MVT::getVectorBaseType(VT);
+ if (MVT::getSizeInBits(BaseVT) == 16) {
+ SDOperand N1 = Op.getOperand(1);
+ SDOperand N2 = Op.getOperand(2);
+ if (N1.getValueType() != MVT::i32)
+ N1 = DAG.getNode(ISD::ANY_EXTEND, MVT::i32, N1);
+ if (N2.getValueType() != MVT::i32)
+ N2 = DAG.getConstant(cast<ConstantSDNode>(N2)->getValue(), MVT::i32);
+ return DAG.getNode(ISD::INSERT_VECTOR_ELT, VT, Op.getOperand(0), N1, N2);
+ }
+
+ return SDOperand();
+ }
}
}
@@ -2692,6 +2725,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
case X86ISD::Wrapper: return "X86ISD::Wrapper";
case X86ISD::S2VEC: return "X86ISD::S2VEC";
case X86ISD::ZEXT_S2VEC: return "X86ISD::ZEXT_S2VEC";
+ case X86ISD::PEXTRW: return "X86ISD::PEXTRW";
}
}
diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h
index 3bd2b88c6c..3f8ec844f4 100644
--- a/lib/Target/X86/X86ISelLowering.h
+++ b/lib/Target/X86/X86ISelLowering.h
@@ -153,6 +153,10 @@ namespace llvm {
/// ZEXT_S2VEC - SCALAR_TO_VECTOR with zero extension. The destination base
/// does not have to match the operand type.
ZEXT_S2VEC,
+
+ /// PEXTRW - Extract a 16-bit value from a vector and zero extend it to
+ /// i32, corresponds to X86::PINSRW.
+ PEXTRW,
};
// X86 specific condition code. These correspond to X86_*_COND in
diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td
index 2245a2218f..38158a24f4 100644
--- a/lib/Target/X86/X86InstrSSE.td
+++ b/lib/Target/X86/X86InstrSSE.td
@@ -28,8 +28,8 @@ def X86s2vec : SDNode<"X86ISD::S2VEC",
def X86zexts2vec : SDNode<"X86ISD::ZEXT_S2VEC",
SDTypeProfile<1, 1, []>, []>;
-def SDTUnpckl : SDTypeProfile<1, 2,
- [SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>]>;
+def X86pextrw : SDNode<"X86ISD::PEXTRW",
+ SDTypeProfile<1, 2, []>, []>;
//===----------------------------------------------------------------------===//
// SSE pattern fragments
@@ -1409,6 +1409,33 @@ def PUNPCKHQDQrm : PDI<0x6D, MRMSrcMem,
UNPCKH_shuffle_mask)))]>;
}
+// Extract / Insert
+def PEXTRWrr : PDIi8<0xC5, MRMSrcReg,
+ (ops R32:$dst, VR128:$src1, i32i8imm:$src2),
+ "pextrw {$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set R32:$dst, (X86pextrw (v8i16 VR128:$src1),
+ (i32 imm:$src2)))]>;
+def PEXTRWrm : PDIi8<0xC5, MRMSrcMem,
+ (ops R32:$dst, i128mem:$src1, i32i8imm:$src2),
+ "pextrw {$src2, $src1, $dst|$dst, $src1, $src2}",
+ [(set R32:$dst, (X86pextrw (loadv8i16 addr:$src1),
+ (i32 imm:$src2)))]>;
+
+let isTwoAddress = 1 in {
+def PINSRWrr : PDIi8<0xC4, MRMSrcReg,
+ (ops VR128:$dst, VR128:$src1, R32:$src2, i32i8imm:$src3),
+ "pinsrw {$src3, $src2, $dst|$dst, $src2, $src3}",
+ [(set VR128:$dst, (v8i16 (vector_insert (v8i16 VR128:$src1),
+ R32:$src2, (i32 imm:$src3))))]>;
+def PINSRWrm : PDIi8<0xC4, MRMSrcMem,
+ (ops VR128:$dst, VR128:$src1, i16mem:$src2, i32i8imm:$src3),
+ "pinsrw {$src3, $src2, $dst|$dst, $src2, $src3}",
+ [(set VR128:$dst,
+ (v8i16 (vector_insert (v8i16 VR128:$src1),
+ (i32 (anyext (loadi16 addr:$src2))),
+ (i32 imm:$src3))))]>;
+}
+
//===----------------------------------------------------------------------===//
// Miscellaneous Instructions
//===----------------------------------------------------------------------===//