mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Turn a series of extract_element's feeding a build_vector into a
vector_shuffle node. For this: void test(__m128 *res, __m128 *A, __m128 *B) { *res = _mm_unpacklo_ps(*A, *B); } we now produce this code: _test: movl 8(%esp), %eax movaps (%eax), %xmm0 movl 12(%esp), %eax unpcklps (%eax), %xmm0 movl 4(%esp), %eax movaps %xmm0, (%eax) ret instead of this: _test: subl $76, %esp movl 88(%esp), %eax movaps (%eax), %xmm0 movaps %xmm0, (%esp) movaps %xmm0, 32(%esp) movss 4(%esp), %xmm0 movss 32(%esp), %xmm1 unpcklps %xmm0, %xmm1 movl 84(%esp), %eax movaps (%eax), %xmm0 movaps %xmm0, 16(%esp) movaps %xmm0, 48(%esp) movss 20(%esp), %xmm0 movss 48(%esp), %xmm2 unpcklps %xmm0, %xmm2 unpcklps %xmm1, %xmm2 movl 80(%esp), %eax movaps %xmm2, (%eax) addl $76, %esp ret GCC produces this (with -fomit-frame-pointer): _test: subl $12, %esp movl 20(%esp), %eax movaps (%eax), %xmm0 movl 24(%esp), %eax unpcklps (%eax), %xmm0 movl 16(%esp), %eax movaps %xmm0, (%eax) addl $12, %esp ret git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27233 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5b2316e2b0
commit
d7648c8934
@ -211,6 +211,7 @@ namespace {
|
||||
SDOperand visitSTORE(SDNode *N);
|
||||
SDOperand visitINSERT_VECTOR_ELT(SDNode *N);
|
||||
SDOperand visitVINSERT_VECTOR_ELT(SDNode *N);
|
||||
SDOperand visitVBUILD_VECTOR(SDNode *N);
|
||||
|
||||
SDOperand ReassociateOps(unsigned Opc, SDOperand LHS, SDOperand RHS);
|
||||
|
||||
@ -644,6 +645,7 @@ SDOperand DAGCombiner::visit(SDNode *N) {
|
||||
case ISD::STORE: return visitSTORE(N);
|
||||
case ISD::INSERT_VECTOR_ELT: return visitINSERT_VECTOR_ELT(N);
|
||||
case ISD::VINSERT_VECTOR_ELT: return visitVINSERT_VECTOR_ELT(N);
|
||||
case ISD::VBUILD_VECTOR: return visitVBUILD_VECTOR(N);
|
||||
}
|
||||
return SDOperand();
|
||||
}
|
||||
@ -2341,6 +2343,90 @@ SDOperand DAGCombiner::visitVINSERT_VECTOR_ELT(SDNode *N) {
|
||||
return SDOperand();
|
||||
}
|
||||
|
||||
SDOperand DAGCombiner::visitVBUILD_VECTOR(SDNode *N) {
|
||||
unsigned NumInScalars = N->getNumOperands()-2;
|
||||
SDOperand NumElts = N->getOperand(NumInScalars);
|
||||
SDOperand EltType = N->getOperand(NumInScalars+1);
|
||||
|
||||
// Check to see if this is a VBUILD_VECTOR of a bunch of VEXTRACT_VECTOR_ELT
|
||||
// operations. If so, and if the EXTRACT_ELT vector inputs come from at most
|
||||
// two distinct vectors, turn this into a shuffle node.
|
||||
SDOperand VecIn1, VecIn2;
|
||||
for (unsigned i = 0; i != NumInScalars; ++i) {
|
||||
// Ignore undef inputs.
|
||||
if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
||||
|
||||
// If this input is something other than a VEXTRACT_VECTOR_ELT with a
|
||||
// constant index, bail out.
|
||||
if (N->getOperand(i).getOpcode() != ISD::VEXTRACT_VECTOR_ELT ||
|
||||
!isa<ConstantSDNode>(N->getOperand(i).getOperand(1))) {
|
||||
VecIn1 = VecIn2 = SDOperand(0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the input vector type disagrees with the result of the vbuild_vector,
|
||||
// we can't make a shuffle.
|
||||
SDOperand ExtractedFromVec = N->getOperand(i).getOperand(0);
|
||||
if (*(ExtractedFromVec.Val->op_end()-2) != NumElts ||
|
||||
*(ExtractedFromVec.Val->op_end()-1) != EltType) {
|
||||
VecIn1 = VecIn2 = SDOperand(0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, remember this. We allow up to two distinct input vectors.
|
||||
if (ExtractedFromVec == VecIn1 || ExtractedFromVec == VecIn2)
|
||||
continue;
|
||||
|
||||
if (VecIn1.Val == 0) {
|
||||
VecIn1 = ExtractedFromVec;
|
||||
} else if (VecIn2.Val == 0) {
|
||||
VecIn2 = ExtractedFromVec;
|
||||
} else {
|
||||
// Too many inputs.
|
||||
VecIn1 = VecIn2 = SDOperand(0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If everything is good, we can make a shuffle operation.
|
||||
if (VecIn1.Val) {
|
||||
std::vector<SDOperand> BuildVecIndices;
|
||||
for (unsigned i = 0; i != NumInScalars; ++i) {
|
||||
if (N->getOperand(i).getOpcode() == ISD::UNDEF) {
|
||||
BuildVecIndices.push_back(DAG.getNode(ISD::UNDEF, MVT::i32));
|
||||
continue;
|
||||
}
|
||||
|
||||
SDOperand Extract = N->getOperand(i);
|
||||
|
||||
// If extracting from the first vector, just use the index directly.
|
||||
if (Extract.getOperand(0) == VecIn1) {
|
||||
BuildVecIndices.push_back(Extract.getOperand(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, use InIdx + VecSize
|
||||
unsigned Idx = cast<ConstantSDNode>(Extract.getOperand(1))->getValue();
|
||||
BuildVecIndices.push_back(DAG.getConstant(Idx+NumInScalars, MVT::i32));
|
||||
}
|
||||
|
||||
// Add count and size info.
|
||||
BuildVecIndices.push_back(NumElts);
|
||||
BuildVecIndices.push_back(DAG.getValueType(MVT::i32));
|
||||
|
||||
// Return the new VVECTOR_SHUFFLE node.
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(VecIn1);
|
||||
Ops.push_back(VecIn2.Val ? VecIn2 : VecIn1); // Use V1 twice if no V2.
|
||||
Ops.push_back(DAG.getNode(ISD::VBUILD_VECTOR,MVT::Vector, BuildVecIndices));
|
||||
Ops.push_back(NumElts);
|
||||
Ops.push_back(EltType);
|
||||
return DAG.getNode(ISD::VVECTOR_SHUFFLE, MVT::Vector, Ops);
|
||||
}
|
||||
|
||||
return SDOperand();
|
||||
}
|
||||
|
||||
SDOperand DAGCombiner::SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2){
|
||||
assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user