[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