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;