diff options
author | Jeff Law <law@redhat.com> | 2013-11-05 12:47:44 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2013-11-05 12:47:44 -0700 |
commit | 8fdc414d439bc7148e079d27220e597b3b602a47 (patch) | |
tree | faf2cabbd865647a82ca5248eea0cae3bb79f870 /gcc/gimple.c | |
parent | 50fae5a679990a4bba7dc30de21e6d4132d778fb (diff) | |
download | gcc-8fdc414d439bc7148e079d27220e597b3b602a47.zip gcc-8fdc414d439bc7148e079d27220e597b3b602a47.tar.gz gcc-8fdc414d439bc7148e079d27220e597b3b602a47.tar.bz2 |
Makefile.in (OBJS): Add gimple-ssa-isolate-paths.o
* Makefile.in (OBJS): Add gimple-ssa-isolate-paths.o
* common.opt (-fisolate-erroneous-paths): Add option and
documentation.
* gimple-ssa-isolate-paths.c: New file.
* gimple.c (check_loadstore): New function.
(infer_nonnull_range): Moved into gimple.c from tree-vrp.c
Verify OP is in the argument list and the argument corresponding
to OP is a pointer type. Use operand_equal_p rather than
pointer equality when testing if OP is on the nonnull list.
Use check_loadstore rather than count_ptr_derefs. Handle
GIMPLE_RETURN statements.
* tree-vrp.c (infer_nonnull_range): Remove.
* gimple.h (infer_nonnull_range): Declare.
* opts.c (default_options_table): Add
* OPT_fisolate_erroneous_paths.
* passes.def: Add pass_isolate_erroneous_paths.
* timevar.def (TV_ISOLATE_ERRONEOUS_PATHS): New timevar.
* tree-pass.h (make_pass_isolate_erroneous_paths): Declare.
* tree-ssa.c (struct count_ptr_d): Remove.
(count_ptr_derefs, count_uses_and_derefs): Remove.
* tree-ssa.h (count_uses_and_derefs): Remove.
* gcc.dg/pr38984.c: Add -fno-isolate-erroneous-paths.
* gcc.dg/tree-ssa/isolate-1.c: New test.
* gcc.dg/tree-ssa/isolate-2.c: New test.
* gcc.dg/tree-ssa/isolate-3.c: New test.
* gcc.dg/tree-ssa/isolate-4.c: New test.
From-SVN: r204414
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r-- | gcc/gimple.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index 4839f3e..55dd091 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3347,3 +3347,84 @@ nonfreeing_call_p (gimple call) return false; } + +/* Callback for walk_stmt_load_store_ops. + + Return TRUE if OP will dereference the tree stored in DATA, FALSE + otherwise. + + This routine only makes a superficial check for a dereference. Thus + it must only be used if it is safe to return a false negative. */ +static bool +check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data) +{ + if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF) + && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0)) + return true; + return false; +} + +/* If OP can be inferred to be non-zero after STMT executes, return true. */ + +bool +infer_nonnull_range (gimple stmt, tree op) +{ + /* We can only assume that a pointer dereference will yield + non-NULL if -fdelete-null-pointer-checks is enabled. */ + if (!flag_delete_null_pointer_checks + || !POINTER_TYPE_P (TREE_TYPE (op)) + || gimple_code (stmt) == GIMPLE_ASM) + return false; + + if (walk_stmt_load_store_ops (stmt, (void *)op, + check_loadstore, check_loadstore)) + return true; + + if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt)) + { + tree fntype = gimple_call_fntype (stmt); + tree attrs = TYPE_ATTRIBUTES (fntype); + for (; attrs; attrs = TREE_CHAIN (attrs)) + { + attrs = lookup_attribute ("nonnull", attrs); + + /* If "nonnull" wasn't specified, we know nothing about + the argument. */ + if (attrs == NULL_TREE) + return false; + + /* If "nonnull" applies to all the arguments, then ARG + is non-null if it's in the argument list. */ + if (TREE_VALUE (attrs) == NULL_TREE) + { + for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++) + { + if (operand_equal_p (op, gimple_call_arg (stmt, i), 0) + && POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i)))) + return true; + } + return false; + } + + /* Now see if op appears in the nonnull list. */ + for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t)) + { + int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1; + tree arg = gimple_call_arg (stmt, idx); + if (operand_equal_p (op, arg, 0)) + return true; + } + } + } + + /* If this function is marked as returning non-null, then we can + infer OP is non-null if it is used in the return statement. */ + if (gimple_code (stmt) == GIMPLE_RETURN + && gimple_return_retval (stmt) + && operand_equal_p (gimple_return_retval (stmt), op, 0) + && lookup_attribute ("returns_nonnull", + TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)))) + return true; + + return false; +} |