-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BPI] Refine libcall heuristic #79941
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-analysis Author: None (lcvon007) ChangesThe return value of fread, fwrite, read and write is likely to 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:
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]
|
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.
e1c16e7
to
5a51d46
Compare
@davidbolvansky @john-brawn-arm @ebrevnov @ZequanWu @topperc , please help review, thanks very much |
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.