This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Improve VPR for some builtins and non pointer checks
On Sun, Sep 2, 2012 at 11:36 PM, Georg-Johann Lay <gjl@gcc.gnu.org> wrote:
> Andrew Pinski schrieb:
>>
>> Hi,
>> While fixing some code not to have aliasing violations in it, I can
>> across that some builtins were not causing their arguments or their
>> return values being marked as non-null. This patch implements just
>> that in VPR while allowing to remove some null pointer checks later
>> on.
>>
>> OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
>>
>> Thanks,
>> Andrew Pinski
>>
>> ChangeLog:
>> * tree-vrp.c (vrp_stmt_computes_nonzero): Return true for some
>> builtins (memcpy and memmove).
>> (infer_value_range): Infer nonzero for some arguments to
>> some builtins (memcpy, memmove, strcmp and memcmp).
>>
>> testsuite/ChangeLog:
>> * gcc.dg/tree-ssa/vrp-builtins1.c: New testcase.
>>
>>
>>
>> Index: tree-vrp.c
>> ===================================================================
>> --- tree-vrp.c (revision 190868)
>> +++ tree-vrp.c (working copy)
>> @@ -1057,6 +1057,20 @@ vrp_stmt_computes_nonzero (gimple stmt,
>> }
>> }
>> + /* With some builtins, we can infer if the pointer return value
>> + will be non null. */
>> + if (flag_delete_null_pointer_checks
>> + && is_gimple_call (stmt) && gimple_call_fndecl (stmt)
>> + && DECL_BUILT_IN_CLASS (gimple_call_fndecl (stmt)) ==
>> BUILT_IN_NORMAL)
>> + {
>> + switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
>> + {
>> + case BUILT_IN_MEMCPY:
>> + case BUILT_IN_MEMMOVE:
>> + return true;
>> + }
>> + }
>> +
>> return false;
>> }
>> @@ -4231,6 +4245,32 @@ infer_value_range (gimple stmt, tree op,
>> }
>> }
>> + /* With some builtins, we can infer if the pointer argument
>> + will be non null. */
>> + if (flag_delete_null_pointer_checks
>> + && is_gimple_call (stmt) && gimple_call_fndecl (stmt))
>> + {
>> + tree callee = gimple_call_fndecl (stmt);
>> + if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
>> + {
>> + switch (DECL_FUNCTION_CODE (callee))
>> + {
>> + case BUILT_IN_MEMCPY:
>> + case BUILT_IN_MEMMOVE:
>> + case BUILT_IN_STRCMP:
>> + case BUILT_IN_MEMCMP:
>> + /* The first and second arguments of memcpy and memmove
>> will be non null after the call. */
>> + if (gimple_call_arg (stmt, 0) == op
>> + || gimple_call_arg (stmt, 1) == op)
>> + {
>> + *val_p = build_int_cst (TREE_TYPE (op), 0);
>> + *comp_code_p = NE_EXPR;
>> + return true;
>> + }
>> + }
>> + }
>> + }
>> +
>> return false;
>> }
>> Index: testsuite/gcc.dg/tree-ssa/vrp-builtins1.c
>> ===================================================================
>> --- testsuite/gcc.dg/tree-ssa/vrp-builtins1.c (revision 0)
>> +++ testsuite/gcc.dg/tree-ssa/vrp-builtins1.c (revision 0)
>> @@ -0,0 +1,30 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -fdump-tree-vrp1" } */
>
>
> Shouldn't this xfail for avr and other targets that set
> flag_delete_null_pointer_checks = 0, cf.
> avr.c:avr_option_override() for example.
This is taken care of by the check keeps_null_pointer_checks which
returns true for avr-*-*.
Thanks,
Andrew Pinski
>
> Johann
>
>> +
>> +struct f1
>> +{
>> +char a[4];
>> +};
>> +
>> +int f(int *a, struct f1 b)
>> +{
>> + int *c = __builtin_memcpy(a, b.a, 4);
>> + if (c == 0)
>> + return 0;
>> + return *a;
>> +}
>> +
>> +
>> +int f1(int *a, struct f1 b)
>> +{
>> + int *c = __builtin_memcpy(a, b.a, 4);
>> + if (a == 0)
>> + return 0;
>> + return *a;
>> +}
>> +
>> +/* Both the if statements should be folded when the target does not keep
>> around null pointer checks. */
>> +/* { dg-final { scan-tree-dump-times "Folding predicate" 0 "vrp1" {
>> target { keeps_null_pointer_checks } } } } */
>> +/* { dg-final { scan-tree-dump-times "Folding predicate" 2 "vrp1" {
>> target { ! keeps_null_pointer_checks } } } } */
>> +/* { dg-final { cleanup-tree-dump "vrp1" } } */
>> +
>
>