This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Hello,
for many builtins, we currently create too pessimistic sets of virtual operands. For example, given the code
int a[1000], b[1000], c;
int test(void) { int x;
c = 0; memset (&x, 0, sizeof (x); memcpy (a, b, sizeof (a)); return c + x; }
we will consider a, b, c all modified by memcpy and memset. Furthermore, we will consider address of x to be escaping to a call, and thus we will consider it call clobbered (and modified by memcpy as well).
In addition to possibly pessimizing the code, this may also complicate optimizers; for example builtinizer may replace
for (i) a[i] = b[i];
by
memcpy (&a, &b, ...)
Now a and b become escaping to a call, so we need to rescan virtual operands of all calls in the functions to add the references to a and b. This is annoying (and also may prevent further optimizations).
To overcome these problems, the patch below enables us to specify a "signature" for a builtin, that describes how it accesses memory. For example, memcpy has signature "n(wr)", meaning that it does not access any memory except through its operands ("n"), the memory pointed to by the first operand is written and the memory pointed to by the second operand is only read.
This patch generalizes (and replaces) the current attribute novops (novops functions now have signature "n()", instead, meaning that they do not read or write any memory).
With this information, we know that in the example above, x is only modified by the memset, a by memcpy and c not at all.
The patch is bootstrapped & regtested on ia64. However, there is one regression -- gcc.c-torture/execute/20060930-2.c (testcase for PR 29272). The problematic code looks basically this way:
struct s {struct s *x} *a, tmps; struct t {struct t *y} *b, tmpt;
a->x = &tmps; tmpt.y = &tmpt; b = (struct t *) (void *) a;
memcpy (b, &tmpt, sizeof (struct s)); assert (a->x != &tmps);
With strict aliasing, we see that the accesses through a and b cannot alias, thus concluding that the memcpy cannot affect the value of a->x. However, this restriction does not seem to hold for memcpy. I am not quite sure how to fix this.
Without looking at the patch in detail there is two things. The memcpy problem may be related to the problems we had with placement new, though unfortunately with different semantics. You have to assume that a pointer passed to a function is written to through a different effective type as the pointed-to-type of the argument.
Another thing is that the novops attribute was exposed to users, so I believe we should not take it away without the usual deprecation period of one release. Can you simply map it back to a signature?
The setting of a signature is not exposed to the user right now? Would it be possible to do that to be able to annotate more library functions? I originally had thought about __attribute__((noescape(n,m,...))) and __attribute__((noclobber(n,m,...))) and storing a bitmap for both properties somewhere.
Thanks, Richard.
Zdenek
* tree.h (DEF_BUILTIN): Add SIG argument. (DECL_IS_NOVOPS): Removed. (DECL_SIGNATURE): New. (struct function_signature): New type. (struct tree_function_decl): Remove novops_flag, add sig field. (ECF_NOVOPS): Removed. * builtins.c (DEF_BUILTIN): Add SIG argument. * builtin-attrs.def: Remove NOVOPS attribute and corresponding attribute lists. * builtins.def: Replace NOVOPS attribute by signature. Add signatures for string functions. * tree-ssa-alias.c (count_derefs_in_call): New function. (count_uses_and_derefs): Use count_derefs_in_call. (is_escape_site): Functions with signature are not escape sites. * c-decl.c (merge_decls): Do not copy DECL_IS_NOVOPS. Copy DECL_SIGNATURE. * calls.c (flags_from_decl_or_type): Do not handle DECL_IS_NOVOPS. * tree-ssa-loop-prefetch.c (tree_ssa_prefetch_arrays): Set signature for builtin_prefetch instead of DECL_IS_NOVOPS. * tree-vect-transform.c (novops_signature_p): New function. (vectorizable_function): Use novops_signature_p instead of testing for ECF_NOVOPS. * c-common.c (handle_novops_attribute): Removed. (c_common_attributes): Remove NOVOPS attribute. (def_builtin_1): Set DECL_SIGNATURE for the created decls. (DEF_BUILTIN): Pass signature to def_builtin_1. (parse_builtin_signature): New function. * tree-ssa-operands.c (get_ptr_operands): Split from ... (get_indirect_ref_operands): ... here. (find_errno_decl, add_call_signature_operands): New functions. (get_call_expr_operands): Call add_call_signature_operands for functions with signature.
* gcc.dg/tree-prof/stringop-1.c: Update outcome.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |