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" } */ + +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" } } */ +