mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 13:35:38 +08:00
Revert "[CGSCC] Detect devirtualization in more cases"
This reverts commit 14a68b4aa9.
Causes building self hosted clang to crash when using NPM.
This commit is contained in:
@@ -90,7 +90,6 @@
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/PriorityWorklist.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
@@ -315,16 +314,6 @@ struct CGSCCUpdateResult {
|
||||
/// for a better technique.
|
||||
SmallDenseSet<std::pair<LazyCallGraph::Node *, LazyCallGraph::SCC *>, 4>
|
||||
&InlinedInternalEdges;
|
||||
|
||||
/// Weak VHs to keep track of indirect calls for the purposes of detecting
|
||||
/// devirtualization.
|
||||
///
|
||||
/// This is a map to avoid having duplicate entries. If a Value is
|
||||
/// deallocated, its corresponding WeakTrackingVH will be nulled out. When
|
||||
/// checking if a Value is in the map or not, also check if the corresponding
|
||||
/// WeakTrackingVH is null to avoid issues with a new Value sharing the same
|
||||
/// address as a deallocated one.
|
||||
SmallMapVector<Value *, WeakTrackingVH, 16> IndirectVHs;
|
||||
};
|
||||
|
||||
/// The core module pass which does a post-order walk of the SCCs and
|
||||
@@ -607,6 +596,9 @@ public:
|
||||
// a pointer that we can update.
|
||||
LazyCallGraph::SCC *C = &InitialC;
|
||||
|
||||
// Collect value handles for all of the indirect call sites.
|
||||
SmallVector<WeakTrackingVH, 8> CallHandles;
|
||||
|
||||
// Struct to track the counts of direct and indirect calls in each function
|
||||
// of the SCC.
|
||||
struct CallCount {
|
||||
@@ -616,37 +608,35 @@ public:
|
||||
|
||||
// Put value handles on all of the indirect calls and return the number of
|
||||
// direct calls for each function in the SCC.
|
||||
auto ScanSCC =
|
||||
[](LazyCallGraph::SCC &C,
|
||||
SmallMapVector<Value *, WeakTrackingVH, 16> &CallHandles) {
|
||||
assert(CallHandles.empty() &&
|
||||
"Must start with a clear set of handles.");
|
||||
auto ScanSCC = [](LazyCallGraph::SCC &C,
|
||||
SmallVectorImpl<WeakTrackingVH> &CallHandles) {
|
||||
assert(CallHandles.empty() && "Must start with a clear set of handles.");
|
||||
|
||||
SmallDenseMap<Function *, CallCount> CallCounts;
|
||||
CallCount CountLocal = {0, 0};
|
||||
for (LazyCallGraph::Node &N : C) {
|
||||
CallCount &Count =
|
||||
CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal))
|
||||
.first->second;
|
||||
for (Instruction &I : instructions(N.getFunction()))
|
||||
if (auto *CB = dyn_cast<CallBase>(&I)) {
|
||||
if (CB->getCalledFunction()) {
|
||||
++Count.Direct;
|
||||
} else {
|
||||
++Count.Indirect;
|
||||
CallHandles.insert({CB, WeakTrackingVH(CB)});
|
||||
}
|
||||
}
|
||||
SmallDenseMap<Function *, CallCount> CallCounts;
|
||||
CallCount CountLocal = {0, 0};
|
||||
for (LazyCallGraph::Node &N : C) {
|
||||
CallCount &Count =
|
||||
CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal))
|
||||
.first->second;
|
||||
for (Instruction &I : instructions(N.getFunction()))
|
||||
if (auto *CB = dyn_cast<CallBase>(&I)) {
|
||||
if (CB->getCalledFunction()) {
|
||||
++Count.Direct;
|
||||
} else {
|
||||
++Count.Indirect;
|
||||
CallHandles.push_back(WeakTrackingVH(&I));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CallCounts;
|
||||
};
|
||||
return CallCounts;
|
||||
};
|
||||
|
||||
UR.IndirectVHs.clear();
|
||||
// Populate the initial call handles and get the initial call counts.
|
||||
auto CallCounts = ScanSCC(*C, UR.IndirectVHs);
|
||||
auto CallCounts = ScanSCC(*C, CallHandles);
|
||||
|
||||
for (int Iteration = 0;; ++Iteration) {
|
||||
|
||||
if (!PI.runBeforePass<LazyCallGraph::SCC>(Pass, *C))
|
||||
continue;
|
||||
|
||||
@@ -669,22 +659,33 @@ public:
|
||||
assert(C->begin() != C->end() && "Cannot have an empty SCC!");
|
||||
|
||||
// Check whether any of the handles were devirtualized.
|
||||
bool Devirt = llvm::any_of(UR.IndirectVHs, [](auto &P) -> bool {
|
||||
if (P.second) {
|
||||
CallBase *CB = cast<CallBase>(P.second);
|
||||
if (CB->getCalledFunction()) {
|
||||
LLVM_DEBUG(dbgs() << "Found devirtualized call: " << *CB << "\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
auto IsDevirtualizedHandle = [&](WeakTrackingVH &CallH) {
|
||||
if (!CallH)
|
||||
return false;
|
||||
auto *CB = dyn_cast<CallBase>(CallH);
|
||||
if (!CB)
|
||||
return false;
|
||||
|
||||
// If the call is still indirect, leave it alone.
|
||||
Function *F = CB->getCalledFunction();
|
||||
if (!F)
|
||||
return false;
|
||||
|
||||
LLVM_DEBUG(dbgs() << "Found devirtualized call from "
|
||||
<< CB->getParent()->getParent()->getName() << " to "
|
||||
<< F->getName() << "\n");
|
||||
|
||||
// We now have a direct call where previously we had an indirect call,
|
||||
// so iterate to process this devirtualization site.
|
||||
return true;
|
||||
};
|
||||
bool Devirt = llvm::any_of(CallHandles, IsDevirtualizedHandle);
|
||||
|
||||
// Rescan to build up a new set of handles and count how many direct
|
||||
// calls remain. If we decide to iterate, this also sets up the input to
|
||||
// the next iteration.
|
||||
UR.IndirectVHs.clear();
|
||||
auto NewCallCounts = ScanSCC(*C, UR.IndirectVHs);
|
||||
CallHandles.clear();
|
||||
auto NewCallCounts = ScanSCC(*C, CallHandles);
|
||||
|
||||
// If we haven't found an explicit devirtualization already see if we
|
||||
// have decreased the number of indirect calls and increased the number
|
||||
@@ -789,8 +790,7 @@ ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>::run(Module &M,
|
||||
|
||||
CGSCCUpdateResult UR = {
|
||||
RCWorklist, CWorklist, InvalidRefSCCSet, InvalidSCCSet,
|
||||
nullptr, nullptr, PreservedAnalyses::all(), InlinedInternalEdges,
|
||||
{}};
|
||||
nullptr, nullptr, PreservedAnalyses::all(), InlinedInternalEdges};
|
||||
|
||||
// Request PassInstrumentation from analysis manager, will use it to run
|
||||
// instrumenting callbacks for the passes later.
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/IR/PassManagerImpl.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
@@ -477,9 +476,9 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
|
||||
// First walk the function and handle all called functions. We do this first
|
||||
// because if there is a single call edge, whether there are ref edges is
|
||||
// irrelevant.
|
||||
for (Instruction &I : instructions(F)) {
|
||||
if (auto *CB = dyn_cast<CallBase>(&I)) {
|
||||
if (Function *Callee = CB->getCalledFunction()) {
|
||||
for (Instruction &I : instructions(F))
|
||||
if (auto *CB = dyn_cast<CallBase>(&I))
|
||||
if (Function *Callee = CB->getCalledFunction())
|
||||
if (Visited.insert(Callee).second && !Callee->isDeclaration()) {
|
||||
Node *CalleeN = G.lookup(*Callee);
|
||||
if (!CalleeN) {
|
||||
@@ -499,17 +498,6 @@ static LazyCallGraph::SCC &updateCGAndAnalysisManagerForPass(
|
||||
else if (!E->isCall())
|
||||
PromotedRefTargets.insert(CalleeN);
|
||||
}
|
||||
} else {
|
||||
// We can miss devirtualization if an indirect call is created then
|
||||
// promoted before updateCGAndAnalysisManagerForPass runs.
|
||||
auto *Entry = UR.IndirectVHs.find(CB);
|
||||
if (Entry == UR.IndirectVHs.end())
|
||||
UR.IndirectVHs.insert({CB, WeakTrackingVH(CB)});
|
||||
else if (!Entry->second)
|
||||
Entry->second = WeakTrackingVH(CB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now walk all references.
|
||||
for (Instruction &I : instructions(F))
|
||||
|
||||
@@ -1815,7 +1815,7 @@ static Optional<int> parseDevirtPassName(StringRef Name) {
|
||||
if (!Name.consume_front("devirt<") || !Name.consume_back(">"))
|
||||
return None;
|
||||
int Count;
|
||||
if (Name.getAsInteger(0, Count) || Count < 0)
|
||||
if (Name.getAsInteger(0, Count) || Count <= 0)
|
||||
return None;
|
||||
return Count;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
; RUN: opt -basic-aa -S -O2 < %s | FileCheck %s
|
||||
; RUN: opt -aa-pipeline=basic-aa -S -passes='default<O2>' < %s | FileCheck %s
|
||||
; PR5009
|
||||
|
||||
; CHECK: define i32 @main()
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
; RUN: opt -abort-on-max-devirt-iterations-reached -passes='cgscc(devirt<1>(inline,instcombine))' -S < %s | FileCheck %s
|
||||
; RUN: opt -abort-on-max-devirt-iterations-reached -passes='default<O2>' -S < %s | FileCheck %s
|
||||
|
||||
define i32 @i() alwaysinline {
|
||||
ret i32 45
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define i32 @main
|
||||
; CHECK-NEXT: ret i32 45
|
||||
|
||||
define i32 @main() {
|
||||
%a = alloca i32 ()*
|
||||
store i32 ()* @i, i32 ()** %a
|
||||
%r = call i32 @call(i32 ()** %a)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define i32 @call(i32 ()** %a) alwaysinline {
|
||||
%c = load i32 ()*, i32 ()** %a
|
||||
%r = call i32 %c()
|
||||
ret i32 %r
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
; Make sure we don't detect devirtualization on inlining a function with a direct call
|
||||
; RUN: opt -abort-on-max-devirt-iterations-reached -passes='cgscc(devirt<0>(inline))' -S < %s | FileCheck %s
|
||||
|
||||
define i32 @i() noinline {
|
||||
ret i32 45
|
||||
}
|
||||
|
||||
; CHECK-NOT: call i32 @call()
|
||||
|
||||
define i32 @main() {
|
||||
%r = call i32 @call()
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define i32 @call() alwaysinline {
|
||||
%r = call i32 @i()
|
||||
ret i32 %r
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
; RUN: opt -S -Os < %s | FileCheck %s
|
||||
; RUN: opt -S -aa-pipeline=basic-aa -passes='default<Os>' < %s | FileCheck %s
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
target triple = "x86_64-apple-darwin10.0.0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user