mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
Revert "[NewPM] Only invalidate modified functions' analyses in CGSCC passes"
This reverts commit d14d84af2f5ebb8ae2188ce6884a29a586dc0a40. Causes unacceptable memory regressions.
This commit is contained in:
parent
6347acc246
commit
1514e1d07b
@ -858,7 +858,7 @@ incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G,
|
|||||||
// split-off SCCs.
|
// split-off SCCs.
|
||||||
// We know however that this will preserve any FAM proxy so go ahead and mark
|
// We know however that this will preserve any FAM proxy so go ahead and mark
|
||||||
// that.
|
// that.
|
||||||
auto PA = PreservedAnalyses::allInSet<AllAnalysesOn<Function>>();
|
PreservedAnalyses PA;
|
||||||
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
||||||
AM.invalidate(*OldC, PA);
|
AM.invalidate(*OldC, PA);
|
||||||
|
|
||||||
|
@ -1019,12 +1019,11 @@ PreservedAnalyses ArgumentPromotionPass::run(LazyCallGraph::SCC &C,
|
|||||||
do {
|
do {
|
||||||
LocalChange = false;
|
LocalChange = false;
|
||||||
|
|
||||||
FunctionAnalysisManager &FAM =
|
|
||||||
AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
|
|
||||||
|
|
||||||
for (LazyCallGraph::Node &N : C) {
|
for (LazyCallGraph::Node &N : C) {
|
||||||
Function &OldF = N.getFunction();
|
Function &OldF = N.getFunction();
|
||||||
|
|
||||||
|
FunctionAnalysisManager &FAM =
|
||||||
|
AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
|
||||||
// FIXME: This lambda must only be used with this function. We should
|
// FIXME: This lambda must only be used with this function. We should
|
||||||
// skip the lambda and just get the AA results directly.
|
// skip the lambda and just get the AA results directly.
|
||||||
auto AARGetter = [&](Function &F) -> AAResults & {
|
auto AARGetter = [&](Function &F) -> AAResults & {
|
||||||
@ -1047,13 +1046,6 @@ PreservedAnalyses ArgumentPromotionPass::run(LazyCallGraph::SCC &C,
|
|||||||
C.getOuterRefSCC().replaceNodeFunction(N, *NewF);
|
C.getOuterRefSCC().replaceNodeFunction(N, *NewF);
|
||||||
FAM.clear(OldF, OldF.getName());
|
FAM.clear(OldF, OldF.getName());
|
||||||
OldF.eraseFromParent();
|
OldF.eraseFromParent();
|
||||||
|
|
||||||
PreservedAnalyses FuncPA;
|
|
||||||
FuncPA.preserveSet<CFGAnalyses>();
|
|
||||||
for (auto *U : NewF->users()) {
|
|
||||||
auto *UserF = cast<CallBase>(U)->getParent()->getParent();
|
|
||||||
FAM.invalidate(*UserF, FuncPA);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Changed |= LocalChange;
|
Changed |= LocalChange;
|
||||||
@ -1062,10 +1054,7 @@ PreservedAnalyses ArgumentPromotionPass::run(LazyCallGraph::SCC &C,
|
|||||||
if (!Changed)
|
if (!Changed)
|
||||||
return PreservedAnalyses::all();
|
return PreservedAnalyses::all();
|
||||||
|
|
||||||
PreservedAnalyses PA;
|
return PreservedAnalyses::none();
|
||||||
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
|
||||||
PA.preserveSet<AllAnalysesOn<Function>>();
|
|
||||||
return PA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -240,8 +240,7 @@ MemoryAccessKind llvm::computeFunctionBodyMemoryAccess(Function &F,
|
|||||||
|
|
||||||
/// Deduce readonly/readnone attributes for the SCC.
|
/// Deduce readonly/readnone attributes for the SCC.
|
||||||
template <typename AARGetterT>
|
template <typename AARGetterT>
|
||||||
static void addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
|
static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
// Check if any of the functions in the SCC read or write memory. If they
|
// Check if any of the functions in the SCC read or write memory. If they
|
||||||
// write memory then they can't be marked readnone or readonly.
|
// write memory then they can't be marked readnone or readonly.
|
||||||
bool ReadsMemory = false;
|
bool ReadsMemory = false;
|
||||||
@ -256,7 +255,7 @@ static void addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
|
|||||||
switch (checkFunctionMemoryAccess(*F, F->hasExactDefinition(),
|
switch (checkFunctionMemoryAccess(*F, F->hasExactDefinition(),
|
||||||
AAR, SCCNodes)) {
|
AAR, SCCNodes)) {
|
||||||
case MAK_MayWrite:
|
case MAK_MayWrite:
|
||||||
return;
|
return false;
|
||||||
case MAK_ReadOnly:
|
case MAK_ReadOnly:
|
||||||
ReadsMemory = true;
|
ReadsMemory = true;
|
||||||
break;
|
break;
|
||||||
@ -272,10 +271,11 @@ static void addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
|
|||||||
// If the SCC contains both functions that read and functions that write, then
|
// If the SCC contains both functions that read and functions that write, then
|
||||||
// we cannot add readonly attributes.
|
// we cannot add readonly attributes.
|
||||||
if (ReadsMemory && WritesMemory)
|
if (ReadsMemory && WritesMemory)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// Success! Functions in this SCC do not access memory, or only read memory.
|
// Success! Functions in this SCC do not access memory, or only read memory.
|
||||||
// Give them the appropriate attribute.
|
// Give them the appropriate attribute.
|
||||||
|
bool MadeChange = false;
|
||||||
|
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
if (F->doesNotAccessMemory())
|
if (F->doesNotAccessMemory())
|
||||||
@ -289,7 +289,7 @@ static void addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
|
|||||||
if (F->doesNotReadMemory() && WritesMemory)
|
if (F->doesNotReadMemory() && WritesMemory)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Changed.insert(F);
|
MadeChange = true;
|
||||||
|
|
||||||
// Clear out any existing attributes.
|
// Clear out any existing attributes.
|
||||||
AttrBuilder AttrsToRemove;
|
AttrBuilder AttrsToRemove;
|
||||||
@ -318,6 +318,8 @@ static void addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter,
|
|||||||
else
|
else
|
||||||
++NumReadNone;
|
++NumReadNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MadeChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -579,8 +581,9 @@ determinePointerReadAttrs(Argument *A,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deduce returned attributes for the SCC.
|
/// Deduce returned attributes for the SCC.
|
||||||
static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes,
|
static bool addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
bool Changed = false;
|
||||||
|
|
||||||
// Check each function in turn, determining if an argument is always returned.
|
// Check each function in turn, determining if an argument is always returned.
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
// We can infer and propagate function attributes only when we know that the
|
// We can infer and propagate function attributes only when we know that the
|
||||||
@ -620,9 +623,11 @@ static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
auto *A = cast<Argument>(RetArg);
|
auto *A = cast<Argument>(RetArg);
|
||||||
A->addAttr(Attribute::Returned);
|
A->addAttr(Attribute::Returned);
|
||||||
++NumReturned;
|
++NumReturned;
|
||||||
Changed.insert(F);
|
Changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a callsite has arguments that are also arguments to the parent function,
|
/// If a callsite has arguments that are also arguments to the parent function,
|
||||||
@ -688,8 +693,9 @@ static bool addReadAttr(Argument *A, Attribute::AttrKind R) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deduce nocapture attributes for the SCC.
|
/// Deduce nocapture attributes for the SCC.
|
||||||
static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
static bool addArgumentAttrs(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
bool Changed = false;
|
||||||
|
|
||||||
ArgumentGraph AG;
|
ArgumentGraph AG;
|
||||||
|
|
||||||
// Check each function in turn, determining which pointer arguments are not
|
// Check each function in turn, determining which pointer arguments are not
|
||||||
@ -701,8 +707,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
if (!F->hasExactDefinition())
|
if (!F->hasExactDefinition())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (addArgumentAttrsFromCallsites(*F))
|
Changed |= addArgumentAttrsFromCallsites(*F);
|
||||||
Changed.insert(F);
|
|
||||||
|
|
||||||
// Functions that are readonly (or readnone) and nounwind and don't return
|
// Functions that are readonly (or readnone) and nounwind and don't return
|
||||||
// a value can't capture arguments. Don't analyze them.
|
// a value can't capture arguments. Don't analyze them.
|
||||||
@ -713,7 +718,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) {
|
if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) {
|
||||||
A->addAttr(Attribute::NoCapture);
|
A->addAttr(Attribute::NoCapture);
|
||||||
++NumNoCapture;
|
++NumNoCapture;
|
||||||
Changed.insert(F);
|
Changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -732,7 +737,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
// If it's trivially not captured, mark it nocapture now.
|
// If it's trivially not captured, mark it nocapture now.
|
||||||
A->addAttr(Attribute::NoCapture);
|
A->addAttr(Attribute::NoCapture);
|
||||||
++NumNoCapture;
|
++NumNoCapture;
|
||||||
Changed.insert(F);
|
Changed = true;
|
||||||
} else {
|
} else {
|
||||||
// If it's not trivially captured and not trivially not captured,
|
// If it's not trivially captured and not trivially not captured,
|
||||||
// then it must be calling into another function in our SCC. Save
|
// then it must be calling into another function in our SCC. Save
|
||||||
@ -756,8 +761,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
Self.insert(&*A);
|
Self.insert(&*A);
|
||||||
Attribute::AttrKind R = determinePointerReadAttrs(&*A, Self);
|
Attribute::AttrKind R = determinePointerReadAttrs(&*A, Self);
|
||||||
if (R != Attribute::None)
|
if (R != Attribute::None)
|
||||||
if (addReadAttr(A, R))
|
Changed = addReadAttr(A, R);
|
||||||
Changed.insert(F);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -781,7 +785,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
Argument *A = ArgumentSCC[0]->Definition;
|
Argument *A = ArgumentSCC[0]->Definition;
|
||||||
A->addAttr(Attribute::NoCapture);
|
A->addAttr(Attribute::NoCapture);
|
||||||
++NumNoCapture;
|
++NumNoCapture;
|
||||||
Changed.insert(A->getParent());
|
Changed = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -823,7 +827,7 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
Argument *A = ArgumentSCC[i]->Definition;
|
Argument *A = ArgumentSCC[i]->Definition;
|
||||||
A->addAttr(Attribute::NoCapture);
|
A->addAttr(Attribute::NoCapture);
|
||||||
++NumNoCapture;
|
++NumNoCapture;
|
||||||
Changed.insert(A->getParent());
|
Changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We also want to compute readonly/readnone. With a small number of false
|
// We also want to compute readonly/readnone. With a small number of false
|
||||||
@ -854,11 +858,12 @@ static void addArgumentAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
if (ReadAttr != Attribute::None) {
|
if (ReadAttr != Attribute::None) {
|
||||||
for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
|
for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
|
||||||
Argument *A = ArgumentSCC[i]->Definition;
|
Argument *A = ArgumentSCC[i]->Definition;
|
||||||
if (addReadAttr(A, ReadAttr))
|
Changed = addReadAttr(A, ReadAttr);
|
||||||
Changed.insert(A->getParent());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether a function is "malloc-like".
|
/// Tests whether a function is "malloc-like".
|
||||||
@ -929,8 +934,7 @@ static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deduce noalias attributes for the SCC.
|
/// Deduce noalias attributes for the SCC.
|
||||||
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes,
|
static bool addNoAliasAttrs(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
// Check each function in turn, determining which functions return noalias
|
// Check each function in turn, determining which functions return noalias
|
||||||
// pointers.
|
// pointers.
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
@ -942,7 +946,7 @@ static void addNoAliasAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
// definition we'll get at link time is *exactly* the definition we see now.
|
// definition we'll get at link time is *exactly* the definition we see now.
|
||||||
// For more details, see GlobalValue::mayBeDerefined.
|
// For more details, see GlobalValue::mayBeDerefined.
|
||||||
if (!F->hasExactDefinition())
|
if (!F->hasExactDefinition())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// We annotate noalias return values, which are only applicable to
|
// We annotate noalias return values, which are only applicable to
|
||||||
// pointer types.
|
// pointer types.
|
||||||
@ -950,9 +954,10 @@ static void addNoAliasAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!isFunctionMallocLike(F, SCCNodes))
|
if (!isFunctionMallocLike(F, SCCNodes))
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MadeChange = false;
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
if (F->returnDoesNotAlias() ||
|
if (F->returnDoesNotAlias() ||
|
||||||
!F->getReturnType()->isPointerTy())
|
!F->getReturnType()->isPointerTy())
|
||||||
@ -960,8 +965,10 @@ static void addNoAliasAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
|
|
||||||
F->setReturnDoesNotAlias();
|
F->setReturnDoesNotAlias();
|
||||||
++NumNoAlias;
|
++NumNoAlias;
|
||||||
Changed.insert(F);
|
MadeChange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MadeChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests whether this function is known to not return null.
|
/// Tests whether this function is known to not return null.
|
||||||
@ -1037,12 +1044,13 @@ static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deduce nonnull attributes for the SCC.
|
/// Deduce nonnull attributes for the SCC.
|
||||||
static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
|
static bool addNonNullAttrs(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
// Speculative that all functions in the SCC return only nonnull
|
// Speculative that all functions in the SCC return only nonnull
|
||||||
// pointers. We may refute this as we analyze functions.
|
// pointers. We may refute this as we analyze functions.
|
||||||
bool SCCReturnsNonNull = true;
|
bool SCCReturnsNonNull = true;
|
||||||
|
|
||||||
|
bool MadeChange = false;
|
||||||
|
|
||||||
// Check each function in turn, determining which functions return nonnull
|
// Check each function in turn, determining which functions return nonnull
|
||||||
// pointers.
|
// pointers.
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
@ -1055,7 +1063,7 @@ static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
// definition we'll get at link time is *exactly* the definition we see now.
|
// definition we'll get at link time is *exactly* the definition we see now.
|
||||||
// For more details, see GlobalValue::mayBeDerefined.
|
// For more details, see GlobalValue::mayBeDerefined.
|
||||||
if (!F->hasExactDefinition())
|
if (!F->hasExactDefinition())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// We annotate nonnull return values, which are only applicable to
|
// We annotate nonnull return values, which are only applicable to
|
||||||
// pointer types.
|
// pointer types.
|
||||||
@ -1071,7 +1079,7 @@ static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
<< " as nonnull\n");
|
<< " as nonnull\n");
|
||||||
F->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
|
F->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
|
||||||
++NumNonNullReturn;
|
++NumNonNullReturn;
|
||||||
Changed.insert(F);
|
MadeChange = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1090,9 +1098,11 @@ static void addNonNullAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
LLVM_DEBUG(dbgs() << "SCC marking " << F->getName() << " as nonnull\n");
|
LLVM_DEBUG(dbgs() << "SCC marking " << F->getName() << " as nonnull\n");
|
||||||
F->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
|
F->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull);
|
||||||
++NumNonNullReturn;
|
++NumNonNullReturn;
|
||||||
Changed.insert(F);
|
MadeChange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MadeChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -1145,13 +1155,12 @@ public:
|
|||||||
InferenceDescriptors.push_back(AttrInference);
|
InferenceDescriptors.push_back(AttrInference);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(const SCCNodeSet &SCCNodes, SmallSetVector<Function *, 8> &Changed);
|
bool run(const SCCNodeSet &SCCNodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Perform all the requested attribute inference actions according to the
|
/// Perform all the requested attribute inference actions according to the
|
||||||
/// attribute predicates stored before.
|
/// attribute predicates stored before.
|
||||||
void AttributeInferer::run(const SCCNodeSet &SCCNodes,
|
bool AttributeInferer::run(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
SmallVector<InferenceDescriptor, 4> InferInSCC = InferenceDescriptors;
|
SmallVector<InferenceDescriptor, 4> InferInSCC = InferenceDescriptors;
|
||||||
// Go through all the functions in SCC and check corresponding attribute
|
// Go through all the functions in SCC and check corresponding attribute
|
||||||
// assumptions for each of them. Attributes that are invalid for this SCC
|
// assumptions for each of them. Attributes that are invalid for this SCC
|
||||||
@ -1160,7 +1169,7 @@ void AttributeInferer::run(const SCCNodeSet &SCCNodes,
|
|||||||
|
|
||||||
// No attributes whose assumptions are still valid - done.
|
// No attributes whose assumptions are still valid - done.
|
||||||
if (InferInSCC.empty())
|
if (InferInSCC.empty())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// Check if our attributes ever need scanning/can be scanned.
|
// Check if our attributes ever need scanning/can be scanned.
|
||||||
llvm::erase_if(InferInSCC, [F](const InferenceDescriptor &ID) {
|
llvm::erase_if(InferInSCC, [F](const InferenceDescriptor &ID) {
|
||||||
@ -1203,8 +1212,9 @@ void AttributeInferer::run(const SCCNodeSet &SCCNodes,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (InferInSCC.empty())
|
if (InferInSCC.empty())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
|
bool Changed = false;
|
||||||
for (Function *F : SCCNodes)
|
for (Function *F : SCCNodes)
|
||||||
// At this point InferInSCC contains only functions that were either:
|
// At this point InferInSCC contains only functions that were either:
|
||||||
// - explicitly skipped from scan/inference, or
|
// - explicitly skipped from scan/inference, or
|
||||||
@ -1213,9 +1223,10 @@ void AttributeInferer::run(const SCCNodeSet &SCCNodes,
|
|||||||
for (auto &ID : InferInSCC) {
|
for (auto &ID : InferInSCC) {
|
||||||
if (ID.SkipFunction(*F))
|
if (ID.SkipFunction(*F))
|
||||||
continue;
|
continue;
|
||||||
Changed.insert(F);
|
Changed = true;
|
||||||
ID.SetAttribute(*F);
|
ID.SetAttribute(*F);
|
||||||
}
|
}
|
||||||
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SCCNodesResult {
|
struct SCCNodesResult {
|
||||||
@ -1271,8 +1282,7 @@ static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes) {
|
|||||||
/// Attempt to remove convergent function attribute when possible.
|
/// Attempt to remove convergent function attribute when possible.
|
||||||
///
|
///
|
||||||
/// Returns true if any changes to function attributes were made.
|
/// Returns true if any changes to function attributes were made.
|
||||||
static void inferConvergent(const SCCNodeSet &SCCNodes,
|
static bool inferConvergent(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
AttributeInferer AI;
|
AttributeInferer AI;
|
||||||
|
|
||||||
// Request to remove the convergent attribute from all functions in the SCC
|
// Request to remove the convergent attribute from all functions in the SCC
|
||||||
@ -1295,7 +1305,7 @@ static void inferConvergent(const SCCNodeSet &SCCNodes,
|
|||||||
},
|
},
|
||||||
/* RequiresExactDefinition= */ false});
|
/* RequiresExactDefinition= */ false});
|
||||||
// Perform all the requested attribute inference actions.
|
// Perform all the requested attribute inference actions.
|
||||||
AI.run(SCCNodes, Changed);
|
return AI.run(SCCNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Infer attributes from all functions in the SCC by scanning every
|
/// Infer attributes from all functions in the SCC by scanning every
|
||||||
@ -1304,9 +1314,7 @@ static void inferConvergent(const SCCNodeSet &SCCNodes,
|
|||||||
/// - addition of NoUnwind attribute
|
/// - addition of NoUnwind attribute
|
||||||
///
|
///
|
||||||
/// Returns true if any changes to function attributes were made.
|
/// Returns true if any changes to function attributes were made.
|
||||||
static void
|
static bool inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes) {
|
||||||
inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes,
|
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
AttributeInferer AI;
|
AttributeInferer AI;
|
||||||
|
|
||||||
if (!DisableNoUnwindInference)
|
if (!DisableNoUnwindInference)
|
||||||
@ -1355,20 +1363,19 @@ inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes,
|
|||||||
/* RequiresExactDefinition= */ true});
|
/* RequiresExactDefinition= */ true});
|
||||||
|
|
||||||
// Perform all the requested attribute inference actions.
|
// Perform all the requested attribute inference actions.
|
||||||
AI.run(SCCNodes, Changed);
|
return AI.run(SCCNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
|
static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
// Try and identify functions that do not recurse.
|
// Try and identify functions that do not recurse.
|
||||||
|
|
||||||
// If the SCC contains multiple nodes we know for sure there is recursion.
|
// If the SCC contains multiple nodes we know for sure there is recursion.
|
||||||
if (SCCNodes.size() != 1)
|
if (SCCNodes.size() != 1)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
Function *F = *SCCNodes.begin();
|
Function *F = *SCCNodes.begin();
|
||||||
if (!F || !F->hasExactDefinition() || F->doesNotRecurse())
|
if (!F || !F->hasExactDefinition() || F->doesNotRecurse())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// If all of the calls in F are identifiable and are to norecurse functions, F
|
// If all of the calls in F are identifiable and are to norecurse functions, F
|
||||||
// is norecurse. This check also detects self-recursion as F is not currently
|
// is norecurse. This check also detects self-recursion as F is not currently
|
||||||
@ -1379,7 +1386,7 @@ static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
Function *Callee = CB->getCalledFunction();
|
Function *Callee = CB->getCalledFunction();
|
||||||
if (!Callee || Callee == F || !Callee->doesNotRecurse())
|
if (!Callee || Callee == F || !Callee->doesNotRecurse())
|
||||||
// Function calls a potentially recursive function.
|
// Function calls a potentially recursive function.
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every call was to a non-recursive function other than this function, and
|
// Every call was to a non-recursive function other than this function, and
|
||||||
@ -1387,7 +1394,7 @@ static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
// recurse.
|
// recurse.
|
||||||
F->setDoesNotRecurse();
|
F->setDoesNotRecurse();
|
||||||
++NumNoRecurse;
|
++NumNoRecurse;
|
||||||
Changed.insert(F);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool instructionDoesNotReturn(Instruction &I) {
|
static bool instructionDoesNotReturn(Instruction &I) {
|
||||||
@ -1405,8 +1412,9 @@ static bool basicBlockCanReturn(BasicBlock &BB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the noreturn function attribute if possible.
|
// Set the noreturn function attribute if possible.
|
||||||
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
|
static bool addNoReturnAttrs(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
bool Changed = false;
|
||||||
|
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
if (!F || !F->hasExactDefinition() || F->hasFnAttribute(Attribute::Naked) ||
|
if (!F || !F->hasExactDefinition() || F->hasFnAttribute(Attribute::Naked) ||
|
||||||
F->doesNotReturn())
|
F->doesNotReturn())
|
||||||
@ -1416,9 +1424,11 @@ static void addNoReturnAttrs(const SCCNodeSet &SCCNodes,
|
|||||||
// FIXME: this doesn't handle recursion or unreachable blocks.
|
// FIXME: this doesn't handle recursion or unreachable blocks.
|
||||||
if (none_of(*F, basicBlockCanReturn)) {
|
if (none_of(*F, basicBlockCanReturn)) {
|
||||||
F->setDoesNotReturn();
|
F->setDoesNotReturn();
|
||||||
Changed.insert(F);
|
Changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool functionWillReturn(const Function &F) {
|
static bool functionWillReturn(const Function &F) {
|
||||||
@ -1451,16 +1461,19 @@ static bool functionWillReturn(const Function &F) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the willreturn function attribute if possible.
|
// Set the willreturn function attribute if possible.
|
||||||
static void addWillReturn(const SCCNodeSet &SCCNodes,
|
static bool addWillReturn(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
bool Changed = false;
|
||||||
|
|
||||||
for (Function *F : SCCNodes) {
|
for (Function *F : SCCNodes) {
|
||||||
if (!F || F->willReturn() || !functionWillReturn(*F))
|
if (!F || F->willReturn() || !functionWillReturn(*F))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
F->setWillReturn();
|
F->setWillReturn();
|
||||||
NumWillReturn++;
|
NumWillReturn++;
|
||||||
Changed.insert(F);
|
Changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if this is an atomic which has an ordering stronger than
|
// Return true if this is an atomic which has an ordering stronger than
|
||||||
@ -1519,8 +1532,7 @@ static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Infer the nosync attribute.
|
// Infer the nosync attribute.
|
||||||
static void addNoSyncAttr(const SCCNodeSet &SCCNodes,
|
static bool addNoSyncAttr(const SCCNodeSet &SCCNodes) {
|
||||||
SmallSetVector<Function *, 8> &Changed) {
|
|
||||||
AttributeInferer AI;
|
AttributeInferer AI;
|
||||||
AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
|
AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
|
||||||
Attribute::NoSync,
|
Attribute::NoSync,
|
||||||
@ -1537,7 +1549,7 @@ static void addNoSyncAttr(const SCCNodeSet &SCCNodes,
|
|||||||
++NumNoSync;
|
++NumNoSync;
|
||||||
},
|
},
|
||||||
/* RequiresExactDefinition= */ true});
|
/* RequiresExactDefinition= */ true});
|
||||||
AI.run(SCCNodes, Changed);
|
return AI.run(SCCNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
|
static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
|
||||||
@ -1570,33 +1582,32 @@ static SCCNodesResult createSCCNodeSet(ArrayRef<Function *> Functions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename AARGetterT>
|
template <typename AARGetterT>
|
||||||
static SmallSetVector<Function *, 8>
|
static bool deriveAttrsInPostOrder(ArrayRef<Function *> Functions,
|
||||||
deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter) {
|
AARGetterT &&AARGetter) {
|
||||||
SCCNodesResult Nodes = createSCCNodeSet(Functions);
|
SCCNodesResult Nodes = createSCCNodeSet(Functions);
|
||||||
|
bool Changed = false;
|
||||||
|
|
||||||
// Bail if the SCC only contains optnone functions.
|
// Bail if the SCC only contains optnone functions.
|
||||||
if (Nodes.SCCNodes.empty())
|
if (Nodes.SCCNodes.empty())
|
||||||
return {};
|
return Changed;
|
||||||
|
|
||||||
SmallSetVector<Function *, 8> Changed;
|
Changed |= addArgumentReturnedAttrs(Nodes.SCCNodes);
|
||||||
|
Changed |= addReadAttrs(Nodes.SCCNodes, AARGetter);
|
||||||
addArgumentReturnedAttrs(Nodes.SCCNodes, Changed);
|
Changed |= addArgumentAttrs(Nodes.SCCNodes);
|
||||||
addReadAttrs(Nodes.SCCNodes, AARGetter, Changed);
|
Changed |= inferConvergent(Nodes.SCCNodes);
|
||||||
addArgumentAttrs(Nodes.SCCNodes, Changed);
|
Changed |= addNoReturnAttrs(Nodes.SCCNodes);
|
||||||
inferConvergent(Nodes.SCCNodes, Changed);
|
Changed |= addWillReturn(Nodes.SCCNodes);
|
||||||
addNoReturnAttrs(Nodes.SCCNodes, Changed);
|
|
||||||
addWillReturn(Nodes.SCCNodes, Changed);
|
|
||||||
|
|
||||||
// If we have no external nodes participating in the SCC, we can deduce some
|
// If we have no external nodes participating in the SCC, we can deduce some
|
||||||
// more precise attributes as well.
|
// more precise attributes as well.
|
||||||
if (!Nodes.HasUnknownCall) {
|
if (!Nodes.HasUnknownCall) {
|
||||||
addNoAliasAttrs(Nodes.SCCNodes, Changed);
|
Changed |= addNoAliasAttrs(Nodes.SCCNodes);
|
||||||
addNonNullAttrs(Nodes.SCCNodes, Changed);
|
Changed |= addNonNullAttrs(Nodes.SCCNodes);
|
||||||
inferAttrsFromFunctionBodies(Nodes.SCCNodes, Changed);
|
Changed |= inferAttrsFromFunctionBodies(Nodes.SCCNodes);
|
||||||
addNoRecurseAttrs(Nodes.SCCNodes, Changed);
|
Changed |= addNoRecurseAttrs(Nodes.SCCNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
addNoSyncAttr(Nodes.SCCNodes, Changed);
|
Changed |= addNoSyncAttr(Nodes.SCCNodes);
|
||||||
|
|
||||||
// Finally, infer the maximal set of attributes from the ones we've inferred
|
// Finally, infer the maximal set of attributes from the ones we've inferred
|
||||||
// above. This is handling the cases where one attribute on a signature
|
// above. This is handling the cases where one attribute on a signature
|
||||||
@ -1604,8 +1615,7 @@ deriveAttrsInPostOrder(ArrayRef<Function *> Functions, AARGetterT &&AARGetter) {
|
|||||||
// the later is missing (or simply less sophisticated).
|
// the later is missing (or simply less sophisticated).
|
||||||
for (Function *F : Nodes.SCCNodes)
|
for (Function *F : Nodes.SCCNodes)
|
||||||
if (F)
|
if (F)
|
||||||
if (inferAttributesFromOthers(*F))
|
Changed |= inferAttributesFromOthers(*F);
|
||||||
Changed.insert(F);
|
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
@ -1628,24 +1638,14 @@ PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
|
|||||||
Functions.push_back(&N.getFunction());
|
Functions.push_back(&N.getFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ChangedFunctions = deriveAttrsInPostOrder(Functions, AARGetter);
|
if (deriveAttrsInPostOrder(Functions, AARGetter)) {
|
||||||
if (ChangedFunctions.empty()) {
|
// We have not changed the call graph or removed/added functions.
|
||||||
return PreservedAnalyses::all();
|
PreservedAnalyses PA;
|
||||||
|
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
||||||
|
return PA;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate analyses for modified functions so that we don't have to
|
return PreservedAnalyses::all();
|
||||||
// invalidate all analyses for all functions in this SCC.
|
|
||||||
PreservedAnalyses FuncPA;
|
|
||||||
// We haven't changed the CFG for modified functions.
|
|
||||||
FuncPA.preserveSet<CFGAnalyses>();
|
|
||||||
for (Function *Changed : ChangedFunctions)
|
|
||||||
FAM.invalidate(*Changed, FuncPA);
|
|
||||||
|
|
||||||
// We have not changed the call graph or removed/added functions.
|
|
||||||
PreservedAnalyses PA;
|
|
||||||
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
|
||||||
PA.preserveSet<AllAnalysesOn<Function>>();
|
|
||||||
return PA;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -1690,7 +1690,7 @@ static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) {
|
|||||||
Functions.push_back(I->getFunction());
|
Functions.push_back(I->getFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
return !deriveAttrsInPostOrder(Functions, AARGetter).empty();
|
return deriveAttrsInPostOrder(Functions, AARGetter);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
|
bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
|
||||||
|
@ -951,10 +951,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|||||||
UR.InlinedInternalEdges.insert({&N, OldC});
|
UR.InlinedInternalEdges.insert({&N, OldC});
|
||||||
}
|
}
|
||||||
InlinedCallees.clear();
|
InlinedCallees.clear();
|
||||||
|
|
||||||
// Invalidate analyses for this function now so that we don't have to
|
|
||||||
// invalidate analyses for all functions in this SCC later.
|
|
||||||
FAM.invalidate(F, PreservedAnalyses::none());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've finished inlining all of the calls across this SCC, delete
|
// Now that we've finished inlining all of the calls across this SCC, delete
|
||||||
@ -994,12 +990,10 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
|||||||
if (!Changed)
|
if (!Changed)
|
||||||
return PreservedAnalyses::all();
|
return PreservedAnalyses::all();
|
||||||
|
|
||||||
PreservedAnalyses PA;
|
|
||||||
// Even if we change the IR, we update the core CGSCC data structures and so
|
// Even if we change the IR, we update the core CGSCC data structures and so
|
||||||
// can preserve the proxy to the function analysis manager.
|
// can preserve the proxy to the function analysis manager.
|
||||||
|
PreservedAnalyses PA;
|
||||||
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
|
||||||
// We have already invalidated all analyses on modified functions.
|
|
||||||
PA.preserveSet<AllAnalysesOn<Function>>();
|
|
||||||
return PA;
|
return PA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,11 +398,19 @@
|
|||||||
; NEWPM-NEXT: Running pass: InlinerPass on (f)
|
; NEWPM-NEXT: Running pass: InlinerPass on (f)
|
||||||
; NEWPM-NEXT: Running pass: PostOrderFunctionAttrsPass on (f)
|
; NEWPM-NEXT: Running pass: PostOrderFunctionAttrsPass on (f)
|
||||||
; NEWPM-NEXT: Running analysis: AAManager on f
|
; NEWPM-NEXT: Running analysis: AAManager on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: PreservedCFGCheckerAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: DominatorTreeAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: BasicAA on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: AAManager on f
|
||||||
; NEWPM-NEXT: Running pass: ArgumentPromotionPass on (f)
|
; NEWPM-NEXT: Running pass: ArgumentPromotionPass on (f)
|
||||||
; NEWPM-NEXT: Running pass: OpenMPOptCGSCCPass on (f)
|
; NEWPM-NEXT: Running pass: OpenMPOptCGSCCPass on (f)
|
||||||
|
; NEWPM-NEXT: Running analysis: PreservedCFGCheckerAnalysis on f
|
||||||
; NEWPM-NEXT: Running pass: SROA on f
|
; NEWPM-NEXT: Running pass: SROA on f
|
||||||
|
; NEWPM-NEXT: Running analysis: DominatorTreeAnalysis on f
|
||||||
; NEWPM-NEXT: Running pass: EarlyCSEPass on f
|
; NEWPM-NEXT: Running pass: EarlyCSEPass on f
|
||||||
; NEWPM-NEXT: Running analysis: MemorySSAAnalysis on f
|
; NEWPM-NEXT: Running analysis: MemorySSAAnalysis on f
|
||||||
|
; NEWPM-NEXT: Running analysis: AAManager on f
|
||||||
|
; NEWPM-NEXT: Running analysis: BasicAA on f
|
||||||
; NEWPM-NEXT: Running pass: SpeculativeExecutionPass on f
|
; NEWPM-NEXT: Running pass: SpeculativeExecutionPass on f
|
||||||
; NEWPM-NEXT: Running pass: JumpThreadingPass on f
|
; NEWPM-NEXT: Running pass: JumpThreadingPass on f
|
||||||
; NEWPM-NEXT: Running analysis: LazyValueAnalysis on f
|
; NEWPM-NEXT: Running analysis: LazyValueAnalysis on f
|
||||||
@ -444,6 +452,16 @@
|
|||||||
; NEWPM-NEXT: Running pass: LCSSAPass on f
|
; NEWPM-NEXT: Running pass: LCSSAPass on f
|
||||||
; NEWPM-NEXT: Running pass: SimplifyCFGPass on f
|
; NEWPM-NEXT: Running pass: SimplifyCFGPass on f
|
||||||
; NEWPM-NEXT: Running pass: InstCombinePass on f
|
; NEWPM-NEXT: Running pass: InstCombinePass on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: PreservedCFGCheckerAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: DominatorTreeAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: BasicAA on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: AAManager on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: MemorySSAAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: LoopAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: PhiValuesAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: MemoryDependenceAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: DemandedBitsAnalysis on f
|
||||||
|
; NEWPM-NEXT: Invalidating analysis: PostDominatorTreeAnalysis on f
|
||||||
; NEWPM-NEXT: Invalidating analysis: CallGraphAnalysis on
|
; NEWPM-NEXT: Invalidating analysis: CallGraphAnalysis on
|
||||||
; NEWPM-NEXT: Running pass: GlobalOptPass on
|
; NEWPM-NEXT: Running pass: GlobalOptPass on
|
||||||
; NEWPM-NEXT: Running pass: GlobalDCEPass on
|
; NEWPM-NEXT: Running pass: GlobalDCEPass on
|
||||||
@ -451,9 +469,14 @@
|
|||||||
; NEWPM-NEXT: Running pass: ReversePostOrderFunctionAttrsPass on
|
; NEWPM-NEXT: Running pass: ReversePostOrderFunctionAttrsPass on
|
||||||
; NEWPM-NEXT: Running analysis: CallGraphAnalysis on
|
; NEWPM-NEXT: Running analysis: CallGraphAnalysis on
|
||||||
; NEWPM-NEXT: Running pass: RequireAnalysisPass<{{.*}}GlobalsAA
|
; NEWPM-NEXT: Running pass: RequireAnalysisPass<{{.*}}GlobalsAA
|
||||||
|
; NEWPM-NEXT: Running analysis: PreservedCFGCheckerAnalysis on f
|
||||||
; NEWPM-NEXT: Running pass: Float2IntPass on f
|
; NEWPM-NEXT: Running pass: Float2IntPass on f
|
||||||
|
; NEWPM-NEXT: Running analysis: DominatorTreeAnalysis on f
|
||||||
; NEWPM-NEXT: Running pass: LowerConstantIntrinsicsPass on f
|
; NEWPM-NEXT: Running pass: LowerConstantIntrinsicsPass on f
|
||||||
; NEWPM-NEXT: Running pass: LowerMatrixIntrinsicsPass on f
|
; NEWPM-NEXT: Running pass: LowerMatrixIntrinsicsPass on f
|
||||||
|
; NEWPM-NEXT: Running analysis: AAManager on f
|
||||||
|
; NEWPM-NEXT: Running analysis: BasicAA on f
|
||||||
|
; NEWPM-NEXT: Running analysis: LoopAnalysis on f
|
||||||
; NEWPM-NEXT: Running pass: EarlyCSEPass on f
|
; NEWPM-NEXT: Running pass: EarlyCSEPass on f
|
||||||
; NEWPM-NEXT: Running pass: LoopSimplifyPass on f
|
; NEWPM-NEXT: Running pass: LoopSimplifyPass on f
|
||||||
; NEWPM-NEXT: Running pass: LCSSAPass on f
|
; NEWPM-NEXT: Running pass: LCSSAPass on f
|
||||||
@ -464,6 +487,9 @@
|
|||||||
; NEWPM-NEXT: Running pass: LoopVectorizePass on f
|
; NEWPM-NEXT: Running pass: LoopVectorizePass on f
|
||||||
; NEWPM-NEXT: Running analysis: BlockFrequencyAnalysis on f
|
; NEWPM-NEXT: Running analysis: BlockFrequencyAnalysis on f
|
||||||
; NEWPM-NEXT: Running analysis: BranchProbabilityAnalysis on f
|
; NEWPM-NEXT: Running analysis: BranchProbabilityAnalysis on f
|
||||||
|
; NEWPM-NEXT: Running analysis: PostDominatorTreeAnalysis on f
|
||||||
|
; NEWPM-NEXT: Running analysis: DemandedBitsAnalysis on f
|
||||||
|
; NEWPM-NEXT: Running analysis: MemorySSAAnalysis on f
|
||||||
; NEWPM-NEXT: Running pass: LoopLoadEliminationPass on f
|
; NEWPM-NEXT: Running pass: LoopLoadEliminationPass on f
|
||||||
; NEWPM-NEXT: Running pass: InstCombinePass on f
|
; NEWPM-NEXT: Running pass: InstCombinePass on f
|
||||||
; NEWPM-NEXT: Running pass: SimplifyCFGPass on f
|
; NEWPM-NEXT: Running pass: SimplifyCFGPass on f
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
; RUN: opt -passes=inliner-wrapper < %s -disable-output -debug-pass-manager 2>&1 | FileCheck %s
|
|
||||||
|
|
||||||
; We shouldn't invalidate any function analyses on g since it's never modified.
|
|
||||||
|
|
||||||
; CHECK-NOT: Invalidating{{.*}} on g
|
|
||||||
; CHECK: Invalidating{{.*}} on f
|
|
||||||
; CHECK-NOT: Invalidating{{.*}} on g
|
|
||||||
|
|
||||||
define void @f() {
|
|
||||||
call void @g()
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @g() alwaysinline {
|
|
||||||
call void @f()
|
|
||||||
ret void
|
|
||||||
}
|
|
@ -8,11 +8,11 @@
|
|||||||
;
|
;
|
||||||
; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
|
; CHECK: Running pass: InlinerPass on (test1_f, test1_g, test1_h)
|
||||||
; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
|
; CHECK: Running analysis: DominatorTreeAnalysis on test1_f
|
||||||
|
; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
|
||||||
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f
|
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_f
|
||||||
; CHECK: Invalidating analysis: LoopAnalysis on test1_f
|
; CHECK: Invalidating analysis: LoopAnalysis on test1_f
|
||||||
; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_f
|
; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_f
|
||||||
; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_f
|
; CHECK: Invalidating analysis: BlockFrequencyAnalysis on test1_f
|
||||||
; CHECK: Running analysis: DominatorTreeAnalysis on test1_g
|
|
||||||
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g
|
; CHECK: Invalidating analysis: DominatorTreeAnalysis on test1_g
|
||||||
; CHECK: Invalidating analysis: LoopAnalysis on test1_g
|
; CHECK: Invalidating analysis: LoopAnalysis on test1_g
|
||||||
; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_g
|
; CHECK: Invalidating analysis: BranchProbabilityAnalysis on test1_g
|
||||||
@ -29,6 +29,7 @@
|
|||||||
; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_h
|
; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_h
|
||||||
; CHECK-NOT: Invalidating analysis:
|
; CHECK-NOT: Invalidating analysis:
|
||||||
; CHECK: Running pass: DominatorTreeVerifierPass on test1_f
|
; CHECK: Running pass: DominatorTreeVerifierPass on test1_f
|
||||||
|
; CHECK-NEXT: Running analysis: DominatorTreeAnalysis on test1_f
|
||||||
|
|
||||||
; An external function used to control branches.
|
; An external function used to control branches.
|
||||||
declare i1 @flag()
|
declare i1 @flag()
|
||||||
|
Loading…
Reference in New Issue
Block a user