On Thu, Nov 14, 2024 at 10:05:05AM -0500, Andrew MacLeod wrote: > The inferred range mechanism is also initialized using cfun, so again > introducing a use of cfun shouldnt be an issue. > > Something like this ought to work I think?
Thanks. Seems to work in quick smoke testing and I've added a testcase to cover that. So, I'll bootstrap/regtest it next. 2024-11-14 Jakub Jelinek <ja...@redhat.com> Andrew MacLeod <amacl...@redhat.com> PR c/117023 * gimple-range-infer.cc (gimple_infer_range::gimple_infer_range): Handle also nonnull_if_nonzero attributes. * gcc.dg/tree-ssa/pr78154-2.c: New test. --- gcc/gimple-range-infer.cc.jj 2024-10-24 18:53:39.355071463 +0200 +++ gcc/gimple-range-infer.cc 2024-11-14 17:46:37.033477580 +0100 @@ -184,6 +184,29 @@ gimple_infer_range::gimple_infer_range ( } BITMAP_FREE (nonnullargs); } + if (fntype) + for (tree attrs = TYPE_ATTRIBUTES (fntype); + (attrs = lookup_attribute ("nonnull_if_nonzero", attrs)); + attrs = TREE_CHAIN (attrs)) + { + tree args = TREE_VALUE (attrs); + unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1; + unsigned int idx2 + = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1; + if (idx < gimple_call_num_args (s) + && idx2 < gimple_call_num_args (s)) + { + tree arg = gimple_call_arg (s, idx); + tree arg2 = gimple_call_arg (s, idx2); + if (!POINTER_TYPE_P (TREE_TYPE (arg)) + || !INTEGRAL_TYPE_P (TREE_TYPE (arg2))) + continue; + value_range r (TREE_TYPE (arg2)); + if (get_range_query (cfun)->range_of_expr (r, arg2, s) + && !r.contains_p (build_zero_cst (TREE_TYPE (arg2)))) + add_nonzero (arg); + } + } // Fallthru and walk load/store ops now. } --- gcc/testsuite/gcc.dg/tree-ssa/pr78154-2.c.jj 2024-11-14 18:01:10.190001548 +0100 +++ gcc/testsuite/gcc.dg/tree-ssa/pr78154-2.c 2024-11-14 18:08:07.352017948 +0100 @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp-slim -fdelete-null-pointer-checks" } */ +/* { dg-skip-if "" { keeps_null_pointer_checks } } */ + +void foo (void *, __SIZE_TYPE__) __attribute__((nonnull_if_nonzero (1, 2))); +void baz (void); + +void +bar (void *a, void *b, void *c, void *d, void *e, __SIZE_TYPE__ n) +{ + foo (a, 42); + if (a == 0) + __builtin_abort (); + if (n) + { + foo (b, n); + if (b == 0) + __builtin_abort (); + } + if (n >= 42) + { + foo (c, n - 10); + if (c == 0) + __builtin_abort (); + } + foo (d, 0); + if (d == 0) + baz (); + if (n != 42) + { + foo (e, n); + if (e == 0) + baz (); + } +} + +/* { dg-final { scan-tree-dump-not "__builtin_abort" "evrp" } } */ +/* { dg-final { scan-tree-dump-times "baz \\\(" 2 "evrp" } } */ Jakub