[Attributor] Remember only necessary dependences

Before we eagerly put dependences into the QueryMap as soon as we
encountered them (via `Attributor::getAAFor<>` or
`Attributor::recordDependence`). Now we will wait to see if the
dependence is useful, that is if the target is not already in a fixpoint
state at the end of the update. If so, there is no need to record the
dependence at all.

Due to the abstraction via `Attributor::updateAA` we will now also treat
the very first update (during attribute creation) as we do subsequent
updates.

Finally this resolves the problematic usage of QueriedNonFixAA.

---

Single run of the Attributor module and then CGSCC pass (oldPM)
for SPASS/clause.c (~10k LLVM-IR loc):

Before:
```
calls to allocation functions: 554675 (389245/s)
temporary memory allocations: 101574 (71280/s)
peak heap memory consumption: 28.46MB
peak RSS (including heaptrack overhead): 116.26MB
total memory leaked: 269.10KB
```

After:
```
calls to allocation functions: 512465 (345559/s)
temporary memory allocations: 98832 (66643/s)
peak heap memory consumption: 22.54MB
peak RSS (including heaptrack overhead): 106.58MB
total memory leaked: 269.10KB
```

Difference:
```
calls to allocation functions: -42210 (-727758/s)
temporary memory allocations: -2742 (-47275/s)
peak heap memory consumption: -5.92MB
peak RSS (including heaptrack overhead): 0B
total memory leaked: 0B
```
This commit is contained in:
Johannes Doerfert 2020-04-30 12:12:22 -05:00
parent 231026a508
commit 95e0d28b71
12 changed files with 273 additions and 162 deletions

View File

