summaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86ISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/X86/X86ISelLowering.cpp')
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 54d824419f..4b11f2b61f 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1498,6 +1498,7 @@ void X86TargetLowering::resetOperationActions() {
}
// We have target-specific dag combine patterns for the following nodes:
+ setTargetDAGCombine(ISD::CONCAT_VECTORS);
setTargetDAGCombine(ISD::VECTOR_SHUFFLE);
setTargetDAGCombine(ISD::EXTRACT_VECTOR_ELT);
setTargetDAGCombine(ISD::VSELECT);
@@ -16151,6 +16152,44 @@ static SDValue PerformShuffleCombine256(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+static SDValue PerformConcatCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const X86Subtarget *Subtarget) {
+ // Creating a v8i16 from a v4i16 argument and an undef runs into trouble in
+ // type legalization and ends up spilling to the stack. Avoid that by
+ // creating a vector first and bitcasting the result rather than
+ // bitcasting the source then creating the vector. Similar problems with
+ // v8i8.
+
+ // No point in doing this after legalize, so early exit for that.
+ if (!DCI.isBeforeLegalize())
+ return SDValue();
+
+ EVT VT = N->getValueType(0);
+ SDValue Op0 = N->getOperand(0);
+ SDValue Op1 = N->getOperand(1);
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (VT.getSizeInBits() == 128 && N->getNumOperands() == 2 &&
+ Op1->getOpcode() == ISD::UNDEF &&
+ Op0->getOpcode() == ISD::BITCAST &&
+ !TLI.isTypeLegal(Op0->getValueType(0)) &&
+ TLI.isTypeLegal(Op0->getOperand(0)->getValueType(0))) {
+ SDValue Scalar = Op0->getOperand(0);
+ // Any legal type here will be a simple value type.
+ MVT SVT = Scalar->getValueType(0).getSimpleVT();
+ // As a special case, bail out on MMX values.
+ if (SVT == MVT::x86mmx)
+ return SDValue();
+ EVT NVT = MVT::getVectorVT(SVT, 2);
+ SDLoc dl = SDLoc(N);
+ SDValue Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NVT, Scalar);
+ Res = DAG.getNode(ISD::BITCAST, dl, VT, Res);
+ return Res;
+ }
+
+ return SDValue();
+}
+
/// PerformShuffleCombine - Performs several different shuffle combines.
static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
@@ -19029,6 +19068,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
case X86ISD::VPERMILP:
case X86ISD::VPERM2X128:
case ISD::VECTOR_SHUFFLE: return PerformShuffleCombine(N, DAG, DCI,Subtarget);
+ case ISD::CONCAT_VECTORS: return PerformConcatCombine(N, DAG, DCI, Subtarget);
case ISD::FMA: return PerformFMACombine(N, DAG, Subtarget);
}