diff options
author | Martin Sebor <msebor@redhat.com> | 2021-09-01 13:46:19 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-09-01 13:46:19 -0600 |
commit | ece28da924ddda8b379c94c9df7cd01168f75fbb (patch) | |
tree | 439ad27f308cff8d6f4133e4cabf184815d73675 /gcc/pointer-query.cc | |
parent | ac6e77aacfb6581f5e84e4430628152b9b98da2e (diff) | |
download | gcc-ece28da924ddda8b379c94c9df7cd01168f75fbb.zip gcc-ece28da924ddda8b379c94c9df7cd01168f75fbb.tar.gz gcc-ece28da924ddda8b379c94c9df7cd01168f75fbb.tar.bz2 |
Enable ranger and caching in pass_waccess.
gcc/ChangeLog:
* gimple-ssa-warn-access.cc (get_size_range): Add argument.
(check_access): Pass additional argument.
(check_memop_access): Remove template and make a member function.
(maybe_check_dealloc_call): Make a pass_waccess member function.
(class pass_waccess): Add, rename, and remove members.
(pass_waccess::pass_waccess): Adjust to name change.
(pass_waccess::~pass_waccess): Same.
(check_alloca): Make a member function.
(check_alloc_size_call): Same.
(check_strcat): Same.
(check_strncat): Same.
(check_stxcpy): Same.
(check_stxncpy): Same.
(check_strncmp): Same.
(maybe_warn_rdwr_sizes): Rename...
(pass_waccess::maybe_check_access_sizes): ...to this.
(pass_waccess::check_call): Adjust to name changes.
(pass_waccess::maybe_check_dealloc_call): Make a pass_waccess member
function.
(pass_waccess::execute): Adjust to name changes.
* gimple-ssa-warn-access.h (check_memop_access): Remove.
* pointer-query.cc (access_ref::phi): Handle null pointer.
(access_ref::inform_access): Same.
(pointer_query::put_ref): Modify a cached value, not a copy of it.
(pointer_query::dump): New function.
(compute_objsize_r): Avoid overwriting access_ref::bndrng. Cache
more results.
* pointer-query.h (pointer_query::dump): Declare.
* tree-ssa-strlen.c (get_range): Simplify. Use function query.
(dump_strlen_info): Use function query.
(printf_strlen_execute): Factor code out into pointer_query::put_ref.
gcc/testsuite/ChangeLog:
* gcc.dg/Wstringop-overflow-11.c: Remove xfails.
* gcc.dg/Wstringop-overflow-12.c: Same.
* gcc.dg/Wstringop-overflow-43.c: Add xfails.
* gcc.dg/Wstringop-overflow-73.c: New test.
Diffstat (limited to 'gcc/pointer-query.cc')
-rw-r--r-- | gcc/pointer-query.cc | 127 |
1 files changed, 120 insertions, 7 deletions
diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index ba8f8a9..4ad2879 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -34,10 +34,13 @@ #include "stringpool.h" #include "attribs.h" #include "gimple-fold.h" +#include "gimple-ssa.h" #include "intl.h" #include "attr-fnspec.h" #include "gimple-range.h" #include "pointer-query.h" +#include "tree-pretty-print.h" +#include "tree-ssanames.h" static bool compute_objsize_r (tree, int, access_ref *, ssa_name_limit_t &, pointer_query *); @@ -307,7 +310,7 @@ get_size_range (range_query *query, tree exp, gimple *stmt, tree range[2], enum value_range_kind range_type; if (!query) - query = get_global_range_query (); + query = get_range_query (cfun); if (integral) { @@ -628,7 +631,7 @@ access_ref::phi () const return NULL; gimple *def_stmt = SSA_NAME_DEF_STMT (ref); - if (gimple_code (def_stmt) != GIMPLE_PHI) + if (!def_stmt || gimple_code (def_stmt) != GIMPLE_PHI) return NULL; return as_a <gphi *> (def_stmt); @@ -1038,6 +1041,9 @@ access_ref::inform_access (access_mode mode) const if (TREE_CODE (ref) == SSA_NAME) { gimple *stmt = SSA_NAME_DEF_STMT (ref); + if (!stmt) + return; + if (is_gimple_call (stmt)) { loc = gimple_location (stmt); @@ -1339,7 +1345,7 @@ pointer_query::put_ref (tree ptr, const access_ref &ref, int ostype /* = 1 */) if (var_cache->access_refs.length () <= cache_idx) var_cache->access_refs.safe_grow_cleared (cache_idx + 1); - access_ref cache_ref = var_cache->access_refs[cache_idx - 1]; + access_ref &cache_ref = var_cache->access_refs[cache_idx]; if (cache_ref.ref) { gcc_checking_assert (cache_ref.ref == ref.ref); @@ -1360,6 +1366,102 @@ pointer_query::flush_cache () var_cache->access_refs.release (); } +/* Dump statistics and, optionally, cache contents to DUMP_FILE. */ + +void +pointer_query::dump (FILE *dump_file, bool contents /* = false */) +{ + unsigned nused = 0, nrefs = 0; + unsigned nidxs = var_cache->indices.length (); + for (unsigned i = 0; i != nidxs; ++i) + { + unsigned ari = var_cache->indices[i]; + if (!ari) + continue; + + ++nused; + + const access_ref &aref = var_cache->access_refs[ari]; + if (!aref.ref) + continue; + + ++nrefs; + } + + fprintf (dump_file, "pointer_query counters:\n" + " index cache size: %u\n" + " index entries: %u\n" + " access cache size: %u\n" + " access entries: %u\n" + " hits: %u\n" + " misses: %u\n" + " failures: %u\n" + " max_depth: %u\n", + nidxs, nused, + var_cache->access_refs.length (), nrefs, + hits, misses, failures, max_depth); + + if (!contents || !nidxs) + return; + + fputs ("\npointer_query cache contents:\n", dump_file); + + for (unsigned i = 0; i != nidxs; ++i) + { + unsigned ari = var_cache->indices[i]; + if (!ari) + continue; + + const access_ref &aref = var_cache->access_refs[ari]; + if (!aref.ref) + continue; + + /* The level-1 cache index corresponds to the SSA_NAME_VERSION + shifted left by one and ORed with the Object Size Type in + the lowest bit. Print the two separately. */ + unsigned ver = i >> 1; + unsigned ost = i & 1; + + fprintf (dump_file, " %u.%u[%u]: ", ver, ost, ari); + if (tree name = ssa_name (ver)) + { + print_generic_expr (dump_file, name); + fputs (" = ", dump_file); + } + else + fprintf (dump_file, " _%u = ", ver); + + if (gphi *phi = aref.phi ()) + { + fputs ("PHI <", dump_file); + unsigned nargs = gimple_phi_num_args (phi); + for (unsigned i = 0; i != nargs; ++i) + { + tree arg = gimple_phi_arg_def (phi, i); + print_generic_expr (dump_file, arg); + if (i + 1 < nargs) + fputs (", ", dump_file); + } + fputc ('>', dump_file); + } + else + print_generic_expr (dump_file, aref.ref); + + if (aref.offrng[0] != aref.offrng[1]) + fprintf (dump_file, " + [%lli, %lli]", + (long long) aref.offrng[0].to_shwi (), + (long long) aref.offrng[1].to_shwi ()); + else if (aref.offrng[0] != 0) + fprintf (dump_file, " %c %lli", + aref.offrng[0] < 0 ? '-' : '+', + (long long) aref.offrng[0].to_shwi ()); + + fputc ('\n', dump_file); + } + + fputc ('\n', dump_file); +} + /* A helper of compute_objsize_r() to determine the size from an assignment statement STMT with the RHS of either MIN_EXPR or MAX_EXPR. */ @@ -1782,8 +1884,14 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref, if (const access_ref *cache_ref = qry->get_ref (ptr)) { /* If the pointer is in the cache set *PREF to what it refers - to and return success. */ + to and return success. + FIXME: BNDRNG is determined by each access and so it doesn't + belong in access_ref. Until the design is changed, keep it + unchanged here. */ + const offset_int bndrng[2] = { pref->bndrng[0], pref->bndrng[1] }; *pref = *cache_ref; + pref->bndrng[0] = bndrng[0]; + pref->bndrng[1] = bndrng[1]; return true; } } @@ -1928,13 +2036,18 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref, pref->add_offset (orng[0], orng[1]); else pref->add_max_offset (); + qry->put_ref (ptr, *pref); return true; } - if (code == ADDR_EXPR - || code == SSA_NAME) - return compute_objsize_r (rhs, ostype, pref, snlim, qry); + if (code == ADDR_EXPR || code == SSA_NAME) + { + if (!compute_objsize_r (rhs, ostype, pref, snlim, qry)) + return false; + qry->put_ref (ptr, *pref); + return true; + } /* (This could also be an assignment from a nonlocal pointer.) Save PTR to mention in diagnostics but otherwise treat it as a pointer |