Skip to content

Commit 5334c51

Browse files
authored
[IR][InstCombine] Fix O(n^2) complexity in SliceUpIllegalIntegerPHI (#175468)
Add a hasInsertionPt() helper, which is equivalent to getFirstInsertionPt() != end(), but performs the check in O(1) instead of O(n). In particular, this avoids quadratic complexity inside SliceUpIllegalIntegerPHI(). Fixes #175465. Should fix rust-lang/rust#129713.
1 parent 55ba30b commit 5334c51

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

llvm/include/llvm/IR/BasicBlock.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,17 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
334334
.getNonConst();
335335
}
336336

337+
/// Returns true if there is a valid insertion point for non-PHI instructions
338+
/// in this block. Returns false for blocks that can only contain PHI nodes,
339+
/// such as blocks with a catchswitch terminator.
340+
///
341+
/// This is an O(1) check, unlike getFirstInsertionPt() which must scan
342+
/// through all PHI nodes.
343+
bool hasInsertionPt() const {
344+
const Instruction *Term = getTerminator();
345+
return Term && Term->getOpcode() != Instruction::CatchSwitch;
346+
}
347+
337348
/// Returns an iterator to the first instruction in this block that is
338349
/// not a PHINode, a debug intrinsic, a static alloca or any pseudo operation.
339350
LLVM_ABI const_iterator getFirstNonPHIOrDbgOrAlloca() const;

llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ bool InstCombinerImpl::foldIntegerTypedPHI(PHINode &PN) {
272272
if (Inst->isTerminator())
273273
return true;
274274
auto *BB = Inst->getParent();
275-
if (isa<PHINode>(Inst) && BB->getFirstInsertionPt() == BB->end())
275+
if (isa<PHINode>(Inst) && !BB->hasInsertionPt())
276276
return true;
277277
return false;
278278
}))
@@ -1133,7 +1133,7 @@ Instruction *InstCombinerImpl::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
11331133
// extract the value within that BB because we cannot insert any non-PHI
11341134
// instructions in the BB.
11351135
for (auto *Pred : PN->blocks())
1136-
if (Pred->getFirstInsertionPt() == Pred->end())
1136+
if (!Pred->hasInsertionPt())
11371137
return nullptr;
11381138

11391139
for (User *U : PN->users()) {
@@ -1451,8 +1451,7 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
14511451

14521452
// If the incoming values are pointer casts of the same original value,
14531453
// replace the phi with a single cast iff we can insert a non-PHI instruction.
1454-
if (PN.getType()->isPointerTy() &&
1455-
PN.getParent()->getFirstInsertionPt() != PN.getParent()->end()) {
1454+
if (PN.getType()->isPointerTy() && PN.getParent()->hasInsertionPt()) {
14561455
Value *IV0 = PN.getIncomingValue(0);
14571456
Value *IV0Stripped = IV0->stripPointerCasts();
14581457
// Set to keep track of values known to be equal to IV0Stripped after

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,8 +1381,7 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
13811381
// If this is a PHI node before a catchswitch, we cannot insert any non-PHI
13821382
// instructions in this BB, which may be required during rewriting. Bail out
13831383
// on these cases.
1384-
if (isa<PHINode>(I) &&
1385-
I.getParent()->getFirstInsertionPt() == I.getParent()->end())
1384+
if (isa<PHINode>(I) && !I.getParent()->hasInsertionPt())
13861385
return PI.setAborted(&I);
13871386

13881387
// TODO: We could use simplifyInstruction here to fold PHINodes and

0 commit comments

Comments
 (0)