@ -1195,6 +1195,14 @@ struct Attributor {
BumpPtrAllocator &Allocator;
private:
/// Run `::update` on \p AA and track the dependences queried while doing so.
/// Also adjust the state if we know further updates are not necessary.
ChangeStatus updateAA(AbstractAttribute &AA);
/// Remember the dependences on the top of the dependence stack such that they
/// may trigger further updates. (\see DependenceStack)
void rememberDependences();
/// Check \p Pred on all call sites of \p Fn.
///
/// This method will evaluate \p Pred on call sites and return
@ -1248,7 +1256,7 @@ private:
return AA;
}
AA.update(*this);
updateAA(AA);
if (TrackDependence && AA.getState().isValidState())
recordDependence(AA, const_cast<AbstractAttribute &>(*QueryingAA),
@ -1345,8 +1353,23 @@ private:
/// impact the call graph.
SmallPtrSet<Function *, 8> CGModifiedFunctions;
/// Set if the attribute currently updated did query a non-fix attribute.
bool QueriedNonFixAA;
/// Information about a dependence. If FromAA is changed ToAA needs to be
/// updated as well.
struct DepInfo {
const AbstractAttribute *FromAA;
const AbstractAttribute *ToAA;
DepClassTy DepClass;
};
/// The dependence stack is used to track dependences during an
/// `AbstractAttribute::update` call. As `AbstractAttribute::update` can be
/// recursive we might have multiple vectors of dependences in here. The stack
/// size, should be adjusted according to the expected recursion depth and the
/// inner dependence vector size to the expected number of dependences per
/// abstract attribute. Since the inner vectors are actually allocated on the
/// stack we can be generous with their size.
using DependenceVector = SmallVector<DepInfo, 8>;
SmallVector<DependenceVector *, 16> DependenceStack;
/// If not null, a set limiting the attribute opportunities.
const DenseSet<const char *> *Whitelist;

View File

@ -976,21 +976,19 @@ ChangeStatus Attributor::run() {
// Update all abstract attribute in the work list and record the ones that
// changed.
for (AbstractAttribute *AA : Worklist)
if (!AA->getState().isAtFixpoint() &&
for (AbstractAttribute *AA : Worklist) {
const auto &AAState = AA->getState();
if (!AAState.isAtFixpoint() &&
!isAssumedDead(*AA, nullptr, /* CheckBBLivenessOnly */ true)) {
QueriedNonFixAA = false;
if (AA->update(*this) == ChangeStatus::CHANGED) {
if (updateAA(*AA) == ChangeStatus::CHANGED) {
ChangedAAs.push_back(AA);
if (!AA->getState().isValidState())
InvalidAAs.insert(AA);
} else if (!QueriedNonFixAA) {
// If the attribute did not query any non-fix information, the state
// will not change and we can indicate that right away.
AA->getState().indicateOptimisticFixpoint();
}
}
// Use the InvalidAAs vector to propagate invalid states fast transitively
// without requiring updates.
if (!AAState.isValidState())
InvalidAAs.insert(AA);
}
// Add attributes to the changed set if they have been created in the last
// iteration.
@ -1271,6 +1269,31 @@ ChangeStatus Attributor::run() {
return ManifestChange;
}
ChangeStatus Attributor::updateAA(AbstractAttribute &AA) {
// Use a new dependence vector for this update.
DependenceVector DV;
DependenceStack.push_back(&DV);
auto &AAState = AA.getState();
ChangeStatus CS = AA.update(*this);
if (DV.empty()) {
// If the attribute did not query any non-fix information, the state
// will not change and we can indicate that right away.
AAState.indicateOptimisticFixpoint();
}
if (!AAState.isAtFixpoint())
rememberDependences();
// Verify the stack was used properly, that is we pop the dependence vector we
// put there earlier.
DependenceVector *PoppedDV = DependenceStack.pop_back_val();
(void)PoppedDV;
assert(PoppedDV == &DV && "Inconsistent usage of the dependence stack!");
return CS;
}
/// Create a shallow wrapper for \p F such that \p F has internal linkage
/// afterwards. It also sets the original \p F 's name to anonymous
///
@ -1686,18 +1709,29 @@ InformationCache::FunctionInfo::~FunctionInfo() {
void Attributor::recordDependence(const AbstractAttribute &FromAA,
const AbstractAttribute &ToAA,
DepClassTy DepClass) {
// If we are outside of an update, thus before the actual fixpoint iteration
// started (= when we create AAs), we do not track dependences because we will
// put all AAs into the initial worklist anyway.
if (DependenceStack.empty())
return;
if (FromAA.getState().isAtFixpoint())
return;
DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
}
QueryMapValueTy *&DepAAs = QueryMap[&FromAA];
if (!DepAAs)
DepAAs = new (Allocator) QueryMapValueTy();
void Attributor::rememberDependences() {
assert(!DependenceStack.empty() && "No dependences to remember!");
if (DepClass == DepClassTy::REQUIRED)
DepAAs->RequiredAAs.insert(const_cast<AbstractAttribute *>(&ToAA));
else
DepAAs->OptionalAAs.insert(const_cast<AbstractAttribute *>(&ToAA));
QueriedNonFixAA = true;
for (DepInfo &DI : *DependenceStack.back()) {
QueryMapValueTy *&DepAAs = QueryMap[DI.FromAA];
if (!DepAAs)
DepAAs = new (Allocator) QueryMapValueTy();
if (DI.DepClass == DepClassTy::REQUIRED)
DepAAs->RequiredAAs.insert(const_cast<AbstractAttribute *>(DI.ToAA));
else
DepAAs->OptionalAAs.insert(const_cast<AbstractAttribute *>(DI.ToAA));
}
}
void Attributor::identifyDefaultAbstractAttributes(Function &F) {

View File

@ -115,6 +115,7 @@ PIPE_OPERATOR(AAMemoryBehavior)
PIPE_OPERATOR(AAMemoryLocation)
PIPE_OPERATOR(AAValueConstantRange)
PIPE_OPERATOR(AAPrivatizablePtr)
PIPE_OPERATOR(AAUndefinedBehavior)
#undef PIPE_OPERATOR
} // namespace llvm

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
; PR2498

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM

View File

@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
@ -8,15 +8,15 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i64 @fn2() {
; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@fn2()
; NOT_TUNIT_NPM-NEXT: entry:
; NOT_TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef)
; NOT_TUNIT_NPM-NEXT: ret i64 [[CALL2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2()
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #0, !range !0
; IS__TUNIT____-NEXT: ret i64 [[CALL2]]
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2()
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #1, !range !0
; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]]
; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2()
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef)
; IS__CGSCC____-NEXT: ret i64 [[CALL2]]
;
entry:
%conv = sext i32 undef to i64
@ -26,21 +26,21 @@ entry:
}
define i64 @fn2b(i32 %arg) {
; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@fn2b
; NOT_TUNIT_NPM-SAME: (i32 [[ARG:%.*]])
; NOT_TUNIT_NPM-NEXT: entry:
; NOT_TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64
; NOT_TUNIT_NPM-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]]
; NOT_TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]])
; NOT_TUNIT_NPM-NEXT: ret i64 [[CALL2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2b
; IS__TUNIT____-SAME: (i32 [[ARG:%.*]])
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64
; IS__TUNIT____-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]]
; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #0, !range !0
; IS__TUNIT____-NEXT: ret i64 [[CALL2]]
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2b
; IS__TUNIT_NPM-SAME: (i32 [[ARG:%.*]])
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64
; IS__TUNIT_NPM-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]]
; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #1, !range !0
; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]]
; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2b
; IS__CGSCC____-SAME: (i32 [[ARG:%.*]])
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64
; IS__CGSCC____-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]]
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]])
; IS__CGSCC____-NEXT: ret i64 [[CALL2]]
;
entry:
%conv = sext i32 %arg to i64
@ -50,15 +50,10 @@ entry:
}
define i64 @fn2c() {
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fn2c()
; IS__TUNIT_OPM-NEXT: entry:
; IS__TUNIT_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42)
; IS__TUNIT_OPM-NEXT: ret i64 [[CALL2]]
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2c()
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) #1, !range !0
; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2c()
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) #0, !range !0
; IS__TUNIT____-NEXT: ret i64 [[CALL2]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2c()
; IS__CGSCC____-NEXT: entry:

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
;

View File

@ -104,27 +104,16 @@ define i1 @c5(i32* %q, i32 %bitno) {
declare void @throw_if_bit_set(i8*, i8) readonly
define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 {
; IS__TUNIT____-LABEL: define {{[^@]+}}@c6
; IS__TUNIT____-SAME: (i8* readonly [[Q:%.*]], i8 [[BIT:%.*]]) #5 personality i32 (...)* @__gxx_personality_v0
; IS__TUNIT____-NEXT: invoke void @throw_if_bit_set(i8* readonly [[Q]], i8 [[BIT]])
; IS__TUNIT____-NEXT: to label [[RET0:%.*]] unwind label [[RET1:%.*]]
; IS__TUNIT____: ret0:
; IS__TUNIT____-NEXT: ret i1 false
; IS__TUNIT____: ret1:
; IS__TUNIT____-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 }
; IS__TUNIT____-NEXT: cleanup
; IS__TUNIT____-NEXT: ret i1 true
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@c6
; IS__CGSCC____-SAME: (i8* readonly [[Q:%.*]], i8 [[BIT:%.*]]) #4 personality i32 (...)* @__gxx_personality_v0
; IS__CGSCC____-NEXT: invoke void @throw_if_bit_set(i8* readonly [[Q]], i8 [[BIT]])
; IS__CGSCC____-NEXT: to label [[RET0:%.*]] unwind label [[RET1:%.*]]
; IS__CGSCC____: ret0:
; IS__CGSCC____-NEXT: ret i1 false
; IS__CGSCC____: ret1:
; IS__CGSCC____-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 }
; IS__CGSCC____-NEXT: cleanup
; IS__CGSCC____-NEXT: ret i1 true
; CHECK-LABEL: define {{[^@]+}}@c6
; CHECK-SAME: (i8* readonly [[Q:%.*]], i8 [[BIT:%.*]]) #4 personality i32 (...)* @__gxx_personality_v0
; CHECK-NEXT: invoke void @throw_if_bit_set(i8* readonly [[Q]], i8 [[BIT]])
; CHECK-NEXT: to label [[RET0:%.*]] unwind label [[RET1:%.*]]
; CHECK: ret0:
; CHECK-NEXT: ret i1 false
; CHECK: ret1:
; CHECK-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: cleanup
; CHECK-NEXT: ret i1 true
;
invoke void @throw_if_bit_set(i8* %q, i8 %bit)
to label %ret0 unwind label %ret1

View File

@ -38,7 +38,7 @@ define i8* @test2A(i1 %c, i8* %ret) {
; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #11 [ "nonnull"(i8* [[RET]]) ]
; NOT_CGSCC_OPM-NEXT: ret i8* [[RET]]
; NOT_CGSCC_OPM: B:
; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[RET]]) ]
; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #11 [ "nonnull"(i8* [[RET]]) ]
; NOT_CGSCC_OPM-NEXT: ret i8* [[RET]]
;
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test2A
@ -48,7 +48,7 @@ define i8* @test2A(i1 %c, i8* %ret) {
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #12 [ "nonnull"(i8* [[RET]]) ]
; IS__CGSCC_OPM-NEXT: ret i8* [[RET]]
; IS__CGSCC_OPM: B:
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[RET]]) ]
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #12 [ "nonnull"(i8* [[RET]]) ]
; IS__CGSCC_OPM-NEXT: ret i8* [[RET]]
;
br i1 %c, label %A, label %B
@ -69,7 +69,7 @@ define i8* @test2B(i1 %c, i8* %ret) {
; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #11 [ "dereferenceable"(i8* [[RET]], i32 4) ]
; NOT_CGSCC_OPM-NEXT: ret i8* [[RET]]
; NOT_CGSCC_OPM: B:
; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i8* [[RET]], i32 4) ]
; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #11 [ "dereferenceable"(i8* [[RET]], i32 4) ]
; NOT_CGSCC_OPM-NEXT: ret i8* [[RET]]
;
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test2B
@ -79,7 +79,7 @@ define i8* @test2B(i1 %c, i8* %ret) {
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #12 [ "dereferenceable"(i8* [[RET]], i32 4) ]
; IS__CGSCC_OPM-NEXT: ret i8* [[RET]]
; IS__CGSCC_OPM: B:
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i8* [[RET]], i32 4) ]
; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #12 [ "dereferenceable"(i8* [[RET]], i32 4) ]
; IS__CGSCC_OPM-NEXT: ret i8* [[RET]]
;
br i1 %c, label %A, label %B
@ -727,18 +727,31 @@ define i8 @parent7(i8* %a) {
declare i32 @esfp(...)
define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){
; CHECK-LABEL: define {{[^@]+}}@parent8
; CHECK-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #2 personality i8* bitcast (i32 (...)* @esfp to i8*)
; CHECK-NEXT: entry:
; CHECK-NEXT: invoke void @use2nonnull(i8* nonnull [[A]], i8* nonnull [[B]])
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
; CHECK: cont:
; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[B]], null
; CHECK-NEXT: ret i1 [[NULL_CHECK]]
; CHECK: exc:
; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT: filter [0 x i8*] zeroinitializer
; CHECK-NEXT: unreachable
; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@parent8
; NOT_CGSCC_OPM-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #4 personality i8* bitcast (i32 (...)* @esfp to i8*)
; NOT_CGSCC_OPM-NEXT: entry:
; NOT_CGSCC_OPM-NEXT: invoke void @use2nonnull(i8* nonnull [[A]], i8* nonnull [[B]])
; NOT_CGSCC_OPM-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
; NOT_CGSCC_OPM: cont:
; NOT_CGSCC_OPM-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[B]], null
; NOT_CGSCC_OPM-NEXT: ret i1 [[NULL_CHECK]]
; NOT_CGSCC_OPM: exc:
; NOT_CGSCC_OPM-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
; NOT_CGSCC_OPM-NEXT: filter [0 x i8*] zeroinitializer
; NOT_CGSCC_OPM-NEXT: unreachable
;
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@parent8
; IS__CGSCC_OPM-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #5 personality i8* bitcast (i32 (...)* @esfp to i8*)
; IS__CGSCC_OPM-NEXT: entry:
; IS__CGSCC_OPM-NEXT: invoke void @use2nonnull(i8* nonnull [[A]], i8* nonnull [[B]])
; IS__CGSCC_OPM-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]
; IS__CGSCC_OPM: cont:
; IS__CGSCC_OPM-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* [[B]], null
; IS__CGSCC_OPM-NEXT: ret i1 [[NULL_CHECK]]
; IS__CGSCC_OPM: exc:
; IS__CGSCC_OPM-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
; IS__CGSCC_OPM-NEXT: filter [0 x i8*] zeroinitializer
; IS__CGSCC_OPM-NEXT: unreachable
;
entry:

