@@ -25100,26 +25100,26 @@ SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *N) {
25100
25100
25101
25101
// Helper that peeks through INSERT_SUBVECTOR/CONCAT_VECTORS to find
25102
25102
// if the subvector can be sourced for free.
25103
- static SDValue getSubVectorSrc(SDValue V, SDValue Index, EVT SubVT) {
25103
+ static SDValue getSubVectorSrc(SDValue V, unsigned Index, EVT SubVT) {
25104
25104
if (V.getOpcode() == ISD::INSERT_SUBVECTOR &&
25105
- V.getOperand(1).getValueType() == SubVT && V.getOperand(2) == Index) {
25105
+ V.getOperand(1).getValueType() == SubVT &&
25106
+ V.getConstantOperandAPInt(2) == Index) {
25106
25107
return V.getOperand(1);
25107
25108
}
25108
- auto *IndexC = dyn_cast<ConstantSDNode>(Index);
25109
- if (IndexC && V.getOpcode() == ISD::CONCAT_VECTORS &&
25109
+ if (V.getOpcode() == ISD::CONCAT_VECTORS &&
25110
25110
V.getOperand(0).getValueType() == SubVT &&
25111
- (IndexC->getZExtValue() % SubVT.getVectorMinNumElements()) == 0) {
25112
- uint64_t SubIdx = IndexC->getZExtValue() / SubVT.getVectorMinNumElements();
25111
+ (Index % SubVT.getVectorMinNumElements()) == 0) {
25112
+ uint64_t SubIdx = Index / SubVT.getVectorMinNumElements();
25113
25113
return V.getOperand(SubIdx);
25114
25114
}
25115
25115
return SDValue();
25116
25116
}
25117
25117
25118
- static SDValue narrowInsertExtractVectorBinOp(SDNode *Extract,
25118
+ static SDValue narrowInsertExtractVectorBinOp(EVT SubVT, SDValue BinOp,
25119
+ unsigned Index, const SDLoc &DL,
25119
25120
SelectionDAG &DAG,
25120
25121
bool LegalOperations) {
25121
25122
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
25122
- SDValue BinOp = Extract->getOperand(0);
25123
25123
unsigned BinOpcode = BinOp.getOpcode();
25124
25124
if (!TLI.isBinOp(BinOpcode) || BinOp->getNumValues() != 1)
25125
25125
return SDValue();
@@ -25128,9 +25128,6 @@ static SDValue narrowInsertExtractVectorBinOp(SDNode *Extract,
25128
25128
SDValue Bop0 = BinOp.getOperand(0), Bop1 = BinOp.getOperand(1);
25129
25129
if (VecVT != Bop0.getValueType() || VecVT != Bop1.getValueType())
25130
25130
return SDValue();
25131
-
25132
- SDValue Index = Extract->getOperand(1);
25133
- EVT SubVT = Extract->getValueType(0);
25134
25131
if (!TLI.isOperationLegalOrCustom(BinOpcode, SubVT, LegalOperations))
25135
25132
return SDValue();
25136
25133
@@ -25146,29 +25143,25 @@ static SDValue narrowInsertExtractVectorBinOp(SDNode *Extract,
25146
25143
// We are inserting both operands of the wide binop only to extract back
25147
25144
// to the narrow vector size. Eliminate all of the insert/extract:
25148
25145
// ext (binop (ins ?, X, Index), (ins ?, Y, Index)), Index --> binop X, Y
25149
- return DAG.getNode(BinOpcode, SDLoc(Extract), SubVT, Sub0, Sub1,
25150
- BinOp->getFlags());
25146
+ return DAG.getNode(BinOpcode, DL, SubVT, Sub0, Sub1, BinOp->getFlags());
25151
25147
}
25152
25148
25153
25149
/// If we are extracting a subvector produced by a wide binary operator try
25154
25150
/// to use a narrow binary operator and/or avoid concatenation and extraction.
25155
- static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG,
25151
+ static SDValue narrowExtractedVectorBinOp(EVT VT, SDValue Src, unsigned Index,
25152
+ const SDLoc &DL, SelectionDAG &DAG,
25156
25153
bool LegalOperations) {
25157
25154
// TODO: Refactor with the caller (visitEXTRACT_SUBVECTOR), so we can share
25158
25155
// some of these bailouts with other transforms.
25159
25156
25160
- if (SDValue V = narrowInsertExtractVectorBinOp(Extract, DAG, LegalOperations))
25157
+ if (SDValue V = narrowInsertExtractVectorBinOp(VT, Src, Index, DL, DAG,
25158
+ LegalOperations))
25161
25159
return V;
25162
25160
25163
- // The extract index must be a constant, so we can map it to a concat operand.
25164
- auto *ExtractIndexC = dyn_cast<ConstantSDNode>(Extract->getOperand(1));
25165
- if (!ExtractIndexC)
25166
- return SDValue();
25167
-
25168
25161
// We are looking for an optionally bitcasted wide vector binary operator
25169
25162
// feeding an extract subvector.
25170
25163
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
25171
- SDValue BinOp = peekThroughBitcasts(Extract->getOperand(0) );
25164
+ SDValue BinOp = peekThroughBitcasts(Src );
25172
25165
unsigned BOpcode = BinOp.getOpcode();
25173
25166
if (!TLI.isBinOp(BOpcode) || BinOp->getNumValues() != 1)
25174
25167
return SDValue();
@@ -25190,9 +25183,7 @@ static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG,
25190
25183
if (!WideBVT.isFixedLengthVector())
25191
25184
return SDValue();
25192
25185
25193
- EVT VT = Extract->getValueType(0);
25194
- unsigned ExtractIndex = ExtractIndexC->getZExtValue();
25195
- assert(ExtractIndex % VT.getVectorNumElements() == 0 &&
25186
+ assert((Index % VT.getVectorNumElements()) == 0 &&
25196
25187
"Extract index is not a multiple of the vector length.");
25197
25188
25198
25189
// Bail out if this is not a proper multiple width extraction.
@@ -25219,12 +25210,11 @@ static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG,
25219
25210
// for concat ops. The narrow binop alone makes this transform profitable.
25220
25211
// We can't just reuse the original extract index operand because we may have
25221
25212
// bitcasted.
25222
- unsigned ConcatOpNum = ExtractIndex / VT.getVectorNumElements();
25213
+ unsigned ConcatOpNum = Index / VT.getVectorNumElements();
25223
25214
unsigned ExtBOIdx = ConcatOpNum * NarrowBVT.getVectorNumElements();
25224
25215
if (TLI.isExtractSubvectorCheap(NarrowBVT, WideBVT, ExtBOIdx) &&
25225
- BinOp.hasOneUse() && Extract->getOperand(0) ->hasOneUse()) {
25216
+ BinOp.hasOneUse() && Src ->hasOneUse()) {
25226
25217
// extract (binop B0, B1), N --> binop (extract B0, N), (extract B1, N)
25227
- SDLoc DL(Extract);
25228
25218
SDValue NewExtIndex = DAG.getVectorIdxConstant(ExtBOIdx, DL);
25229
25219
SDValue X = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NarrowBVT,
25230
25220
BinOp.getOperand(0), NewExtIndex);
@@ -25264,7 +25254,6 @@ static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG,
25264
25254
// extract (binop (concat X1, X2), (concat Y1, Y2)), N --> binop XN, YN
25265
25255
// extract (binop (concat X1, X2), Y), N --> binop XN, (extract Y, IndexC)
25266
25256
// extract (binop X, (concat Y1, Y2)), N --> binop (extract X, IndexC), YN
25267
- SDLoc DL(Extract);
25268
25257
SDValue IndexC = DAG.getVectorIdxConstant(ExtBOIdx, DL);
25269
25258
SDValue X = SubVecL ? DAG.getBitcast(NarrowBVT, SubVecL)
25270
25259
: DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NarrowBVT,
@@ -25284,24 +25273,24 @@ static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG,
25284
25273
/// If we are extracting a subvector from a wide vector load, convert to a
25285
25274
/// narrow load to eliminate the extraction:
25286
25275
/// (extract_subvector (load wide vector)) --> (load narrow vector)
25287
- static SDValue narrowExtractedVectorLoad(SDNode *Extract, const SDLoc &DL ,
25288
- SelectionDAG &DAG) {
25276
+ static SDValue narrowExtractedVectorLoad(EVT VT, SDValue Src, unsigned Index ,
25277
+ const SDLoc &DL, SelectionDAG &DAG) {
25289
25278
// TODO: Add support for big-endian. The offset calculation must be adjusted.
25290
25279
if (DAG.getDataLayout().isBigEndian())
25291
25280
return SDValue();
25292
25281
25293
- auto *Ld = dyn_cast<LoadSDNode>(Extract->getOperand(0) );
25282
+ auto *Ld = dyn_cast<LoadSDNode>(Src );
25294
25283
if (!Ld || !ISD::isNormalLoad(Ld) || !Ld->isSimple())
25295
25284
return SDValue();
25296
25285
25297
- // Allow targets to opt-out.
25298
- EVT VT = Extract->getValueType(0);
25299
-
25300
25286
// We can only create byte sized loads.
25301
25287
if (!VT.isByteSized())
25302
25288
return SDValue();
25303
25289
25304
- unsigned Index = Extract->getConstantOperandVal(1);
25290
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
25291
+ if (!TLI.isOperationLegalOrCustomOrPromote(ISD::LOAD, VT))
25292
+ return SDValue();
25293
+
25305
25294
unsigned NumElts = VT.getVectorMinNumElements();
25306
25295
// A fixed length vector being extracted from a scalable vector
25307
25296
// may not be any *smaller* than the scalable one.
@@ -25319,7 +25308,6 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, const SDLoc &DL,
25319
25308
if (Offset.isFixed())
25320
25309
ByteOffset = Offset.getFixedValue();
25321
25310
25322
- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
25323
25311
if (!TLI.shouldReduceLoadWidth(Ld, Ld->getExtensionType(), VT, ByteOffset))
25324
25312
return SDValue();
25325
25313
@@ -25350,23 +25338,18 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, const SDLoc &DL,
25350
25338
/// iff it is legal and profitable to do so. Notably, the trimmed mask
25351
25339
/// (containing only the elements that are extracted)
25352
25340
/// must reference at most two subvectors.
25353
- static SDValue foldExtractSubvectorFromShuffleVector(SDNode *N,
25341
+ static SDValue foldExtractSubvectorFromShuffleVector(EVT NarrowVT, SDValue Src,
25342
+ unsigned Index,
25343
+ const SDLoc &DL,
25354
25344
SelectionDAG &DAG,
25355
- const TargetLowering &TLI,
25356
25345
bool LegalOperations) {
25357
- assert(N->getOpcode() == ISD::EXTRACT_SUBVECTOR &&
25358
- "Must only be called on EXTRACT_SUBVECTOR's");
25359
-
25360
- SDValue N0 = N->getOperand(0);
25361
-
25362
25346
// Only deal with non-scalable vectors.
25363
- EVT NarrowVT = N->getValueType(0);
25364
- EVT WideVT = N0.getValueType();
25347
+ EVT WideVT = Src.getValueType();
25365
25348
if (!NarrowVT.isFixedLengthVector() || !WideVT.isFixedLengthVector())
25366
25349
return SDValue();
25367
25350
25368
25351
// The operand must be a shufflevector.
25369
- auto *WideShuffleVector = dyn_cast<ShuffleVectorSDNode>(N0 );
25352
+ auto *WideShuffleVector = dyn_cast<ShuffleVectorSDNode>(Src );
25370
25353
if (!WideShuffleVector)
25371
25354
return SDValue();
25372
25355
@@ -25375,13 +25358,13 @@ static SDValue foldExtractSubvectorFromShuffleVector(SDNode *N,
25375
25358
return SDValue();
25376
25359
25377
25360
// And the narrow shufflevector that we'll form must be legal.
25361
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
25378
25362
if (LegalOperations &&
25379
25363
!TLI.isOperationLegalOrCustom(ISD::VECTOR_SHUFFLE, NarrowVT))
25380
25364
return SDValue();
25381
25365
25382
- uint64_t FirstExtractedEltIdx = N->getConstantOperandVal(1);
25383
25366
int NumEltsExtracted = NarrowVT.getVectorNumElements();
25384
- assert((FirstExtractedEltIdx % NumEltsExtracted) == 0 &&
25367
+ assert((Index % NumEltsExtracted) == 0 &&
25385
25368
"Extract index is not a multiple of the output vector length.");
25386
25369
25387
25370
int WideNumElts = WideVT.getVectorNumElements();
@@ -25392,8 +25375,7 @@ static SDValue foldExtractSubvectorFromShuffleVector(SDNode *N,
25392
25375
DemandedSubvectors;
25393
25376
25394
25377
// Try to decode the wide mask into narrow mask from at most two subvectors.
25395
- for (int M : WideShuffleVector->getMask().slice(FirstExtractedEltIdx,
25396
- NumEltsExtracted)) {
25378
+ for (int M : WideShuffleVector->getMask().slice(Index, NumEltsExtracted)) {
25397
25379
assert((M >= -1) && (M < (2 * WideNumElts)) &&
25398
25380
"Out-of-bounds shuffle mask?");
25399
25381
@@ -25476,8 +25458,6 @@ static SDValue foldExtractSubvectorFromShuffleVector(SDNode *N,
25476
25458
!TLI.isShuffleMaskLegal(NewMask, NarrowVT))
25477
25459
return SDValue();
25478
25460
25479
- SDLoc DL(N);
25480
-
25481
25461
SmallVector<SDValue, 2> NewOps;
25482
25462
for (const std::pair<SDValue /*Op*/, int /*SubvectorIndex*/>
25483
25463
&DemandedSubvector : DemandedSubvectors) {
@@ -25507,9 +25487,8 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *N) {
25507
25487
if (V.isUndef())
25508
25488
return DAG.getUNDEF(NVT);
25509
25489
25510
- if (TLI.isOperationLegalOrCustomOrPromote(ISD::LOAD, NVT))
25511
- if (SDValue NarrowLoad = narrowExtractedVectorLoad(N, DL, DAG))
25512
- return NarrowLoad;
25490
+ if (SDValue NarrowLoad = narrowExtractedVectorLoad(NVT, V, ExtIdx, DL, DAG))
25491
+ return NarrowLoad;
25513
25492
25514
25493
// Combine an extract of an extract into a single extract_subvector.
25515
25494
// ext (ext X, C), 0 --> ext X, C
@@ -25631,9 +25610,13 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *N) {
25631
25610
}
25632
25611
}
25633
25612
25634
- if (SDValue V =
25635
- foldExtractSubvectorFromShuffleVector(N, DAG, TLI, LegalOperations))
25636
- return V;
25613
+ if (SDValue Shuffle = foldExtractSubvectorFromShuffleVector(
25614
+ NVT, V, ExtIdx, DL, DAG, LegalOperations))
25615
+ return Shuffle;
25616
+
25617
+ if (SDValue NarrowBOp =
25618
+ narrowExtractedVectorBinOp(NVT, V, ExtIdx, DL, DAG, LegalOperations))
25619
+ return NarrowBOp;
25637
25620
25638
25621
V = peekThroughBitcasts(V);
25639
25622
@@ -25694,9 +25677,6 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode *N) {
25694
25677
}
25695
25678
}
25696
25679
25697
- if (SDValue NarrowBOp = narrowExtractedVectorBinOp(N, DAG, LegalOperations))
25698
- return NarrowBOp;
25699
-
25700
25680
// If only EXTRACT_SUBVECTOR nodes use the source vector we can
25701
25681
// simplify it based on the (valid) extractions.
25702
25682
if (!V.getValueType().isScalableVector() &&
0 commit comments