Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 2ac73a1

Browse files
committed
Merging r308891:
------------------------------------------------------------------------ r308891 | d0k | 2017-07-24 09:18:09 -0700 (Mon, 24 Jul 2017) | 16 lines [CodeGenPrepare] Cut off FindAllMemoryUses if there are too many uses. This avoids excessive compile time. The case I'm looking at is Function.cpp from an old version of LLVM that still had the giant memcmp string matcher in it. Before r308322 this compiled in about 2 minutes, after it, clang takes infinite* time to compile it. With this patch we're at 5 min, which is still bad but this is a pathological case. The cut off at 20 uses was chosen by looking at other cut-offs in LLVM for user scanning. It's probably too high, but does the job and is very unlikely to regress anything. Fixes PR33900. * I'm impatient and aborted after 15 minutes, on the bug report it was killed after 2h. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@309131 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e872521 commit 2ac73a1

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4016,14 +4016,18 @@ static bool IsOperandAMemoryOperand(CallInst *CI, InlineAsm *IA, Value *OpVal,
40164016
return true;
40174017
}
40184018

4019+
// Max number of memory uses to look at before aborting the search to conserve
4020+
// compile time.
4021+
static constexpr int MaxMemoryUsesToScan = 20;
4022+
40194023
/// Recursively walk all the uses of I until we find a memory use.
40204024
/// If we find an obviously non-foldable instruction, return true.
40214025
/// Add the ultimately found memory instructions to MemoryUses.
40224026
static bool FindAllMemoryUses(
40234027
Instruction *I,
40244028
SmallVectorImpl<std::pair<Instruction *, unsigned>> &MemoryUses,
4025-
SmallPtrSetImpl<Instruction *> &ConsideredInsts,
4026-
const TargetLowering &TLI, const TargetRegisterInfo &TRI) {
4029+
SmallPtrSetImpl<Instruction *> &ConsideredInsts, const TargetLowering &TLI,
4030+
const TargetRegisterInfo &TRI, int SeenInsts = 0) {
40274031
// If we already considered this instruction, we're done.
40284032
if (!ConsideredInsts.insert(I).second)
40294033
return false;
@@ -4036,8 +4040,12 @@ static bool FindAllMemoryUses(
40364040

40374041
// Loop over all the uses, recursively processing them.
40384042
for (Use &U : I->uses()) {
4039-
Instruction *UserI = cast<Instruction>(U.getUser());
4043+
// Conservatively return true if we're seeing a large number or a deep chain
4044+
// of users. This avoids excessive compilation times in pathological cases.
4045+
if (SeenInsts++ >= MaxMemoryUsesToScan)
4046+
return true;
40404047

4048+
Instruction *UserI = cast<Instruction>(U.getUser());
40414049
if (LoadInst *LI = dyn_cast<LoadInst>(UserI)) {
40424050
MemoryUses.push_back(std::make_pair(LI, U.getOperandNo()));
40434051
continue;
@@ -4082,7 +4090,8 @@ static bool FindAllMemoryUses(
40824090
continue;
40834091
}
40844092

4085-
if (FindAllMemoryUses(UserI, MemoryUses, ConsideredInsts, TLI, TRI))
4093+
if (FindAllMemoryUses(UserI, MemoryUses, ConsideredInsts, TLI, TRI,
4094+
SeenInsts))
40864095
return true;
40874096
}
40884097

0 commit comments

Comments
 (0)