@@ -23807,6 +23807,13 @@ SDValue DAGCombiner::reduceBuildVecToShuffle(SDNode *N) {
23807
23807
SmallVector<SDValue, 8> VecIn;
23808
23808
VecIn.push_back(SDValue());
23809
23809
23810
+ // If we have a single extract_element with a constant index, track the index
23811
+ // value.
23812
+ unsigned OneConstExtractIndex = ~0u;
23813
+
23814
+ // Count the number of extract_vector_elt sources (i.e. non-constant or undef)
23815
+ unsigned NumExtracts = 0;
23816
+
23810
23817
for (unsigned i = 0; i != NumElems; ++i) {
23811
23818
SDValue Op = N->getOperand(i);
23812
23819
@@ -23824,23 +23831,28 @@ SDValue DAGCombiner::reduceBuildVecToShuffle(SDNode *N) {
23824
23831
23825
23832
// Not an undef or zero. If the input is something other than an
23826
23833
// EXTRACT_VECTOR_ELT with an in-range constant index, bail out.
23827
- if (Op.getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
23828
- !isa<ConstantSDNode>(Op.getOperand(1)))
23834
+ if (Op.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
23829
23835
return SDValue();
23830
- SDValue ExtractedFromVec = Op.getOperand(0);
23831
23836
23837
+ SDValue ExtractedFromVec = Op.getOperand(0);
23832
23838
if (ExtractedFromVec.getValueType().isScalableVector())
23833
23839
return SDValue();
23840
+ auto *ExtractIdx = dyn_cast<ConstantSDNode>(Op.getOperand(1));
23841
+ if (!ExtractIdx)
23842
+ return SDValue();
23834
23843
23835
- const APInt & ExtractIdx = Op.getConstantOperandAPInt(1);
23836
- if (ExtractIdx.uge( ExtractedFromVec.getValueType().getVectorNumElements()))
23844
+ if ( ExtractIdx->getAsAPIntVal().uge(
23845
+ ExtractedFromVec.getValueType().getVectorNumElements()))
23837
23846
return SDValue();
23838
23847
23839
23848
// All inputs must have the same element type as the output.
23840
23849
if (VT.getVectorElementType() !=
23841
23850
ExtractedFromVec.getValueType().getVectorElementType())
23842
23851
return SDValue();
23843
23852
23853
+ OneConstExtractIndex = ExtractIdx->getZExtValue();
23854
+ ++NumExtracts;
23855
+
23844
23856
// Have we seen this input vector before?
23845
23857
// The vectors are expected to be tiny (usually 1 or 2 elements), so using
23846
23858
// a map back from SDValues to numbers isn't worth it.
@@ -23863,6 +23875,20 @@ SDValue DAGCombiner::reduceBuildVecToShuffle(SDNode *N) {
23863
23875
// VecIn accordingly.
23864
23876
bool DidSplitVec = false;
23865
23877
if (VecIn.size() == 2) {
23878
+ // If we only found a single constant indexed extract_vector_elt feeding the
23879
+ // build_vector, do not produce a more complicated shuffle if the extract is
23880
+ // cheap with other constant/undef elements. Skip broadcast patterns with
23881
+ // multiple uses in the build_vector.
23882
+
23883
+ // TODO: This should be more aggressive about skipping the shuffle
23884
+ // formation, particularly if VecIn[1].hasOneUse(), and regardless of the
23885
+ // index.
23886
+ if (NumExtracts == 1 &&
23887
+ TLI.isOperationLegalOrCustom(ISD::EXTRACT_VECTOR_ELT, VT) &&
23888
+ TLI.isTypeLegal(VT.getVectorElementType()) &&
23889
+ TLI.isExtractVecEltCheap(VT, OneConstExtractIndex))
23890
+ return SDValue();
23891
+
23866
23892
unsigned MaxIndex = 0;
23867
23893
unsigned NearestPow2 = 0;
23868
23894
SDValue Vec = VecIn.back();
0 commit comments