* [PATCH][RFC] Simple IPA mod-ref analysis
@ 2011-10-24 14:10 Richard Guenther
0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2011-10-24 14:10 UTC (permalink / raw)
To: gcc-patches; +Cc: Jan Hubicka
This sketches a simple local mod-ref analysis, piggy-backed ontop
of the local IPA pure-const machinery (well, just sharing its
pass really). I am not yet sure how or if it will be possible
to IPA propagate this (other than handling already processed
bodies during local discovery) - we would need to know whether
parameters may reach calls, and in which position - something
that looks more close to IPA CP than IPA pure-const.
Not yet bootstrapped or tested other than on the simple testcase.
Any comments?
Thanks,
Richard.
2011-10-24 Richard Guenther <rguenther@suse.de>
* gimple.c (gimple_call_fnspec): Also look in DECL_ATTRIBUTES.
* ipa-pure-const.c (struct funct_state_d): Add fnspec member.
(varying_state): Adjust.
(analyze_function): Populate fnspec.
(local_pure_const): Set the fnspec attribute.
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig 2011-10-24 15:14:30.000000000 +0200
--- gcc/gimple.c 2011-10-24 15:14:33.000000000 +0200
*************** gimple_call_flags (const_gimple stmt)
*** 1915,1931 ****
static tree
gimple_call_fnspec (const_gimple stmt)
{
! tree type, attr;
type = gimple_call_fntype (stmt);
! if (!type)
! return NULL_TREE;
! attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
! if (!attr)
! return NULL_TREE;
! return TREE_VALUE (TREE_VALUE (attr));
}
/* Detects argument flags for argument number ARG on call STMT. */
--- 1915,1939 ----
static tree
gimple_call_fnspec (const_gimple stmt)
{
! tree type, decl, attr;
type = gimple_call_fntype (stmt);
! if (type)
! {
! attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
! if (attr)
! return TREE_VALUE (TREE_VALUE (attr));
! }
! decl = gimple_call_fndecl (stmt);
! if (decl)
! {
! attr = lookup_attribute ("fn spec", DECL_ATTRIBUTES (decl));
! if (attr)
! return TREE_VALUE (TREE_VALUE (attr));
! }
! return NULL_TREE;
}
/* Detects argument flags for argument number ARG on call STMT. */
*************** is_gimple_constant (const_tree t)
*** 2731,2743 ****
case VECTOR_CST:
return true;
- /* Vector constant constructors are gimple invariant. */
- case CONSTRUCTOR:
- if (TREE_TYPE (t) && TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
- return TREE_CONSTANT (t);
- else
- return false;
-
default:
return false;
}
--- 2739,2744 ----
Index: gcc/ipa-pure-const.c
===================================================================
*** gcc/ipa-pure-const.c.orig 2011-10-24 15:14:30.000000000 +0200
--- gcc/ipa-pure-const.c 2011-10-24 15:47:34.000000000 +0200
*************** struct funct_state_d
*** 94,104 ****
bool looping;
bool can_throw;
};
/* State used when we know nothing about function. */
static struct funct_state_d varying_state
! = { IPA_NEITHER, IPA_NEITHER, true, true, true };
typedef struct funct_state_d * funct_state;
--- 94,106 ----
bool looping;
bool can_throw;
+
+ char fnspec[1 + 4 + 1];
};
/* State used when we know nothing about function. */
static struct funct_state_d varying_state
! = { IPA_NEITHER, IPA_NEITHER, true, true, true, "....." };
typedef struct funct_state_d * funct_state;
*************** end:
*** 819,824 ****
--- 821,941 ----
if (TREE_NOTHROW (decl))
l->can_throw = false;
+ memset (l->fnspec, '.', sizeof (l->fnspec));
+ l->fnspec[5] = '\0';
+
+ /* Check properties of the return value.
+ ??? Ignore EH edges. */
+ if (single_pred_p (EXIT_BLOCK_PTR)
+ && !gsi_end_p (gsi_last_bb (single_pred (EXIT_BLOCK_PTR))))
+ {
+ gimple ret = gsi_stmt (gsi_last_bb (single_pred (EXIT_BLOCK_PTR)));
+ if (gimple_code (ret) == GIMPLE_RETURN)
+ {
+ tree retval = gimple_return_retval (ret);
+ if (retval
+ && TREE_CODE (retval) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (retval)
+ && TREE_CODE (SSA_NAME_VAR (retval)) == PARM_DECL)
+ {
+ tree arg;
+ unsigned n;
+ for (arg = DECL_ARGUMENTS (decl), n = 1;
+ arg && n <= 4 && arg != SSA_NAME_VAR (retval);
+ arg = DECL_CHAIN (arg))
+ ++n;
+ /* Returns a parameter. */
+ if (arg == SSA_NAME_VAR (retval) && n <= 4)
+ l->fnspec[0] = '0' + n;
+ }
+ else if (retval
+ && TREE_CODE (retval) == SSA_NAME)
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (retval);
+ if (is_gimple_call (def_stmt)
+ && (gimple_call_return_flags (def_stmt) & ERF_NOALIAS))
+ l->fnspec[0] = 'm';
+ /* ??? Support ret = PHI <0, malloc ()>, thus returning zero. */
+ }
+ }
+ }
+
+ /* Check properties of arguments. */
+ {
+ tree arg;
+ unsigned n;
+ for (arg = DECL_ARGUMENTS (decl), n = 1; arg && n <= 4;
+ arg = DECL_CHAIN (arg))
+ {
+ tree name = gimple_default_def (cfun, arg);
+ if (!name)
+ ;
+ else if (has_zero_uses (name))
+ l->fnspec[n] = 'x';
+ else if (POINTER_TYPE_P (TREE_TYPE (name)))
+ {
+ gimple use_stmt;
+ imm_use_iterator iter;
+ bool escapes = false;
+ bool seen_store = false;
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
+ {
+ if (gimple_code (use_stmt) == GIMPLE_RETURN)
+ continue;
+ else if (gimple_assign_single_p (use_stmt))
+ {
+ /* Store. */
+ if (TREE_CODE (gimple_assign_lhs (use_stmt)) != SSA_NAME)
+ seen_store = true;
+ /* Not name or an ADDR_EXPR involving name
+ is transfered to the lhs. */
+ if ((TREE_CODE (gimple_assign_rhs1 (use_stmt))
+ != ADDR_EXPR)
+ && gimple_assign_rhs1 (use_stmt) != name)
+ continue;
+ /* Everything else makes name escape. */
+ }
+ else if (is_gimple_call (use_stmt))
+ {
+ tree lhs = gimple_call_lhs (use_stmt);
+ unsigned m;
+ for (m = 0; m < gimple_call_num_args (use_stmt); ++m)
+ {
+ tree carg = gimple_call_arg (use_stmt, m);
+ if (TREE_CODE (carg) == SSA_NAME)
+ {
+ if (gimple_call_arg (use_stmt, m) == name)
+ {
+ if (!(gimple_call_arg_flags (use_stmt, m)
+ & EAF_NOCLOBBER))
+ seen_store = true;
+ if ((gimple_call_arg_flags (use_stmt, m)
+ & EAF_NOESCAPE))
+ continue;
+ goto escape;
+ }
+ }
+ else
+ goto escape;
+ }
+ if (TREE_CODE (lhs) != SSA_NAME)
+ seen_store = true;
+ continue;
+ }
+ /* Everything else makes name escape. */
+
+ escape:
+ escapes = true;
+ BREAK_FROM_IMM_USE_STMT (iter);
+ }
+ if (!escapes)
+ l->fnspec[n] = seen_store ? 'w' : 'r';
+ }
+ ++n;
+ }
+ }
+
pop_cfun ();
current_function_decl = old_decl;
if (dump_file)
*************** end:
*** 831,836 ****
--- 948,954 ----
fprintf (dump_file, "Function is locally const.\n");
if (l->pure_const_state == IPA_PURE)
fprintf (dump_file, "Function is locally pure.\n");
+ fprintf (dump_file, "Function spec is \"%s\".\n", l->fnspec);
}
return l;
}
*************** local_pure_const (void)
*** 1653,1658 ****
--- 1771,1797 ----
lang_hooks.decl_printable_name (current_function_decl,
2));
}
+ {
+ unsigned n;
+ for (n = 0; n < sizeof (l->fnspec) - 1; ++n)
+ if (l->fnspec[n] != '.')
+ break;
+ if (n < sizeof (l->fnspec) - 1)
+ {
+ DECL_ATTRIBUTES (current_function_decl)
+ = tree_cons (get_identifier ("fn spec"),
+ build_tree_list (NULL_TREE,
+ build_string (1 + 4,
+ l->fnspec)),
+ remove_attribute ("fn spec",
+ DECL_ATTRIBUTES
+ (current_function_decl)));
+ if (dump_file)
+ fprintf (dump_file, "Function specification found: %s (%s)\n",
+ lang_hooks.decl_printable_name (current_function_decl, 2),
+ l->fnspec);
+ }
+ }
free (l);
if (changed)
return execute_fixup_cfg ();
Index: gcc/testsuite/gcc.dg/tree-ssa/mod-ref-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/mod-ref-1.c 2011-10-24 15:33:25.000000000 +0200
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do run } */
+ /* { dg-options "-O" } */
+
+ extern void abort (void);
+ extern void link_error (void);
+
+ char c;
+ char * __attribute__((noinline,noclone))
+ foo(int i, char *p)
+ {
+ c = *p;
+ return p;
+ }
+
+ int main ()
+ {
+ char c = 1;
+ char *c2 = foo(0, &c);
+ if (c != 1)
+ link_error ();
+ *c2 = 2;
+ if (c != 2)
+ abort ();
+ return 0;
+ }
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-10-24 13:48 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-24 14:10 [PATCH][RFC] Simple IPA mod-ref analysis Richard Guenther
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).