[PATCH] Handle __builtin_expect in gimple_boolify (PR middle-end/42233)
Jakub Jelinek
jakub@redhat.com
Thu Feb 18 20:08:00 GMT 2010
Hi!
On
extern void likely ();
extern void unlikely ();
void
test_expect (char *a, char *b, char *c, char *d)
{
if (__builtin_expect ((a == b && c == d), 0))
unlikely ();
else
likely ();
}
gcc generates (IMHO) significantly worse code on x86_64 with the
__builtin_expect than with -D'__builtin_expect(a,b)=a' at -O2:
cmpq %rcx, %rdx
je .L4
.L2: xorl %eax, %eax
jmp likely
.p2align 4,,10
.p2align 3
.L4: cmpq %rsi, %rdi
jne .L2
xorl %eax, %eax
jmp unlikely
with __builtin_expect defined away and:
cmpq %rcx, %rdx
sete %dl
xorl %eax, %eax
cmpq %rsi, %rdi
movzbl %dl, %edx
sete %al
testl %eax, %edx
jne .L4
xorl %eax, %eax
jmp likely
.L4: xorl %eax, %eax
jmp unlikely
when __builtin_expect is used. The problem is that without __builtin_expect
gimple_boolify changes types of the condition to _Bool and therefore at
expansion time gcc is able to optimize &&, while with __builtin_expect
gimple_boolify just boolifies it by casing __builtin_expect result to _Bool.
The following patch fixes it by boolifying also first __builtin_expect
argument to make sure __builtin_expect is less intrusive.
Bootstrapped/regtested on x86_64-linux and i686-linux, will commit to trunk
tomorrow unless somebody objects.
2010-02-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/42233
* gimplify.c (gimple_boolify): For __builtin_expect call
gimple_boolify also on its first argument.
--- gcc/gimplify.c.jj 2010-02-09 19:17:08.000000000 +0100
+++ gcc/gimplify.c 2010-02-18 12:45:21.000000000 +0100
@@ -2720,6 +2720,32 @@ gimple_boolify (tree expr)
tree type = TREE_TYPE (expr);
location_t loc = EXPR_LOCATION (expr);
+ if (TREE_CODE (expr) == NE_EXPR
+ && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
+ && integer_zerop (TREE_OPERAND (expr, 1)))
+ {
+ tree call = TREE_OPERAND (expr, 0);
+ tree fn = get_callee_fndecl (call);
+
+ /* For __builtin_expect ((long) (x), y) recurse into x as well. */
+ if (fn
+ && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (fn) == BUILT_IN_EXPECT
+ && call_expr_nargs (call) == 2)
+ {
+ tree arg = CALL_EXPR_ARG (call, 0);
+ if (arg)
+ {
+ if (TREE_CODE (arg) == NOP_EXPR
+ && TREE_TYPE (arg) == TREE_TYPE (call))
+ arg = TREE_OPERAND (arg, 0);
+ arg = gimple_boolify (arg);
+ CALL_EXPR_ARG (call, 0)
+ = fold_convert_loc (loc, TREE_TYPE (call), arg);
+ }
+ }
+ }
+
if (TREE_CODE (type) == BOOLEAN_TYPE)
return expr;
Jakub
More information about the Gcc-patches
mailing list