Skip to content

Commit 2dbd45d

Browse files
committed
[InstCombine] linearize complexity of findDemandedEltsByAllUsers()
Each call to findemandedEltsBySingleUser() returns a new APInt that must be OR'd with the current APInt. For large vectors with many uses this can be slow, if the total number of operations is {# uses} x {size of vector}. Instead or OR'ing, use setBit() on the passed-in APInt.
1 parent fe9fba8 commit 2dbd45d

File tree

1 file changed

+15
-14
lines changed

1 file changed

+15
-14
lines changed

llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -319,20 +319,20 @@ Instruction *InstCombinerImpl::foldBitcastExtElt(ExtractElementInst &Ext) {
319319
return nullptr;
320320
}
321321

322-
/// Find elements of V demanded by UserInstr.
323-
static APInt findDemandedEltsBySingleUser(Value *V, Instruction *UserInstr) {
322+
/// Find elements of V demanded by UserInstr. If returns false, we were not able
323+
/// to determine all elements.
324+
static bool findDemandedEltsBySingleUser(Value *V, Instruction *UserInstr,
325+
APInt &UnionUsedElts) {
324326
unsigned VWidth = cast<FixedVectorType>(V->getType())->getNumElements();
325327

326-
// Conservatively assume that all elements are needed.
327-
APInt UsedElts(APInt::getAllOnes(VWidth));
328-
329328
switch (UserInstr->getOpcode()) {
330329
case Instruction::ExtractElement: {
331330
ExtractElementInst *EEI = cast<ExtractElementInst>(UserInstr);
332331
assert(EEI->getVectorOperand() == V);
333332
ConstantInt *EEIIndexC = dyn_cast<ConstantInt>(EEI->getIndexOperand());
334333
if (EEIIndexC && EEIIndexC->getValue().ult(VWidth)) {
335-
UsedElts = APInt::getOneBitSet(VWidth, EEIIndexC->getZExtValue());
334+
UnionUsedElts.setBit(EEIIndexC->getZExtValue());
335+
return true;
336336
}
337337
break;
338338
}
@@ -341,23 +341,23 @@ static APInt findDemandedEltsBySingleUser(Value *V, Instruction *UserInstr) {
341341
unsigned MaskNumElts =
342342
cast<FixedVectorType>(UserInstr->getType())->getNumElements();
343343

344-
UsedElts = APInt(VWidth, 0);
345-
for (unsigned i = 0; i < MaskNumElts; i++) {
346-
unsigned MaskVal = Shuffle->getMaskValue(i);
344+
for (auto I : llvm::seq(MaskNumElts)) {
345+
unsigned MaskVal = Shuffle->getMaskValue(I);
347346
if (MaskVal == -1u || MaskVal >= 2 * VWidth)
348347
continue;
349348
if (Shuffle->getOperand(0) == V && (MaskVal < VWidth))
350-
UsedElts.setBit(MaskVal);
349+
UnionUsedElts.setBit(MaskVal);
351350
if (Shuffle->getOperand(1) == V &&
352351
((MaskVal >= VWidth) && (MaskVal < 2 * VWidth)))
353-
UsedElts.setBit(MaskVal - VWidth);
352+
UnionUsedElts.setBit(MaskVal - VWidth);
354353
}
355-
break;
354+
return true;
356355
}
357356
default:
358357
break;
359358
}
360-
return UsedElts;
359+
360+
return false;
361361
}
362362

363363
/// Find union of elements of V demanded by all its users.
@@ -370,7 +370,8 @@ static APInt findDemandedEltsByAllUsers(Value *V) {
370370
APInt UnionUsedElts(VWidth, 0);
371371
for (const Use &U : V->uses()) {
372372
if (Instruction *I = dyn_cast<Instruction>(U.getUser())) {
373-
UnionUsedElts |= findDemandedEltsBySingleUser(V, I);
373+
if (!findDemandedEltsBySingleUser(V, I, UnionUsedElts))
374+
return APInt::getAllOnes(VWidth);
374375
} else {
375376
UnionUsedElts = APInt::getAllOnes(VWidth);
376377
break;

0 commit comments

Comments
 (0)