summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Transforms/IPO/Attributor.h6
-rw-r--r--llvm/lib/Transforms/IPO/Attributor.cpp157
-rw-r--r--llvm/test/Transforms/FunctionAttrs/align.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/arg_returned.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/dereferenceable.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/internal-noalias.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/liveness.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/noalias_returned.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/noreturn_async.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/nosync.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/nounwind.ll2
-rw-r--r--llvm/test/Transforms/FunctionAttrs/willreturn.ll2
15 files changed, 117 insertions, 72 deletions
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 95cc07d31b3..3be021bc336 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -733,6 +733,12 @@ struct Attributor {
/// various places.
void identifyDefaultAbstractAttributes(Function &F);
+ /// Initialize the information cache for queries regarding function \p F.
+ ///
+ /// This method needs to be called for all function that might be looked at
+ /// through the information cache interface *prior* to looking at them.
+ void initializeInformationCache(Function &F);
+
/// Mark the internal function \p F as live.
///
/// This will trigger the identification and initialization of attributes for
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index a6f8472e85d..654f2084be4 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -1863,12 +1863,14 @@ struct AAIsDeadImpl : public AAIsDead {
void exploreFromEntry(Attributor &A, const Function *F) {
ToBeExploredPaths.insert(&(F->getEntryBlock().front()));
- assumeLive(A, F->getEntryBlock());
for (size_t i = 0; i < ToBeExploredPaths.size(); ++i)
if (const Instruction *NextNoReturnI =
findNextNoReturn(A, ToBeExploredPaths[i]))
NoReturnCalls.insert(NextNoReturnI);
+
+ // Mark the block live after we looked for no-return instructions.
+ assumeLive(A, F->getEntryBlock());
}
/// Find the next assumed noreturn instruction in the block of \p I starting
@@ -3537,6 +3539,26 @@ bool Attributor::checkForAllReturnedValues(
});
}
+static bool
+checkForAllInstructionsImpl(InformationCache::OpcodeInstMapTy &OpcodeInstMap,
+ const function_ref<bool(Instruction &)> &Pred,
+ const AAIsDead *LivenessAA, bool &AnyDead,
+ const ArrayRef<unsigned> &Opcodes) {
+ for (unsigned Opcode : Opcodes) {
+ for (Instruction *I : OpcodeInstMap[Opcode]) {
+ // Skip dead instructions.
+ if (LivenessAA && LivenessAA->isAssumedDead(I)) {
+ AnyDead = true;
+ continue;
+ }
+
+ if (!Pred(*I))
+ return false;
+ }
+ }
+ return true;
+}
+
bool Attributor::checkForAllInstructions(
const llvm::function_ref<bool(Instruction &)> &Pred,
const AbstractAttribute &QueryingAA, const ArrayRef<unsigned> &Opcodes) {
@@ -3555,18 +3577,8 @@ bool Attributor::checkForAllInstructions(
auto &OpcodeInstMap =
InfoCache.getOpcodeInstMapForFunction(*AssociatedFunction);
- for (unsigned Opcode : Opcodes) {
- for (Instruction *I : OpcodeInstMap[Opcode]) {
- // Skip dead instructions.
- if (LivenessAA.isAssumedDead(I)) {
- AnyDead = true;
- continue;
- }
-
- if (!Pred(*I))
- return false;
- }
- }
+ if (!checkForAllInstructionsImpl(OpcodeInstMap, Pred, &LivenessAA, AnyDead, Opcodes))
+ return false;
// If we actually used liveness information so we have to record a dependence.
if (AnyDead)
@@ -3852,6 +3864,48 @@ ChangeStatus Attributor::run(Module &M) {
return ManifestChange;
}
+void Attributor::initializeInformationCache(Function &F) {
+
+ // Walk all instructions to find interesting instructions that might be
+ // queried by abstract attributes during their initialization or update.
+ // This has to happen before we create attributes.
+ auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
+ auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
+
+ for (Instruction &I : instructions(&F)) {
+ bool IsInterestingOpcode = false;
+
+ // To allow easy access to all instructions in a function with a given
+ // opcode we store them in the InfoCache. As not all opcodes are interesting
+ // to concrete attributes we only cache the ones that are as identified in
+ // the following switch.
+ // Note: There are no concrete attributes now so this is initially empty.
+ switch (I.getOpcode()) {
+ default:
+ assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
+ "New call site/base instruction type needs to be known int the "
+ "Attributor.");
+ break;
+ case Instruction::Load:
+ // The alignment of a pointer is interesting for loads.
+ case Instruction::Store:
+ // The alignment of a pointer is interesting for stores.
+ case Instruction::Call:
+ case Instruction::CallBr:
+ case Instruction::Invoke:
+ case Instruction::CleanupRet:
+ case Instruction::CatchSwitch:
+ case Instruction::Resume:
+ case Instruction::Ret:
+ IsInterestingOpcode = true;
+ }
+ if (IsInterestingOpcode)
+ InstOpcodeMap[I.getOpcode()].push_back(&I);
+ if (I.mayReadOrWriteMemory())
+ ReadOrWriteInsts.push_back(&I);
+ }
+}
+
void Attributor::identifyDefaultAbstractAttributes(Function &F) {
if (!VisitedFunctions.insert(&F).second)
return;
@@ -3935,52 +3989,9 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
}
}
- // Walk all instructions to find more attribute opportunities and also
- // interesting instructions that might be queried by abstract attributes
- // during their initialization or update.
- auto &ReadOrWriteInsts = InfoCache.FuncRWInstsMap[&F];
- auto &InstOpcodeMap = InfoCache.FuncInstOpcodeMap[&F];
-
- for (Instruction &I : instructions(&F)) {
- bool IsInterestingOpcode = false;
-
- // To allow easy access to all instructions in a function with a given
- // opcode we store them in the InfoCache. As not all opcodes are interesting
- // to concrete attributes we only cache the ones that are as identified in
- // the following switch.
- // Note: There are no concrete attributes now so this is initially empty.
- switch (I.getOpcode()) {
- default:
- assert((!ImmutableCallSite(&I)) && (!isa<CallBase>(&I)) &&
- "New call site/base instruction type needs to be known int the "
- "attributor.");
- break;
- case Instruction::Load:
- // The alignment of a pointer is interesting for loads.
- getOrCreateAAFor<AAAlign>(
- IRPosition::value(*cast<LoadInst>(I).getPointerOperand()));
- break;
- case Instruction::Store:
- // The alignment of a pointer is interesting for stores.
- getOrCreateAAFor<AAAlign>(
- IRPosition::value(*cast<StoreInst>(I).getPointerOperand()));
- break;
- case Instruction::Call:
- case Instruction::CallBr:
- case Instruction::Invoke:
- case Instruction::CleanupRet:
- case Instruction::CatchSwitch:
- case Instruction::Resume:
- case Instruction::Ret:
- IsInterestingOpcode = true;
- }
- if (IsInterestingOpcode)
- InstOpcodeMap[I.getOpcode()].push_back(&I);
- if (I.mayReadOrWriteMemory())
- ReadOrWriteInsts.push_back(&I);
-
+ auto CallSitePred = [&](Instruction &I) -> bool {
CallSite CS(&I);
- if (CS && CS.getCalledFunction()) {
+ if (CS.getCalledFunction()) {
for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) {
IRPosition CSArgPos = IRPosition::callsite_argument(CS, i);
@@ -4004,7 +4015,32 @@ void Attributor::identifyDefaultAbstractAttributes(Function &F) {
getOrCreateAAFor<AAAlign>(CSArgPos);
}
}
- }
+ return true;
+ };
+
+ auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
+ bool Success, AnyDead = false;
+ Success = checkForAllInstructionsImpl(
+ OpcodeInstMap, CallSitePred, nullptr, AnyDead,
+ {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
+ (unsigned)Instruction::Call});
+ (void)Success;
+ assert(Success && !AnyDead && "Expected the check call to be successful!");
+
+ auto LoadStorePred = [&](Instruction &I) -> bool {
+ if (isa<LoadInst>(I))
+ getOrCreateAAFor<AAAlign>(
+ IRPosition::value(*cast<LoadInst>(I).getPointerOperand()));
+ else
+ getOrCreateAAFor<AAAlign>(
+ IRPosition::value(*cast<StoreInst>(I).getPointerOperand()));
+ return true;
+ };
+ Success = checkForAllInstructionsImpl(
+ OpcodeInstMap, LoadStorePred, nullptr, AnyDead,
+ {(unsigned)Instruction::Load, (unsigned)Instruction::Store});
+ (void)Success;
+ assert(Success && !AnyDead && "Expected the check call to be successful!");
}
/// Helpers to ease debugging through output streams and print calls.
@@ -4078,6 +4114,9 @@ static bool runAttributorOnModule(Module &M, AnalysisGetter &AG) {
InformationCache InfoCache(M.getDataLayout(), AG);
Attributor A(InfoCache, DepRecInterval);
+ for (Function &F : M)
+ A.initializeInformationCache(F);
+
for (Function &F : M) {
if (F.hasExactDefinition())
NumFnWithExactDefinition++;
diff --git a/llvm/test/Transforms/FunctionAttrs/align.ll b/llvm/test/Transforms/FunctionAttrs/align.ll
index 5e8671b64a2..fc5ffc61e8e 100644
--- a/llvm/test/Transforms/FunctionAttrs/align.ll
+++ b/llvm/test/Transforms/FunctionAttrs/align.ll
@@ -1,4 +1,4 @@
-; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
index 95871ff7d34..57d2713d278 100644
--- a/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
+++ b/llvm/test/Transforms/FunctionAttrs/arg_returned.ll
@@ -1,5 +1,5 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -functionattrs -S < %s | FileCheck %s --check-prefix=BOTH
;
; Test cases specifically designed for the "returned" argument attribute.
diff --git a/llvm/test/Transforms/FunctionAttrs/dereferenceable.ll b/llvm/test/Transforms/FunctionAttrs/dereferenceable.ll
index 852b2a28351..d7b576f506a 100644
--- a/llvm/test/Transforms/FunctionAttrs/dereferenceable.ll
+++ b/llvm/test/Transforms/FunctionAttrs/dereferenceable.ll
@@ -1,4 +1,4 @@
-; RUN: opt -attributor -attributor-manifest-internal --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR
declare void @deref_phi_user(i32* %a);
diff --git a/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll b/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
index d8258be7d2c..e3a0f0b2504 100644
--- a/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
+++ b/llvm/test/Transforms/FunctionAttrs/fn_noreturn.ll
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S < %s | FileCheck %s
+; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s
;
; Test cases specifically designed for the "no-return" function attribute.
; We use FIXME's to indicate problems and missing attributes.
diff --git a/llvm/test/Transforms/FunctionAttrs/internal-noalias.ll b/llvm/test/Transforms/FunctionAttrs/internal-noalias.ll
index edc3fe07dae..1118fa194f3 100644
--- a/llvm/test/Transforms/FunctionAttrs/internal-noalias.ll
+++ b/llvm/test/Transforms/FunctionAttrs/internal-noalias.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 < %s | FileCheck %s
+; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=5 < %s | FileCheck %s
define dso_local i32 @visible(i32* noalias %A, i32* noalias %B) #0 {
entry:
diff --git a/llvm/test/Transforms/FunctionAttrs/liveness.ll b/llvm/test/Transforms/FunctionAttrs/liveness.ll
index 93aac999950..771c99309bb 100644
--- a/llvm/test/Transforms/FunctionAttrs/liveness.ll
+++ b/llvm/test/Transforms/FunctionAttrs/liveness.ll
@@ -1,4 +1,4 @@
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=11 -S < %s | FileCheck %s
+; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s
declare void @no_return_call() nofree noreturn nounwind readnone
diff --git a/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll b/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll
index 410d1d6cbc3..7174c3dc97c 100644
--- a/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll
+++ b/llvm/test/Transforms/FunctionAttrs/noalias_returned.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=5 < %s | FileCheck %s
+; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s
; TEST 1 - negative.
diff --git a/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll b/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
index bfaa98eccf7..f76b429aa4b 100644
--- a/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nofree-attributor.ll
@@ -1,5 +1,5 @@
; RUN: opt -functionattrs --disable-nofree-inference=false -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/Transforms/FunctionAttrs/noreturn_async.ll b/llvm/test/Transforms/FunctionAttrs/noreturn_async.ll
index 1e34ca4f948..e9e423688df 100644
--- a/llvm/test/Transforms/FunctionAttrs/noreturn_async.ll
+++ b/llvm/test/Transforms/FunctionAttrs/noreturn_async.ll
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S < %s | FileCheck %s
+; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s
;
; This file is the same as noreturn_sync.ll but with a personality which
; indicates that the exception handler *can* catch asynchronous exceptions. As
diff --git a/llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll b/llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll
index 4c62ea57f50..5d644965fb2 100644
--- a/llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll
+++ b/llvm/test/Transforms/FunctionAttrs/noreturn_sync.ll
@@ -1,4 +1,4 @@
-; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=5 -S < %s | FileCheck %s
+; RUN: opt -functionattrs -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s
;
; This file is the same as noreturn_async.ll but with a personality which
; indicates that the exception handler *cannot* catch asynchronous exceptions.
diff --git a/llvm/test/Transforms/FunctionAttrs/nosync.ll b/llvm/test/Transforms/FunctionAttrs/nosync.ll
index 2807e89e986..d948048db12 100644
--- a/llvm/test/Transforms/FunctionAttrs/nosync.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nosync.ll
@@ -1,5 +1,5 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; Test cases designed for the nosync function attribute.
diff --git a/llvm/test/Transforms/FunctionAttrs/nounwind.ll b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
index 0e6b607d546..85878058922 100644
--- a/llvm/test/Transforms/FunctionAttrs/nounwind.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nounwind.ll
@@ -1,5 +1,5 @@
; RUN: opt < %s -functionattrs -S | FileCheck %s
-; RUN: opt < %s -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=5 -S | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt < %s -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S | FileCheck %s --check-prefix=ATTRIBUTOR
; TEST 1
; CHECK: Function Attrs: norecurse nounwind readnone
diff --git a/llvm/test/Transforms/FunctionAttrs/willreturn.ll b/llvm/test/Transforms/FunctionAttrs/willreturn.ll
index 1b9b3c91b31..7821658c952 100644
--- a/llvm/test/Transforms/FunctionAttrs/willreturn.ll
+++ b/llvm/test/Transforms/FunctionAttrs/willreturn.ll
@@ -1,5 +1,5 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
-; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
OpenPOWER on IntegriCloud