View File

@ -17,10 +17,15 @@ define i32 @test0(i32* %p) {
}
define i32 @test0-range-check(i32* %p) {
; IS__TUNIT____-LABEL: define {{[^@]+}}@test0-range-check
; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT____-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #4, !range !0
; IS__TUNIT____-NEXT: ret i32 [[A]]
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test0-range-check
; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT_OPM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #3, !range !0
; IS__TUNIT_OPM-NEXT: ret i32 [[A]]
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test0-range-check
; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT_NPM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #2, !range !0
; IS__TUNIT_NPM-NEXT: ret i32 [[A]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test0-range-check
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
@ -45,52 +50,99 @@ define void @use3(i1, i1, i1) {
; TEST0 icmp test
define void @test0-icmp-check(i32* %p){
; ret = [0, 10)
; IS__TUNIT____-LABEL: define {{[^@]+}}@test0-icmp-check
; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT____-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #4, !range !0
; IS__TUNIT____-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
; IS__TUNIT____-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
; IS__TUNIT____-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
; IS__TUNIT____-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
; IS__TUNIT____-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
; IS__TUNIT____-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
; IS__TUNIT____-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
; IS__TUNIT____-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
; IS__TUNIT____-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
; IS__TUNIT____-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
; IS__TUNIT____-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
; IS__TUNIT____-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
; IS__TUNIT____-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
; IS__TUNIT____-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
; IS__TUNIT____-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
; IS__TUNIT____-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
; IS__TUNIT____-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
; IS__TUNIT____-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
; IS__TUNIT____-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
; IS__TUNIT____-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
; IS__TUNIT____-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
; IS__TUNIT____-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
; IS__TUNIT____-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
; IS__TUNIT____-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
; IS__TUNIT____-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
; IS__TUNIT____-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
; IS__TUNIT____-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
; IS__TUNIT____-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
; IS__TUNIT____-NEXT: ret void
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test0-icmp-check
; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT_OPM-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #3, !range !0
; IS__TUNIT_OPM-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
; IS__TUNIT_OPM-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
; IS__TUNIT_OPM-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
; IS__TUNIT_OPM-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
; IS__TUNIT_OPM-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
; IS__TUNIT_OPM-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
; IS__TUNIT_OPM-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
; IS__TUNIT_OPM-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
; IS__TUNIT_OPM-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
; IS__TUNIT_OPM-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
; IS__TUNIT_OPM-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
; IS__TUNIT_OPM-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
; IS__TUNIT_OPM-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
; IS__TUNIT_OPM-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
; IS__TUNIT_OPM-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
; IS__TUNIT_OPM-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
; IS__TUNIT_OPM-NEXT: ret void
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test0-icmp-check
; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT_NPM-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #2, !range !0
; IS__TUNIT_NPM-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
; IS__TUNIT_NPM-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
; IS__TUNIT_NPM-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
; IS__TUNIT_NPM-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
; IS__TUNIT_NPM-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
; IS__TUNIT_NPM-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
; IS__TUNIT_NPM-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
; IS__TUNIT_NPM-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
; IS__TUNIT_NPM-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
; IS__TUNIT_NPM-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
; IS__TUNIT_NPM-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
; IS__TUNIT_NPM-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
; IS__TUNIT_NPM-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
; IS__TUNIT_NPM-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
; IS__TUNIT_NPM-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
; IS__TUNIT_NPM-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
; IS__TUNIT_NPM-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test0-icmp-check
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
@ -259,11 +311,17 @@ define i32 @test1(i32* %p) {
define i1 @test1-check(i32* %p) {
;
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1-check
; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT____-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly align 4 [[P]]) #4, !range !2
; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
; IS__TUNIT____-NEXT: ret i1 [[CMP]]
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test1-check
; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT_OPM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly align 4 [[P]]) #3, !range !2
; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
; IS__TUNIT_OPM-NEXT: ret i1 [[CMP]]
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test1-check
; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
; IS__TUNIT_NPM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly align 4 [[P]]) #2, !range !2
; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
; IS__TUNIT_NPM-NEXT: ret i1 [[CMP]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1-check
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
@ -566,7 +624,7 @@ define dso_local i32 @test4-g2(i32 %u) {
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test4-g2
; IS__TUNIT_NPM-SAME: (i32 [[U:%.*]])
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #2, !range !3
; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #1, !range !3
; IS__TUNIT_NPM-NEXT: ret i32 [[CALL]]
;
entry:
@ -929,8 +987,8 @@ define i1 @callee_range_2(i1 %c1, i1 %c2) {
;
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_range_2
; IS__TUNIT_OPM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]])
; IS__TUNIT_OPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #2, !range !4
; IS__TUNIT_OPM-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #3, !range !4
; IS__TUNIT_OPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #1, !range !4
; IS__TUNIT_OPM-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #1, !range !4
; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[R1]], [[R2]]
; IS__TUNIT_OPM-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 3
; IS__TUNIT_OPM-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2
@ -939,8 +997,8 @@ define i1 @callee_range_2(i1 %c1, i1 %c2) {
;
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_range_2
; IS__TUNIT_NPM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]])
; IS__TUNIT_NPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #2, !range !5
; IS__TUNIT_NPM-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #3, !range !5
; IS__TUNIT_NPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #1, !range !5
; IS__TUNIT_NPM-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #1, !range !5
; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[R1]], [[R2]]
; IS__TUNIT_NPM-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 3
; IS__TUNIT_NPM-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2

View File

@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM

View File

@ -335,9 +335,7 @@ define void @f1() #0 {
ret void
}
; IS__TUNIT____: Function Attrs: noinline nounwind uwtable
; FIXME: Because we do not derive norecurse in the module run anymore, willreturn is missing as well.
; IS__TUNIT____-NOT: willreturn
; IS__TUNIT____: Function Attrs: noinline nounwind uwtable willreturn
; IS__CGSCC____: Function Attrs: noinline norecurse nounwind uwtable willreturn
define void @f2() #0 {
; CHECK-LABEL: define {{[^@]+}}@f2()