[llvm] 64ef29b - [Attributor] Call site specific AAValueSimplification and AAIsDead.
Kuter Dinel via llvm-commits
llvm-commits at lists.llvm.org
Sat May 15 14:39:36 PDT 2021
Author: Kuter Dinel
Date: 2021-05-15T21:39:07Z
New Revision: 64ef29bc66aae98efe27553267f1d56a62ee1a4d
URL: https://github.com/llvm/llvm-project/commit/64ef29bc66aae98efe27553267f1d56a62ee1a4d
DIFF: https://github.com/llvm/llvm-project/commit/64ef29bc66aae98efe27553267f1d56a62ee1a4d.diff
LOG: [Attributor] Call site specific AAValueSimplification and AAIsDead.
This patch makes it possible to do call site specific deductions
for AAValueSimplification and AAIsDead.
Reviewed By: jdoerfert
Differential Revision: https://reviews.llvm.org/D84722
Added:
llvm/test/Transforms/Attributor/cb_liveness_disabled.ll
llvm/test/Transforms/Attributor/cb_liveness_enabled.ll
Modified:
llvm/lib/Transforms/IPO/Attributor.cpp
llvm/lib/Transforms/IPO/AttributorAttributes.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index cc8804f9d9d2b..fc025ea124074 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -546,8 +546,8 @@ void IRPosition::verify() {
Optional<Constant *>
Attributor::getAssumedConstant(const Value &V, const AbstractAttribute &AA,
bool &UsedAssumedInformation) {
- const auto &ValueSimplifyAA =
- getAAFor<AAValueSimplify>(AA, IRPosition::value(V), DepClassTy::NONE);
+ const auto &ValueSimplifyAA = getAAFor<AAValueSimplify>(
+ AA, IRPosition::value(V, AA.getCallBaseContext()), DepClassTy::NONE);
Optional<Value *> SimplifiedV =
ValueSimplifyAA.getAssumedSimplifiedValue(*this);
bool IsKnown = ValueSimplifyAA.isKnown();
@@ -624,9 +624,13 @@ bool Attributor::isAssumedDead(const Instruction &I,
const AbstractAttribute *QueryingAA,
const AAIsDead *FnLivenessAA,
bool CheckBBLivenessOnly, DepClassTy DepClass) {
+ const IRPosition::CallBaseContext *CBCtx =
+ QueryingAA ? QueryingAA->getCallBaseContext() : nullptr;
+
if (!FnLivenessAA)
- FnLivenessAA = lookupAAFor<AAIsDead>(IRPosition::function(*I.getFunction()),
- QueryingAA, DepClassTy::NONE);
+ FnLivenessAA =
+ lookupAAFor<AAIsDead>(IRPosition::function(*I.getFunction(), CBCtx),
+ QueryingAA, DepClassTy::NONE);
// If we have a context instruction and a liveness AA we use it.
if (FnLivenessAA &&
@@ -641,7 +645,7 @@ bool Attributor::isAssumedDead(const Instruction &I,
return false;
const AAIsDead &IsDeadAA = getOrCreateAAFor<AAIsDead>(
- IRPosition::value(I), QueryingAA, DepClassTy::NONE);
+ IRPosition::value(I, CBCtx), QueryingAA, DepClassTy::NONE);
// Don't check liveness for AAIsDead.
if (QueryingAA == &IsDeadAA)
return false;
@@ -899,7 +903,8 @@ bool Attributor::checkForAllReturnedValues(
return false;
// TODO: use the function scope once we have call site AAReturnedValues.
- const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
+ const IRPosition &QueryIRP = IRPosition::function(
+ *AssociatedFunction, QueryingAA.getCallBaseContext());
const auto &AARetVal =
getAAFor<AAReturnedValues>(QueryingAA, QueryIRP, DepClassTy::REQUIRED);
if (!AARetVal.getState().isValidState())
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 33ed2b4423a8a..a0af66d245203 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -263,7 +263,8 @@ static bool genericValueTraversal(
const AAIsDead *LivenessAA = nullptr;
if (IRP.getAnchorScope())
LivenessAA = &A.getAAFor<AAIsDead>(
- QueryingAA, IRPosition::function(*IRP.getAnchorScope()),
+ QueryingAA,
+ IRPosition::function(*IRP.getAnchorScope(), IRP.getCallBaseContext()),
DepClassTy::NONE);
bool AnyDead = false;
@@ -1088,7 +1089,7 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A) {
// Helper method to invoke the generic value traversal.
auto VisitReturnedValue = [&](Value &RV, RVState &RVS,
const Instruction *CtxI) {
- IRPosition RetValPos = IRPosition::value(RV);
+ IRPosition RetValPos = IRPosition::value(RV, getCallBaseContext());
return genericValueTraversal<AAReturnedValues, RVState>(
A, RetValPos, *this, RVS, VisitValueCB, CtxI,
/* UseValueSimplify */ false);
@@ -4559,7 +4560,9 @@ struct AAValueSimplifyImpl : AAValueSimplify {
// FIXME: Add a typecast support.
auto &ValueSimplifyAA = A.getAAFor<AAValueSimplify>(
- QueryingAA, IRPosition::value(QueryingValue), DepClassTy::REQUIRED);
+ QueryingAA,
+ IRPosition::value(QueryingValue, QueryingAA.getCallBaseContext()),
+ DepClassTy::REQUIRED);
Optional<Value *> QueryingValueSimplified =
ValueSimplifyAA.getAssumedSimplifiedValue(A);
@@ -4594,6 +4597,7 @@ struct AAValueSimplifyImpl : AAValueSimplify {
if (!getAssociatedValue().getType()->isIntegerTy())
return false;
+ // This will also pass the call base context.
const auto &AA =
A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
@@ -4722,9 +4726,17 @@ struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
return checkAndUpdate(A, *this, ArgOp, SimplifiedAssociatedValue);
};
+ // Generate a answer specific to a call site context.
+ bool Success;
bool AllCallSitesKnown;
- if (!A.checkForAllCallSites(PredForCallSite, *this, true,
- AllCallSitesKnown))
+ if (hasCallBaseContext())
+ Success = PredForCallSite(
+ AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
+ else
+ Success = A.checkForAllCallSites(PredForCallSite, *this, true,
+ AllCallSitesKnown);
+
+ if (!Success)
if (!askSimplifiedValueForOtherAAs(A))
return indicatePessimisticFixpoint();
@@ -4895,8 +4907,9 @@ struct AAValueSimplifyFloating : AAValueSimplifyImpl {
auto VisitValueCB = [&](Value &V, const Instruction *CtxI, bool &,
bool Stripped) -> bool {
- auto &AA = A.getAAFor<AAValueSimplify>(*this, IRPosition::value(V),
- DepClassTy::REQUIRED);
+ auto &AA = A.getAAFor<AAValueSimplify>(
+ *this, IRPosition::value(V, getCallBaseContext()),
+ DepClassTy::REQUIRED);
if (!Stripped && this == &AA) {
// TODO: Look the instruction and check recursively.
@@ -7360,7 +7373,8 @@ struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
// If the value is not instruction, we query AA to Attributor.
const auto &AA = A.getAAFor<AAValueConstantRange>(
- *this, IRPosition::value(V), DepClassTy::REQUIRED);
+ *this, IRPosition::value(V, getCallBaseContext()),
+ DepClassTy::REQUIRED);
// Clamp operator is not used to utilize a program point CtxI.
T.unionAssumed(AA.getAssumedConstantRange(A, CtxI));
diff --git a/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll b/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll
new file mode 100644
index 0000000000000..b954fa84e858e
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/cb_liveness_disabled.ll
@@ -0,0 +1,166 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-globals
+; call site specific analysis is disabled
+
+; RUN: opt -attributor -enable-new-pm=0 -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 -enable-new-pm=0 -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
+
+define dso_local i32 @test_range1(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_range1
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
+; CHECK: 3:
+; CHECK-NEXT: br label [[TMP5:%.*]]
+; CHECK: 4:
+; CHECK-NEXT: br label [[TMP5]]
+; CHECK: 5:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 100, [[TMP3]] ], [ 0, [[TMP4]] ]
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+ %2 = icmp ne i32 %0, 0
+ br i1 %2, label %3, label %4
+
+3: ; preds = %1
+ br label %5
+
+4: ; preds = %1
+ br label %5
+
+5: ; preds = %4, %3
+ %.0 = phi i32 [ 100, %3 ], [ 0, %4 ]
+ ret i32 %.0
+}
+
+define i32 @test_range2(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_range2
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
+; CHECK: 3:
+; CHECK-NEXT: br label [[TMP5:%.*]]
+; CHECK: 4:
+; CHECK-NEXT: br label [[TMP5]]
+; CHECK: 5:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 100, [[TMP3]] ], [ 200, [[TMP4]] ]
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+ %2 = icmp ne i32 %0, 0
+ br i1 %2, label %3, label %4
+
+3: ; preds = %1
+ br label %5
+
+4: ; preds = %1
+ br label %5
+
+5: ; preds = %4, %3
+ %.0 = phi i32 [ 100, %3 ], [ 200, %4 ]
+ ret i32 %.0
+}
+define i32 @test(i32 %0, i32 %1) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test
+; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
+; CHECK: 4:
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
+; CHECK-NEXT: br label [[TMP8:%.*]]
+; CHECK: 6:
+; CHECK-NEXT: [[TMP7:%.*]] = call i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
+; CHECK-NEXT: br label [[TMP8]]
+; CHECK: 8:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+ %3 = icmp ne i32 %1, 0
+ br i1 %3, label %4, label %6
+
+4: ; preds = %2
+ %5 = call i32 @test_range1(i32 %0)
+ br label %8
+
+6: ; preds = %2
+ %7 = call i32 @test_range2(i32 %0)
+ br label %8
+
+8: ; preds = %6, %4
+ %.0 = phi i32 [ %5, %4 ], [ %7, %6 ]
+ ret i32 %.0
+}
+
+define i32 @test_pcheck1(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_pcheck1
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
+; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 1)
+ %3 = icmp slt i32 %2, 101
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+define i32 @test_pcheck2(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_pcheck2
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
+; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 0)
+ %3 = icmp sgt i32 %2, 99
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+define i32 @test_ncheck1(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_ncheck1
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
+; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 1)
+ %3 = icmp sgt i32 %2, 50
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+define i32 @test_ncheck2(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_ncheck2
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
+; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 0)
+ %3 = icmp sgt i32 %2, 150
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+attributes #0 = { noinline nounwind sspstrong uwtable}
+
+; IS__TUNIT_____: !0 = !{i32 0, i32 101}
+; IS__TUNIT_____: !1 = !{i32 100, i32 201}
+;.
+; IS__TUNIT____: attributes #[[ATTR0]] = { nofree noinline nosync nounwind readnone sspstrong uwtable willreturn }
+; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
+;.
+; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone sspstrong uwtable willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
+;.
+; CHECK: [[RNG0]] = !{i32 0, i32 101}
+; CHECK: [[RNG1]] = !{i32 100, i32 201}
+; CHECK: [[RNG2]] = !{i32 0, i32 201}
+;.
diff --git a/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll b/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll
new file mode 100644
index 0000000000000..ef214cb11ceab
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/cb_liveness_enabled.ll
@@ -0,0 +1,194 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-globals
+; call site specific analysis is enabled
+
+; RUN: opt -attributor -enable-new-pm=0 -attributor-enable-call-site-specific-deduction=true -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-enable-call-site-specific-deduction=true -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-enable-call-site-specific-deduction=true -enable-new-pm=0 -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-enable-call-site-specific-deduction=true -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
+
+define dso_local i32 @test_range1(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_range1
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
+; CHECK: 3:
+; CHECK-NEXT: br label [[TMP5:%.*]]
+; CHECK: 4:
+; CHECK-NEXT: br label [[TMP5]]
+; CHECK: 5:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 100, [[TMP3]] ], [ 0, [[TMP4]] ]
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+ %2 = icmp ne i32 %0, 0
+ br i1 %2, label %3, label %4
+
+3: ; preds = %1
+ br label %5
+
+4: ; preds = %1
+ br label %5
+
+5: ; preds = %4, %3
+ %.0 = phi i32 [ 100, %3 ], [ 0, %4 ]
+ ret i32 %.0
+}
+
+define i32 @test_range2(i32 %0) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test_range2
+; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]]
+; CHECK: 3:
+; CHECK-NEXT: br label [[TMP5:%.*]]
+; CHECK: 4:
+; CHECK-NEXT: br label [[TMP5]]
+; CHECK: 5:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 100, [[TMP3]] ], [ 200, [[TMP4]] ]
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+ %2 = icmp ne i32 %0, 0
+ br i1 %2, label %3, label %4
+
+3: ; preds = %1
+ br label %5
+
+4: ; preds = %1
+ br label %5
+
+5: ; preds = %4, %3
+ %.0 = phi i32 [ 100, %3 ], [ 200, %4 ]
+ ret i32 %.0
+}
+define i32 @test(i32 %0, i32 %1) #0 {
+; CHECK-LABEL: define {{[^@]+}}@test
+; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
+; CHECK: 4:
+; CHECK-NEXT: [[TMP5:%.*]] = call i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
+; CHECK-NEXT: br label [[TMP8:%.*]]
+; CHECK: 6:
+; CHECK-NEXT: [[TMP7:%.*]] = call i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
+; CHECK-NEXT: br label [[TMP8]]
+; CHECK: 8:
+; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
+; CHECK-NEXT: ret i32 [[DOT0]]
+;
+ %3 = icmp ne i32 %1, 0
+ br i1 %3, label %4, label %6
+
+4: ; preds = %2
+ %5 = call i32 @test_range1(i32 %0)
+ br label %8
+
+6: ; preds = %2
+ %7 = call i32 @test_range2(i32 %0)
+ br label %8
+
+8: ; preds = %6, %4
+ %.0 = phi i32 [ %5, %4 ], [ %7, %6 ]
+ ret i32 %.0
+}
+
+define i32 @test_pcheck1(i32 %0) #0 {
+; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck1
+; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__TUNIT____-NEXT: ret i32 1
+;
+; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck1
+; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]]
+; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
+; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
+;
+; IS__TUNIT_____ENABLED-LABEL: define {{[^@]+}}@test_pcheck1
+; IS__TUNIT_____ENABLED-SAME: (i32 [[TMP0:%.*]])
+; IS__TUNIT_____ENABLED-NEXT: ret i32 1
+ %2 = call i32 @test(i32 %0, i32 1)
+ %3 = icmp slt i32 %2, 101
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+define i32 @test_pcheck2(i32 %0) #0 {
+; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck2
+; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__TUNIT____-NEXT: ret i32 1
+;
+; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck2
+; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
+; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
+; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 0)
+ %3 = icmp sgt i32 %2, 99
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+define i32 @test_ncheck1(i32 %0) #0 {
+; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck1
+; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG0]]
+; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
+; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
+;
+; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck1
+; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
+; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
+; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 1)
+ %3 = icmp sgt i32 %2, 50
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+define i32 @test_ncheck2(i32 %0) #0 {
+; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck2
+; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG1]]
+; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
+; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
+;
+; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck2
+; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
+; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
+; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
+; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
+;
+ %2 = call i32 @test(i32 %0, i32 0)
+ %3 = icmp sgt i32 %2, 150
+ %4 = zext i1 %3 to i32
+ ret i32 %4
+}
+
+attributes #0 = { noinline nounwind sspstrong uwtable}
+
+; IS__TUNIT_____: !0 = !{i32 0, i32 101}
+; IS__TUNIT_____: !1 = !{i32 100, i32 201}
+;.
+; IS__TUNIT____: attributes #[[ATTR0]] = { nofree noinline nosync nounwind readnone sspstrong uwtable willreturn }
+; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
+;.
+; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone sspstrong uwtable willreturn }
+; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
+;.
+; IS__TUNIT____: [[RNG0]] = !{i32 0, i32 101}
+; IS__TUNIT____: [[RNG1]] = !{i32 100, i32 201}
+;.
+; IS__CGSCC____: [[RNG0]] = !{i32 0, i32 101}
+; IS__CGSCC____: [[RNG1]] = !{i32 100, i32 201}
+; IS__CGSCC____: [[RNG2]] = !{i32 0, i32 201}
+;.
More information about the llvm-commits
mailing list