Richard Guenther wrote:
>> I fully concede that my trick isn't a general solution to making full
>> use of restrict. But, given that I think it'll take about 20-50 lines
>> of code, and that it will get a lot of the common cases, I think it's
>> worth it. Do you agree?
>
> Yes, I agree. I just was curious on the status of Dannys work and if it
> would obsolete what you propose.
OK, great. Here's a draft patch for the trick; this works on the test
case I had, and I'll be testing it now. If it passes testing, and I add
testcases, does this look OK to you?
Thanks,
--
Mark Mitchell
CodeSourcery
[EMAIL PROTECTED]
(650) 331-3385 x713
2007-09-01 Mark Mitchell <[EMAIL PROTECTED]>
* function.h (struct function): Add argument_noalias.
* alias.h (argument_noalias): Declare it.
* alias.c (argument_noalias): New function.
(base_alias_check): Use it.
* tree-ssa-structalias.c (intra_create_variable_infos): Use
argument_noalias.
Index: function.h
===================================================================
--- function.h (revision 127950)
+++ function.h (working copy)
@@ -473,6 +473,12 @@ struct function GTY(())
function has been gimplified, so we can make sure we're not
creating non GIMPLE tuples after gimplification. */
unsigned gimplified : 1;
+
+ /* 0 if we have not yet determined whether arguments to this
+ function might alias each other. 1 if we have determined they
+ may alias each other. 2 if we have determined they cannot alias
+ each other. */
+ unsigned argument_noalias : 2;
};
/* If va_list_[gf]pr_size is set to this, it means we don't know how
Index: alias.c
===================================================================
--- alias.c (revision 127950)
+++ alias.c (working copy)
@@ -1452,6 +1452,56 @@ find_base_term (rtx x)
}
}
+/* Returns an integer indicating to what extent arguments to the
+ current function may alias one-another or global variables. In
+ particular, the return value is:
+
+ 0 if pointer arguments may alias each other.
+ 1 if pointer arguments may not alias each other but may alias
+ global variables.
+ 2 if pointer arguments may not alias each other and may not
+ alias global variables.
+ 3 if pointer arguments may not alias anything.
+
+ Unlike FLAG_ARGUMENT_NOALIAS, the value returned may differ
+ depending on the function presently being processed. */
+
+int
+argument_noalias (void)
+{
+ tree t;
+
+ /* If FLAG_ARGUMENT_NOALIAS tells us that arguments cannot alias, we
+ do not have to try to prove that ourselves. And, if we're
+ outside of a function, there's nothing we can prove. */
+ if (flag_argument_noalias || !cfun)
+ return flag_argument_noalias;
+
+ /* If we have not already determined whether this function's
+ arguments can alias each other, figure that out now. */
+ if (!cfun->argument_noalias)
+ {
+ /* If all the arguments to the current function are pointers with
+ the "restrict" qualifier, then none of them can point to one
+ another. Assume that's the case. */
+ cfun->argument_noalias = 2;
+ for (t = DECL_ARGUMENTS (current_function_decl); t; t = TREE_CHAIN (t))
+ {
+ tree type = TREE_TYPE (t);
+ /* If we find a pointer argument that does not have the
+ "restrict" qualifier, then some of the arguments to this
+ function might alias other arguments. */
+ if (POINTER_TYPE_P (type) && !TYPE_RESTRICT (type))
+ {
+ cfun->argument_noalias = 1;
+ break;
+ }
+ }
+ }
+
+ return cfun->argument_noalias - 1;
+}
+
/* Return 0 if the addresses X and Y are known to point to different
objects, 1 if they might be pointers to the same object. */
@@ -1461,6 +1511,7 @@ base_alias_check (rtx x, rtx y, enum mac
{
rtx x_base = find_base_term (x);
rtx y_base = find_base_term (y);
+ int noalias;
/* If the address itself has no known base see if a known equivalent
value has one. If either address still has no known base, nothing
@@ -1521,10 +1572,11 @@ base_alias_check (rtx x, rtx y, enum mac
|| (GET_CODE (y_base) == ADDRESS && GET_MODE (y_base) == Pmode))
return 0;
- if (! flag_argument_noalias)
+ noalias = argument_noalias ();
+ if (! noalias)
return 1;
- if (flag_argument_noalias > 1)
+ if (noalias > 1)
return 0;
/* Weak noalias assertion (arguments are distinct, but may match globals).
*/
Index: alias.h
===================================================================
--- alias.h (revision 127950)
+++ alias.h (working copy)
@@ -28,6 +28,7 @@ extern alias_set_type get_varargs_alias_
extern alias_set_type get_frame_alias_set (void);
extern bool component_uses_parent_alias_set (const_tree);
extern bool alias_set_subset_of (alias_set_type, alias_set_type);
+extern int argument_noalias (void);
/* This alias set can be used to force a memory to conflict with all
other memories, creating a barrier across which no memory reference
Index: tree-ssa-structalias.c
===================================================================
--- tree-ssa-structalias.c (revision 127950)
+++ tree-ssa-structalias.c (working copy)
@@ -4544,7 +4544,12 @@ intra_create_variable_infos (void)
{
tree t;
struct constraint_expr lhs, rhs;
+ bool noalias;
+ noalias = argument_noalias ();
+
+ /* For each incoming pointer argument arg, ARG = ESCAPED_VARS or a
+ dummy variable if flag_argument_noalias > 2. */
/* For each incoming pointer argument arg, create the constraint ARG
= ANYTHING or a dummy variable if flag_argument_noalias is set. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = TREE_CHAIN (t))
@@ -4554,11 +4559,10 @@ intra_create_variable_infos (void)
if (!could_have_pointers (t))
continue;
- /* If flag_argument_noalias is set, then function pointer
- arguments are guaranteed not to point to each other. In that
- case, create an artificial variable PARM_NOALIAS and the
- constraint ARG = &PARM_NOALIAS. */
- if (POINTER_TYPE_P (TREE_TYPE (t)) && flag_argument_noalias > 0)
+ /* If the arguments are guaranteed not to point to each other,
+ create an artificial variable PARM_NOALIAS and the constraint
+ ARG = &PARM_NOALIAS. */
+ if (POINTER_TYPE_P (TREE_TYPE (t)) && noalias)
{
varinfo_t vi;
tree heapvar = heapvar_lookup (t);
@@ -4579,7 +4583,7 @@ intra_create_variable_infos (void)
heapvar_insert (t, heapvar);
ann = get_var_ann (heapvar);
- if (flag_argument_noalias == 1)
+ if (flag_argument_noalias <= 1)
ann->noalias_state = NO_ALIAS;
else if (flag_argument_noalias == 2)
ann->noalias_state = NO_ALIAS_GLOBAL;