forked from OSchip/llvm-project
[Attributor] Regularly clear dependences to remove spurious ones
As dependences between abstract attributes can become stale, e.g., if one was sufficient to imply another one at some point but it has since been wakened to the point it is not usable for the formerly implied one. To weed out spurious dependences, and thereby eliminate unneeded updates, we introduce an option to determine how often the dependence cache is cleared and recomputed during the fixpoint iteration. Note that the initial value was determined such that we see a positive result on our tests. Differential Revision: https://reviews.llvm.org/D63315 llvm-svn: 370230
This commit is contained in:
parent
8f85685b5c
commit
f7ca0fe1c8
|
@ -568,7 +568,15 @@ private:
|
||||||
/// NOTE: The mechanics of adding a new "concrete" abstract attribute are
|
/// NOTE: The mechanics of adding a new "concrete" abstract attribute are
|
||||||
/// described in the file comment.
|
/// described in the file comment.
|
||||||
struct Attributor {
|
struct Attributor {
|
||||||
Attributor(InformationCache &InfoCache) : InfoCache(InfoCache) {}
|
/// Constructor
|
||||||
|
///
|
||||||
|
/// \param InformationCache Cache to hold various information accessible for
|
||||||
|
/// the abstract attributes.
|
||||||
|
/// \param DepRecomputeInterval Number of iterations until the dependences
|
||||||
|
/// between abstract attributes are recomputed.
|
||||||
|
Attributor(InformationCache &InfoCache, unsigned DepRecomputeInterval)
|
||||||
|
: InfoCache(InfoCache), DepRecomputeInterval(DepRecomputeInterval) {}
|
||||||
|
|
||||||
~Attributor() { DeleteContainerPointers(AllAbstractAttributes); }
|
~Attributor() { DeleteContainerPointers(AllAbstractAttributes); }
|
||||||
|
|
||||||
/// Run the analyses until a fixpoint is reached or enforced (timeout).
|
/// Run the analyses until a fixpoint is reached or enforced (timeout).
|
||||||
|
@ -775,6 +783,10 @@ private:
|
||||||
/// The information cache that holds pre-processed (LLVM-IR) information.
|
/// The information cache that holds pre-processed (LLVM-IR) information.
|
||||||
InformationCache &InfoCache;
|
InformationCache &InfoCache;
|
||||||
|
|
||||||
|
/// Number of iterations until the dependences between abstract attributes are
|
||||||
|
/// recomputed.
|
||||||
|
const unsigned DepRecomputeInterval;
|
||||||
|
|
||||||
/// Functions, blocks, and instructions we delete after manifest is done.
|
/// Functions, blocks, and instructions we delete after manifest is done.
|
||||||
///
|
///
|
||||||
///{
|
///{
|
||||||
|
|
|
@ -123,6 +123,11 @@ static cl::opt<bool> VerifyAttributor(
|
||||||
"manifestation of attributes -- may issue false-positive errors"),
|
"manifestation of attributes -- may issue false-positive errors"),
|
||||||
cl::init(false));
|
cl::init(false));
|
||||||
|
|
||||||
|
static cl::opt<unsigned> DepRecInterval(
|
||||||
|
"attributor-dependence-recompute-interval", cl::Hidden,
|
||||||
|
cl::desc("Number of iterations until dependences are recomputed."),
|
||||||
|
cl::init(4));
|
||||||
|
|
||||||
/// Logic operators for the change status enum class.
|
/// Logic operators for the change status enum class.
|
||||||
///
|
///
|
||||||
///{
|
///{
|
||||||
|
@ -2548,12 +2553,25 @@ ChangeStatus Attributor::run() {
|
||||||
SetVector<AbstractAttribute *> Worklist;
|
SetVector<AbstractAttribute *> Worklist;
|
||||||
Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
|
Worklist.insert(AllAbstractAttributes.begin(), AllAbstractAttributes.end());
|
||||||
|
|
||||||
|
bool RecomputeDependences = false;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Remember the size to determine new attributes.
|
// Remember the size to determine new attributes.
|
||||||
size_t NumAAs = AllAbstractAttributes.size();
|
size_t NumAAs = AllAbstractAttributes.size();
|
||||||
LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
|
LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
|
||||||
<< ", Worklist size: " << Worklist.size() << "\n");
|
<< ", Worklist size: " << Worklist.size() << "\n");
|
||||||
|
|
||||||
|
// If dependences (=QueryMap) are recomputed we have to look at all abstract
|
||||||
|
// attributes again, regardless of what changed in the last iteration.
|
||||||
|
if (RecomputeDependences) {
|
||||||
|
LLVM_DEBUG(
|
||||||
|
dbgs() << "[Attributor] Run all AAs to recompute dependences\n");
|
||||||
|
QueryMap.clear();
|
||||||
|
ChangedAAs.clear();
|
||||||
|
Worklist.insert(AllAbstractAttributes.begin(),
|
||||||
|
AllAbstractAttributes.end());
|
||||||
|
}
|
||||||
|
|
||||||
// Add all abstract attributes that are potentially dependent on one that
|
// Add all abstract attributes that are potentially dependent on one that
|
||||||
// changed to the work list.
|
// changed to the work list.
|
||||||
for (AbstractAttribute *ChangedAA : ChangedAAs) {
|
for (AbstractAttribute *ChangedAA : ChangedAAs) {
|
||||||
|
@ -2575,6 +2593,10 @@ ChangeStatus Attributor::run() {
|
||||||
if (AA->update(*this) == ChangeStatus::CHANGED)
|
if (AA->update(*this) == ChangeStatus::CHANGED)
|
||||||
ChangedAAs.push_back(AA);
|
ChangedAAs.push_back(AA);
|
||||||
|
|
||||||
|
// Check if we recompute the dependences in the next iteration.
|
||||||
|
RecomputeDependences = (DepRecomputeInterval > 0 &&
|
||||||
|
IterationCounter % DepRecomputeInterval == 0);
|
||||||
|
|
||||||
// Add attributes to the changed set if they have been created in the last
|
// Add attributes to the changed set if they have been created in the last
|
||||||
// iteration.
|
// iteration.
|
||||||
ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs,
|
ChangedAAs.append(AllAbstractAttributes.begin() + NumAAs,
|
||||||
|
@ -2589,13 +2611,18 @@ ChangeStatus Attributor::run() {
|
||||||
|
|
||||||
size_t NumFinalAAs = AllAbstractAttributes.size();
|
size_t NumFinalAAs = AllAbstractAttributes.size();
|
||||||
|
|
||||||
|
if (VerifyMaxFixpointIterations && IterationCounter != MaxFixpointIterations) {
|
||||||
|
errs() << "\n[Attributor] Fixpoint iteration done after: "
|
||||||
|
<< IterationCounter << "/" << MaxFixpointIterations
|
||||||
|
<< " iterations\n";
|
||||||
|
llvm_unreachable("The fixpoint was not reached with exactly the number of "
|
||||||
|
"specified iterations!");
|
||||||
|
}
|
||||||
|
|
||||||
LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
|
LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
|
||||||
<< IterationCounter << "/" << MaxFixpointIterations
|
<< IterationCounter << "/" << MaxFixpointIterations
|
||||||
<< " iterations\n");
|
<< " iterations\n");
|
||||||
|
|
||||||
if (VerifyMaxFixpointIterations && IterationCounter != MaxFixpointIterations)
|
|
||||||
llvm_unreachable("The fixpoint was not reached with exactly the number of "
|
|
||||||
"specified iterations!");
|
|
||||||
|
|
||||||
bool FinishedAtFixpoint = Worklist.empty();
|
bool FinishedAtFixpoint = Worklist.empty();
|
||||||
|
|
||||||
|
@ -2930,7 +2957,7 @@ static bool runAttributorOnModule(Module &M) {
|
||||||
// Create an Attributor and initially empty information cache that is filled
|
// Create an Attributor and initially empty information cache that is filled
|
||||||
// while we identify default attribute opportunities.
|
// while we identify default attribute opportunities.
|
||||||
InformationCache InfoCache(M.getDataLayout());
|
InformationCache InfoCache(M.getDataLayout());
|
||||||
Attributor A(InfoCache);
|
Attributor A(InfoCache, DepRecInterval);
|
||||||
|
|
||||||
for (Function &F : M) {
|
for (Function &F : M) {
|
||||||
// TODO: Not all attributes require an exact definition. Find a way to
|
// TODO: Not all attributes require an exact definition. Find a way to
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
|
; RUN: opt -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
|
||||||
|
|
||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR
|
; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR
|
||||||
; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR
|
; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=BOTH,FNATTR
|
||||||
; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=BOTH,ATTRIBUTOR
|
; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=10 -S < %s | FileCheck %s --check-prefixes=BOTH,ATTRIBUTOR
|
||||||
|
|
||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s
|
; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s
|
||||||
;
|
;
|
||||||
; This file is the same as noreturn_async.ll but with a personality which
|
; This file is the same as noreturn_async.ll but with a personality which
|
||||||
; indicates that the exception handler *cannot* catch asynchronous exceptions.
|
; indicates that the exception handler *cannot* catch asynchronous exceptions.
|
||||||
|
|
Loading…
Reference in New Issue