[llvm] [BPI] Refine libcall heuristic (PR #79941)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 29 19:53:05 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: None (lcvon007)

<details>
<summary>Changes</summary>

The return value of fread, fwrite, read and write is likely to
be equal to the count parameter and many system library calls
like mkdir, chown, mkdir etc will return 0 when it runs
successfully, so it can predict the branch probability better
to use these information.


---

Patch is 41.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/79941.diff


2 Files Affected:

- (modified) llvm/lib/Analysis/BranchProbabilityInfo.cpp (+95-13) 
- (modified) llvm/test/Analysis/BranchProbabilityInfo/libfunc_call.ll (+927-15) 


``````````diff
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 6448ed66dc51c..388d446605050 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -162,11 +162,53 @@ static const ProbabilityTable ICmpWithOneTable{
 /// probably false given that what exactly is returned for nonzero values is
 /// not specified. Any kind of comparison other than equality we know
 /// nothing about.
-static const ProbabilityTable ICmpWithLibCallTable{
+static const ProbabilityTable ICmpWithCmpLibCallTable{
     {CmpInst::ICMP_EQ, {ZeroUntakenProb, ZeroTakenProb}},
     {CmpInst::ICMP_NE, {ZeroTakenProb, ZeroUntakenProb}},
 };
 
+// LibCall Heuristics
+static const uint32_t LIBH_TAKEN_WEIGHT = 999;
+static const uint32_t LIBH_NONTAKEN_WEIGHT = 1;
+static const BranchProbability
+    LibTakenProb(LIBH_TAKEN_WEIGHT, LIBH_TAKEN_WEIGHT + LIBH_NONTAKEN_WEIGHT);
+static const BranchProbability LibUntakenProb(LIBH_NONTAKEN_WEIGHT,
+                                              LIBH_TAKEN_WEIGHT +
+                                                  LIBH_NONTAKEN_WEIGHT);
+
+/// The return value of fread, fwrite, read and write will be mostly equal to
+/// the count parameter. So a comparison using eq is probably true when
+/// comparing return value and count parameter.
+static const ProbabilityTable ICmpWithRWLibcallEqTable{
+    {CmpInst::ICMP_EQ, {LibTakenProb, LibUntakenProb}},  /// X == Y -> likely
+    {CmpInst::ICMP_NE, {LibUntakenProb, LibTakenProb}},  /// X != Y -> Unlikely
+    {CmpInst::ICMP_SLT, {LibUntakenProb, LibTakenProb}}, /// X < Y -> Unlikely
+};
+
+/// The return value of fread and fwrite will be zero when size or count
+/// parameter is zero and it's less possible in program. The return value of
+/// read and write will only be -1 when they run failed. So a comparison
+/// with 0 or -1 is probably false.
+static const ProbabilityTable ICmpWithRWLibcallZeroTable{
+    {CmpInst::ICMP_EQ,
+     {LibUntakenProb, LibTakenProb}}, /// X == 0 or -1 -> Unlikely
+    {CmpInst::ICMP_NE,
+     {LibTakenProb, LibUntakenProb}}, /// X != 0 or -1 -> Likely
+};
+
+/// The return value of fread, fwrite, read and write will be mostly not less
+/// than 1. So a comparison that is slt 1 is probably false.
+static const ProbabilityTable ICmpWithRWLibcallOneTable{
+    {CmpInst::ICMP_SLT, {LibUntakenProb, LibTakenProb}}, /// X < 1 -> Unlikely
+};
+
+/// Most system library call like chmod, chown, mkdir etc will return 0 when
+/// they run successfully. So a comparison with 0 is probably true.
+static const ProbabilityTable ICmpWithSysLibcallTable{
+    {CmpInst::ICMP_EQ, {LibTakenProb, LibUntakenProb}}, /// X == 0 -> Likely
+    {CmpInst::ICMP_NE, {LibUntakenProb, LibTakenProb}}, /// X != 0 -> Unlikely
+};
+
 // Floating-Point Heuristics (FPH)
 static const uint32_t FPH_TAKEN_WEIGHT = 20;
 static const uint32_t FPH_NONTAKEN_WEIGHT = 12;
@@ -977,10 +1019,15 @@ bool BranchProbabilityInfo::calcZeroHeuristics(const BasicBlock *BB,
     return dyn_cast<ConstantInt>(V);
   };
 
-  Value *RHS = CI->getOperand(1);
-  ConstantInt *CV = GetConstantInt(RHS);
-  if (!CV)
+  auto IsSameValue = [&](Value *Lhs, Value *Rhs) -> bool {
+    if (Lhs == Rhs)
+      return true;
+    auto *LhsCV = GetConstantInt(Lhs);
+    auto *RhsCV = GetConstantInt(Rhs);
+    if (LhsCV && RhsCV && LhsCV->getZExtValue() == RhsCV->getZExtValue())
+      return true;
     return false;
+  };
 
   // If the LHS is the result of AND'ing a value with a single bit bitmask,
   // we don't have information about probabilities.
@@ -996,16 +1043,51 @@ bool BranchProbabilityInfo::calcZeroHeuristics(const BasicBlock *BB,
     if (CallInst *Call = dyn_cast<CallInst>(CI->getOperand(0)))
       if (Function *CalledFn = Call->getCalledFunction())
         TLI->getLibFunc(*CalledFn, Func);
-
+  Value *RHS = CI->getOperand(1);
+  ConstantInt *CV = GetConstantInt(RHS);
   ProbabilityTable::const_iterator Search;
-  if (Func == LibFunc_strcasecmp ||
-      Func == LibFunc_strcmp ||
-      Func == LibFunc_strncasecmp ||
-      Func == LibFunc_strncmp ||
-      Func == LibFunc_memcmp ||
-      Func == LibFunc_bcmp) {
-    Search = ICmpWithLibCallTable.find(CI->getPredicate());
-    if (Search == ICmpWithLibCallTable.end())
+  if (Func == LibFunc_fread || Func == LibFunc_fwrite || Func == LibFunc_read ||
+      Func == LibFunc_write) {
+    const uint32_t CountOpId = 2;
+    auto *Call = dyn_cast<CallInst>(CI->getOperand(0));
+    if (CV && (CV->isZero() || CV->isMinusOne())) {
+      Search = ICmpWithRWLibcallZeroTable.find(CI->getPredicate());
+      if (Search == ICmpWithRWLibcallZeroTable.end())
+        return false;
+    } else if (CV && CV->isOne()) {
+      Search = ICmpWithRWLibcallOneTable.find(CI->getPredicate());
+      if (Search == ICmpWithRWLibcallOneTable.end())
+        return false;
+    } else if (IsSameValue(Call->getOperand(CountOpId), RHS)) {
+      Search = ICmpWithRWLibcallEqTable.find(CI->getPredicate());
+      if (Search == ICmpWithRWLibcallEqTable.end())
+        return false;
+    } else
+      return false;
+  } else if (!CV)
+    return false;
+  else if (Func == LibFunc_strcasecmp || Func == LibFunc_strcmp ||
+           Func == LibFunc_strncasecmp || Func == LibFunc_strncmp ||
+           Func == LibFunc_memcmp || Func == LibFunc_bcmp) {
+    Search = ICmpWithCmpLibCallTable.find(CI->getPredicate());
+    if (Search == ICmpWithCmpLibCallTable.end())
+      return false;
+  } else if (CV->isZero() &&
+             (Func == LibFunc_chmod || Func == LibFunc_chown ||
+              Func == LibFunc_closedir || Func == LibFunc_fclose ||
+              Func == LibFunc_ferror || Func == LibFunc_fflush ||
+              Func == LibFunc_fseek || Func == LibFunc_fseeko ||
+              Func == LibFunc_fsetpos || Func == LibFunc_fstat ||
+              Func == LibFunc_fstatvfs || Func == LibFunc_ftrylockfile ||
+              Func == LibFunc_lchown || Func == LibFunc_lstat ||
+              Func == LibFunc_mkdir || Func == LibFunc_remove ||
+              Func == LibFunc_rename || Func == LibFunc_rmdir ||
+              Func == LibFunc_setvbuf || Func == LibFunc_stat ||
+              Func == LibFunc_statvfs || Func == LibFunc_unlink ||
+              Func == LibFunc_unsetenv || Func == LibFunc_utime ||
+              Func == LibFunc_utimes)) {
+    Search = ICmpWithSysLibcallTable.find(CI->getPredicate());
+    if (Search == ICmpWithSysLibcallTable.end())
       return false;
   } else if (CV->isZero()) {
     Search = ICmpWithZeroTable.find(CI->getPredicate());
diff --git a/llvm/test/Analysis/BranchProbabilityInfo/libfunc_call.ll b/llvm/test/Analysis/BranchProbabilityInfo/libfunc_call.ll
index c342edcc64afc..6acbed9e77963 100644
--- a/llvm/test/Analysis/BranchProbabilityInfo/libfunc_call.ll
+++ b/llvm/test/Analysis/BranchProbabilityInfo/libfunc_call.ll
@@ -7,13 +7,41 @@ declare i32 @strncasecmp(ptr, ptr, i32)
 declare i32 @memcmp(ptr, ptr)
 declare i32 @bcmp(ptr, ptr)
 declare i32 @nonstrcmp(ptr, ptr)
+declare i64 @fread(ptr, i64, i64, ptr)
+declare i64 @fwrite(ptr, i64, i64, ptr)
+declare i64 @read(i32, ptr, i64)
+declare i64 @write(i32, ptr, i64)
+declare i32 @chmod(ptr, i32)
+declare i32 @chown(ptr, i32, i32)
+declare i32 @closedir(ptr)
+declare i32 @fclose(ptr)
+declare i32 @ferror(ptr)
+declare i32 @fflush(ptr)
+declare i32 @fseek(ptr, i64, i32)
+declare i32 @fseeko(ptr, i64, i32)
+declare i32 @fstat(i32, ptr)
+declare i32 @fstatvfs(i32, ptr)
+declare i32 @ftrylockfile(ptr)
+declare i32 @lchown(ptr)
+declare i32 @lstat(ptr, ptr)
+declare i32 @mkdir(ptr, i32)
+declare i32 @remove(ptr)
+declare i32 @rename(ptr, ptr)
+declare i32 @rmdir(ptr)
+declare i32 @setvbuf(ptr, ptr, i32, i64)
+declare i32 @stat(ptr, ptr)
+declare i32 @statvfs(ptr, ptr)
+declare i32 @unlink(ptr)
+declare i32 @unsetenv(ptr)
+declare i32 @utime(ptr, ptr)
+declare i32 @utimes(ptr, ptr)
 
 
 ; Check that the result of strcmp is considered more likely to be nonzero than
 ; zero, and equally likely to be (nonzero) positive or negative.
 
 define i32 @test_strcmp_eq(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strcmp_eq'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strcmp_eq'
 entry:
   %val = call i32 @strcmp(ptr %p, ptr %q)
   %cond = icmp eq i32 %val, 0
@@ -35,7 +63,7 @@ exit:
 }
 
 define i32 @test_strcmp_eq5(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strcmp_eq5'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strcmp_eq5'
 entry:
   %val = call i32 @strcmp(ptr %p, ptr %q)
   %cond = icmp eq i32 %val, 5
@@ -57,7 +85,7 @@ exit:
 }
 
 define i32 @test_strcmp_ne(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strcmp_ne'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strcmp_ne'
 entry:
   %val = call i32 @strcmp(ptr %p, ptr %q)
   %cond = icmp ne i32 %val, 0
@@ -79,7 +107,7 @@ exit:
 }
 
 define i32 @test_strcmp_sgt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strcmp_sgt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strcmp_sgt'
 entry:
   %val = call i32 @strcmp(ptr %p, ptr %q)
   %cond = icmp sgt i32 %val, 0
@@ -101,7 +129,7 @@ exit:
 }
 
 define i32 @test_strcmp_slt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strcmp_slt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strcmp_slt'
 entry:
   %val = call i32 @strcmp(ptr %p, ptr %q)
   %cond = icmp slt i32 %val, 0
@@ -126,7 +154,7 @@ exit:
 ; Similarly check other library functions that have the same behaviour
 
 define i32 @test_strncmp_sgt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strncmp_sgt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strncmp_sgt'
 entry:
   %val = call i32 @strncmp(ptr %p, ptr %q, i32 4)
   %cond = icmp sgt i32 %val, 0
@@ -148,7 +176,7 @@ exit:
 }
 
 define i32 @test_strcasecmp_sgt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strcasecmp_sgt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strcasecmp_sgt'
 entry:
   %val = call i32 @strcasecmp(ptr %p, ptr %q)
   %cond = icmp sgt i32 %val, 0
@@ -170,7 +198,7 @@ exit:
 }
 
 define i32 @test_strncasecmp_sgt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_strncasecmp_sgt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_strncasecmp_sgt'
 entry:
   %val = call i32 @strncasecmp(ptr %p, ptr %q, i32 4)
   %cond = icmp sgt i32 %val, 0
@@ -192,7 +220,7 @@ exit:
 }
 
 define i32 @test_memcmp_sgt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_memcmp_sgt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_memcmp_sgt'
 entry:
   %val = call i32 @memcmp(ptr %p, ptr %q)
   %cond = icmp sgt i32 %val, 0
@@ -219,7 +247,7 @@ exit:
 ; likely than zero.
 
 define i32 @test_nonstrcmp_eq(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_nonstrcmp_eq'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_nonstrcmp_eq'
 entry:
   %val = call i32 @nonstrcmp(ptr %p, ptr %q)
   %cond = icmp eq i32 %val, 0
@@ -241,7 +269,7 @@ exit:
 }
 
 define i32 @test_nonstrcmp_ne(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_nonstrcmp_ne'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_nonstrcmp_ne'
 entry:
   %val = call i32 @nonstrcmp(ptr %p, ptr %q)
   %cond = icmp ne i32 %val, 0
@@ -263,7 +291,7 @@ exit:
 }
 
 define i32 @test_nonstrcmp_sgt(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_nonstrcmp_sgt'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_nonstrcmp_sgt'
 entry:
   %val = call i32 @nonstrcmp(ptr %p, ptr %q)
   %cond = icmp sgt i32 %val, 0
@@ -286,7 +314,7 @@ exit:
 
 
 define i32 @test_bcmp_eq(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_bcmp_eq'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_bcmp_eq'
 entry:
   %val = call i32 @bcmp(ptr %p, ptr %q)
   %cond = icmp eq i32 %val, 0
@@ -308,7 +336,7 @@ exit:
 }
 
 define i32 @test_bcmp_eq5(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_bcmp_eq5'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_bcmp_eq5'
 entry:
   %val = call i32 @bcmp(ptr %p, ptr %q)
   %cond = icmp eq i32 %val, 5
@@ -332,7 +360,7 @@ exit:
 
 
 define i32 @test_bcmp_ne(ptr %p, ptr %q) {
-; CHECK: Printing analysis {{.*}} for function 'test_bcmp_ne'
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_bcmp_ne'
 entry:
   %val = call i32 @bcmp(ptr %p, ptr %q)
   %cond = icmp ne i32 %val, 0
@@ -352,3 +380,887 @@ exit:
   %result = phi i32 [ 0, %then ], [ 1, %else ]
   ret i32 %result
 }
+
+define i32 @test_fread_eq_zero(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_eq_zero'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp eq i64 %val, 0
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_ne_zero(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_ne_zero'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp ne i64 %val, 0
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+; CHECK: edge %entry -> %else probability is 0x0020c49c / 0x80000000 = 0.10%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_slt_one(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_slt_one'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp slt i64 %val, 1
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_eq_count(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_eq_count'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp eq i64 %val, %count
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+; CHECK: edge %entry -> %else probability is 0x0020c49c / 0x80000000 = 0.10%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_ne_count(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_ne_count'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp ne i64 %val, %count
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_eq_const_count(i64 %size, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_eq_const_count'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 10, ptr %q)
+  %cond = icmp eq i64 %val, 10
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+; CHECK: edge %entry -> %else probability is 0x0020c49c / 0x80000000 = 0.10%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_ne_const_count(i64 %size, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_ne_const_count'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 10, ptr %q)
+  %cond = icmp ne i64 %val, 10
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_slt_count(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_slt_count'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp slt i64 %val, %count
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+define i32 @test_fread_slt_const_count(i64 %size, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fread_slt_const_count'
+entry:
+  %val = call i64 @fread(ptr %p, i64 %size, i64 10, ptr %q)
+  %cond = icmp slt i64 %val, 10
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
+; fwrite only tests eq predicate
+define i32 @test_fwrite_eq_zero(i64 %size, i64 %count, ptr %p, ptr %q) {
+; CHECK-LABEL: Printing analysis {{.*}} for function 'test_fwrite_eq_zero'
+entry:
+  %val = call i64 @fwrite(ptr %p, i64 %size, i64 %count, ptr %q)
+  %cond = icmp eq i64 %val, 0
+  br i1 %cond, label %then, label %else
+; CHECK: edge %entry -> %then probability is 0x0020c49c / 0x80000000 = 0.10%
+; CHECK: edge %entry -> %else probability is 0x7fdf3b64 / 0x80000000 = 99.90%
+
+then:
+  br label %exit
+; CHECK: edge %then -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+else:
+  br label %exit
+; CHECK: edge %else -> %exit probability is 0x80000000 / 0x80000000 = 100.00% [HOT edge]
+
+exit:
+  %result = phi i32 [ 0, %then ], [ 1, %else ]
+  ret i32 %result
+}
+
...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/79941


More information about the llvm-commits mailing list