mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
9f05fb5e02
The zero heuristic assumes that integers are more likely positive than negative, but this also has the effect of assuming that strcmp return values are more likely positive than negative. Given that for nonzero strcmp return values it's the ordering of arguments that determines the sign of the result there's no reason to assume that's true. Fix this by inspecting the LHS of the compare and using TargetLibraryInfo to decide if it's strcmp-like, and if so only assume that nonzero is more likely than zero i.e. strings are more often different than the same. This causes a slight code generation change in the spec2006 benchmark 403.gcc, but with no noticeable performance impact. The intent of this patch is to allow better optimisation of dhrystone on Cortex-M cpus, but currently it won't as there are also some changes that need to be made to if-conversion. Differential Revision: https://reviews.llvm.org/D33934 llvm-svn: 304970
265 lines
8.1 KiB
LLVM
265 lines
8.1 KiB
LLVM
; RUN: opt < %s -analyze -branch-prob | FileCheck %s
|
|
; RUN: opt < %s -analyze -lazy-branch-prob | FileCheck %s
|
|
; RUN: opt < %s -passes='print<branch-prob>' -disable-output 2>&1 | FileCheck %s
|
|
|
|
declare i32 @strcmp(i8*, i8*)
|
|
declare i32 @strncmp(i8*, i8*, i32)
|
|
declare i32 @strcasecmp(i8*, i8*)
|
|
declare i32 @strncasecmp(i8*, i8*, i32)
|
|
declare i32 @memcmp(i8*, i8*)
|
|
declare i32 @nonstrcmp(i8*, i8*)
|
|
|
|
|
|
; 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(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strcmp_eq'
|
|
entry:
|
|
%val = call i32 @strcmp(i8* %p, i8* %q)
|
|
%cond = icmp eq i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x30000000 / 0x80000000 = 37.50%
|
|
; CHECK: edge entry -> else probability is 0x50000000 / 0x80000000 = 62.50%
|
|
|
|
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_strcmp_ne(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strcmp_ne'
|
|
entry:
|
|
%val = call i32 @strcmp(i8* %p, i8* %q)
|
|
%cond = icmp ne i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x50000000 / 0x80000000 = 62.50%
|
|
; CHECK: edge entry -> else probability is 0x30000000 / 0x80000000 = 37.50%
|
|
|
|
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_strcmp_sgt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strcmp_sgt'
|
|
entry:
|
|
%val = call i32 @strcmp(i8* %p, i8* %q)
|
|
%cond = icmp sgt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00%
|
|
; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00%
|
|
|
|
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_strcmp_slt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strcmp_slt'
|
|
entry:
|
|
%val = call i32 @strcmp(i8* %p, i8* %q)
|
|
%cond = icmp slt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00%
|
|
; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00%
|
|
|
|
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
|
|
}
|
|
|
|
|
|
; Similarly check other library functions that have the same behaviour
|
|
|
|
define i32 @test_strncmp_sgt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strncmp_sgt'
|
|
entry:
|
|
%val = call i32 @strncmp(i8* %p, i8* %q, i32 4)
|
|
%cond = icmp sgt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00%
|
|
; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00%
|
|
|
|
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_strcasecmp_sgt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strcasecmp_sgt'
|
|
entry:
|
|
%val = call i32 @strcasecmp(i8* %p, i8* %q)
|
|
%cond = icmp sgt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00%
|
|
; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00%
|
|
|
|
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_strncasecmp_sgt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_strncasecmp_sgt'
|
|
entry:
|
|
%val = call i32 @strncasecmp(i8* %p, i8* %q, i32 4)
|
|
%cond = icmp sgt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00%
|
|
; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00%
|
|
|
|
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_memcmp_sgt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_memcmp_sgt'
|
|
entry:
|
|
%val = call i32 @memcmp(i8* %p, i8* %q)
|
|
%cond = icmp sgt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x40000000 / 0x80000000 = 50.00%
|
|
; CHECK: edge entry -> else probability is 0x40000000 / 0x80000000 = 50.00%
|
|
|
|
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
|
|
}
|
|
|
|
|
|
; Check that for the result of a call to a non-library function the default
|
|
; heuristic is applied, i.e. positive more likely than negative, nonzero more
|
|
; likely than zero.
|
|
|
|
define i32 @test_nonstrcmp_eq(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_nonstrcmp_eq'
|
|
entry:
|
|
%val = call i32 @nonstrcmp(i8* %p, i8* %q)
|
|
%cond = icmp eq i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x30000000 / 0x80000000 = 37.50%
|
|
; CHECK: edge entry -> else probability is 0x50000000 / 0x80000000 = 62.50%
|
|
|
|
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_nonstrcmp_ne(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_nonstrcmp_ne'
|
|
entry:
|
|
%val = call i32 @nonstrcmp(i8* %p, i8* %q)
|
|
%cond = icmp ne i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x50000000 / 0x80000000 = 62.50%
|
|
; CHECK: edge entry -> else probability is 0x30000000 / 0x80000000 = 37.50%
|
|
|
|
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_nonstrcmp_sgt(i8* %p, i8* %q) {
|
|
; CHECK: Printing analysis {{.*}} for function 'test_nonstrcmp_sgt'
|
|
entry:
|
|
%val = call i32 @nonstrcmp(i8* %p, i8* %q)
|
|
%cond = icmp sgt i32 %val, 0
|
|
br i1 %cond, label %then, label %else
|
|
; CHECK: edge entry -> then probability is 0x50000000 / 0x80000000 = 62.50%
|
|
; CHECK: edge entry -> else probability is 0x30000000 / 0x80000000 = 37.50%
|
|
|
|
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
|
|
}
|