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]

Re: [PATCH] Some cleanups after the PTA patches


Any cleanups and splitting you want to do of the constraint finding
part are preapproved as long as they pass bootstrap.
If you want to start what constraints it actually generates though,
please send them along because it is tricky to get right (as i'm sure
you've noticed by now :P)

On Sun, Jun 29, 2008 at 11:34 AM, Richard Guenther <rguenther@suse.de> wrote:
>
> This is some pending source re-org I had laying around.  The
> from_call argument of process_constraint_1 is unused.  We can
> also separate tree-ssa-alias.c from tree-ssa-structalias.c some
> more (the extra walk over the IL in tree-ssa-alias.c will be
> used to implement the alias warnings of tree-ssa-aliaswarnings.c)
>
> I also noticed that for globals we create still constraints from
> anything where we only need from escaped.  Fixed.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
>
> Richard.
>
> 2008-06-29  Richard Guenther  <rguenther@suse.de>
>
>        * tree-ssa-structalias.h (compute_points_to_sets): Adjust
>        prototype.
>        (struct alias_info): Move ...
>        * tree-ssa-alias.c: ... here.
>        (update_alias_info): Declare.
>        (compute_may_aliases): Call it.
>        (update_alias_info): New function.
>        * tree-ssa-structalias.c (update_alias_info): Move ...
>        * tree-ssa-alias.c (update_alias_info_1): ... here.
>        * tree-ssa-structalias.c (process_constraint_1): Remove
>        unused from_call argument.  Rename to ...
>        (process_constraint): ... this.  Delete old wrapper.
>        (make_constraint_to): Adjust callers.
>        (handle_const_call): Likewise.
>        (handle_pure_call): Likewise.
>        (init_base_vars): Likewise.
>        (handle_lhs_call): Likewise.  Remove unnecessary constraint.
>        (find_func_aliases): We don't need structure copies for
>        complex types.
>        (make_constraint_from_anything): Remove.
>        (create_variable_info_for): For globals make constraints
>        from escaped, not from anything.
>        (compute_points_to_sets): Do not call update_alias_info.
>        (ipa_pta_execute): Use make_constraint_from.
>
> Index: tree-ssa-alias.c
> ===================================================================
> *** tree-ssa-alias.c    (revision 137251)
> --- tree-ssa-alias.c    (working copy)
> *************** along with GCC; see the file COPYING3. *** 166,171 ****
> --- 166,205 ----
>     Lastly, we delete partitions with no symbols, and clean up after
>     ourselves.  */
>
> + + /* Alias information used by compute_may_aliases and its helpers.  */
> + struct alias_info
> + {
> +   /* SSA names visited while collecting points-to information.  If bit I
> +      is set, it means that SSA variable with version I has already been
> +      visited.  */
> +   sbitmap ssa_names_visited;
> + +   /* Array of SSA_NAME pointers processed by the points-to collector.
>  */
> +   VEC(tree,heap) *processed_ptrs;
> + +   /* ADDRESSABLE_VARS contains all the global variables and locals that
> +      have had their address taken.  */
> +   struct alias_map_d **addressable_vars;
> +   size_t num_addressable_vars;
> + +   /* POINTERS contains all the _DECL pointers with unique memory tags
> +      that have been referenced in the program.  */
> +   struct alias_map_d **pointers;
> +   size_t num_pointers;
> + +   /* Variables that have been written to directly (i.e., not through a
> +      pointer dereference).  */
> +   struct pointer_set_t *written_vars;
> + +   /* Pointers that have been used in an indirect store operation.  */
> +   struct pointer_set_t *dereferenced_ptrs_store;
> + +   /* Pointers that have been used in an indirect load operation.  */
> +   struct pointer_set_t *dereferenced_ptrs_load;
> + };
> + +
>  /* Structure to map a variable to its alias set.  */
>  struct alias_map_d
>  {
> *************** static struct alias_info *init_alias_inf
> *** 205,210 ****
> --- 239,245 ----
>  static void delete_alias_info (struct alias_info *);
>  static void compute_flow_sensitive_aliasing (struct alias_info *);
>  static void setup_pointers_and_addressables (struct alias_info *);
> + static void update_alias_info (struct alias_info *);
>  static void create_global_var (void);
>  static void maybe_create_global_var (void);
>  static void set_pt_anything (tree);
> *************** compute_may_aliases (void)
> *** 1722,1728 ****
>       address of V escapes the current function, making V call-clobbered
>       (i.e., whether &V is stored in a global variable or if its passed as a
>       function call argument).  */
> !   compute_points_to_sets (ai);
>
>    /* Collect all pointers and addressable variables, compute alias sets,
>       create memory tags for pointers and promote variables whose address is
> --- 1757,1768 ----
>       address of V escapes the current function, making V call-clobbered
>       (i.e., whether &V is stored in a global variable or if its passed as a
>       function call argument).  */
> !   compute_points_to_sets ();
> ! !   /* Update various related attributes like escaped addresses,
> !      pointer dereferences for loads and stores.  This is used
> !      when creating name tags and alias sets.  */
> !   update_alias_info (ai);
>
>    /* Collect all pointers and addressable variables, compute alias sets,
>       create memory tags for pointers and promote variables whose address is
> *************** create_alias_map_for (tree var, struct a
> *** 2438,2443 ****
> --- 2478,2747 ----
>  }
>
>
> + /* Update related alias information kept in AI.  This is used when
> +    building name tags, alias sets and deciding grouping heuristics.
> +    STMT is the statement to process.  This function also updates
> +    ADDRESSABLE_VARS.  */
> + + static void
> + update_alias_info_1 (tree stmt, struct alias_info *ai)
> + {
> +   bitmap addr_taken;
> +   use_operand_p use_p;
> +   ssa_op_iter iter;
> +   bool stmt_dereferences_ptr_p;
> +   enum escape_type stmt_escape_type = is_escape_site (stmt);
> +   struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
> + +   stmt_dereferences_ptr_p = false;
> + +   if (stmt_escape_type == ESCAPE_TO_CALL
> +       || stmt_escape_type == ESCAPE_TO_PURE_CONST)
> +     {
> +       mem_ref_stats->num_call_sites++;
> +       if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
> +       mem_ref_stats->num_pure_const_call_sites++;
> +     }
> +   else if (stmt_escape_type == ESCAPE_TO_ASM)
> +     mem_ref_stats->num_asm_sites++;
> + +   /* Mark all the variables whose address are taken by the statement.
>  */
> +   addr_taken = addresses_taken (stmt);
> +   if (addr_taken)
> +     bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
> + +   /* Process each operand use.  For pointers, determine whether they
> +      are dereferenced by the statement, or whether their value
> +      escapes, etc.  */
> +   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
> +     {
> +       tree op, var;
> +       var_ann_t v_ann;
> +       struct ptr_info_def *pi;
> +       unsigned num_uses, num_loads, num_stores;
> + +       op = USE_FROM_PTR (use_p);
> + +       /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
> +        to the set of addressable variables.  */
> +       if (TREE_CODE (op) == ADDR_EXPR)
> +       {
> +         bitmap addressable_vars = gimple_addressable_vars (cfun);
> + +         gcc_assert (TREE_CODE (stmt) == PHI_NODE);
> +         gcc_assert (addressable_vars);
> + +         /* PHI nodes don't have annotations for pinning the set
> +            of addresses taken, so we collect them here.
> + +            FIXME, should we allow PHI nodes to have annotations
> +            so that they can be treated like regular statements?
> +            Currently, they are treated as second-class
> +            statements.  */
> +         add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
> +         continue;
> +       }
> + +       /* Ignore constants (they may occur in PHI node arguments).  */
> +       if (TREE_CODE (op) != SSA_NAME)
> +       continue;
> + +       var = SSA_NAME_VAR (op);
> +       v_ann = var_ann (var);
> + +       /* The base variable of an SSA name must be a GIMPLE register, and
> thus
> +        it cannot be aliased.  */
> +       gcc_assert (!may_be_aliased (var));
> + +       /* We are only interested in pointers.  */
> +       if (!POINTER_TYPE_P (TREE_TYPE (op)))
> +       continue;
> + +       pi = get_ptr_info (op);
> + +       /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
> +       if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
> +       {
> +         SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
> +         VEC_safe_push (tree, heap, ai->processed_ptrs, op);
> +       }
> + +       /* If STMT is a PHI node, then it will not have pointer
> +        dereferences and it will not be an escape point.  */
> +       if (TREE_CODE (stmt) == PHI_NODE)
> +       continue;
> + +       /* Determine whether OP is a dereferenced pointer, and if STMT
> +        is an escape point, whether OP escapes.  */
> +       count_uses_and_derefs (op, stmt, &num_uses, &num_loads,
> &num_stores);
> + +       /* For directly dereferenced pointers we can apply
> +        TBAA-pruning to their points-to set.  We may not count the
> +        implicit dereferences &PTR->FLD here.  */
> +       if (num_loads + num_stores > 0)
> +       pi->is_dereferenced = 1;
> + +       /* Handle a corner case involving address expressions of the
> +        form '&PTR->FLD'.  The problem with these expressions is that
> +        they do not represent a dereference of PTR.  However, if some
> +        other transformation propagates them into an INDIRECT_REF
> +        expression, we end up with '*(&PTR->FLD)' which is folded
> +        into 'PTR->FLD'.
> + +        So, if the original code had no other dereferences of PTR,
> +        the aliaser will not create memory tags for it, and when
> +        &PTR->FLD gets propagated to INDIRECT_REF expressions, the
> +        memory operations will receive no VDEF/VUSE operands.
> + +        One solution would be to have count_uses_and_derefs consider
> +        &PTR->FLD a dereference of PTR.  But that is wrong, since it
> +        is not really a dereference but an offset calculation.
> + +        What we do here is to recognize these special ADDR_EXPR
> +        nodes.  Since these expressions are never GIMPLE values (they
> +        are not GIMPLE invariants), they can only appear on the RHS
> +        of an assignment and their base address is always an
> +        INDIRECT_REF expression.  */
> +       if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
> +         && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR
> +         && !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1)))
> +       {
> +         /* If the RHS if of the form &PTR->FLD and PTR == OP, then
> +            this represents a potential dereference of PTR.  */
> +         tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
> +         tree base = get_base_address (TREE_OPERAND (rhs, 0));
> +         if (TREE_CODE (base) == INDIRECT_REF
> +             && TREE_OPERAND (base, 0) == op)
> +           num_loads++;
> +       }
> + +       if (num_loads + num_stores > 0)
> +       {
> +         /* Mark OP as dereferenced.  In a subsequent pass,
> +            dereferenced pointers that point to a set of
> +            variables will be assigned a name tag to alias
> +            all the variables OP points to.  */
> +         pi->memory_tag_needed = 1;
> + +         /* ???  For always executed direct dereferences we can
> +            apply TBAA-pruning to their escape set.  */
> + +         /* If this is a store operation, mark OP as being
> +            dereferenced to store, otherwise mark it as being
> +            dereferenced to load.  */
> +         if (num_stores > 0)
> +           pointer_set_insert (ai->dereferenced_ptrs_store, var);
> +         else
> +           pointer_set_insert (ai->dereferenced_ptrs_load, var);
> + +         /* Update the frequency estimate for all the dereferences of
> +            pointer OP.  */
> +         update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores);
> + +         /* Indicate that STMT contains pointer dereferences.  */
> +         stmt_dereferences_ptr_p = true;
> +       }
> + +       if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores <
> num_uses)
> +       {
> +         /* If STMT is an escape point and STMT contains at
> +            least one direct use of OP, then the value of OP
> +            escapes and so the pointed-to variables need to
> +            be marked call-clobbered.  */
> +         pi->value_escapes_p = 1;
> +         pi->escape_mask |= stmt_escape_type;
> + +         /* If the statement makes a function call, assume
> +            that pointer OP will be dereferenced in a store
> +            operation inside the called function.  */
> +         if (get_call_expr_in (stmt)
> +             || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
> +           {
> +             pointer_set_insert (ai->dereferenced_ptrs_store, var);
> +             pi->memory_tag_needed = 1;
> +           }
> +       }
> +     }
> + +   if (TREE_CODE (stmt) == PHI_NODE)
> +     return;
> + +   /* Mark stored variables in STMT as being written to and update the
> +      memory reference stats for all memory symbols referenced by STMT.  */
> +   if (stmt_references_memory_p (stmt))
> +     {
> +       unsigned i;
> +       bitmap_iterator bi;
> + +       mem_ref_stats->num_mem_stmts++;
> + +       /* Notice that we only update memory reference stats for symbols
> +        loaded and stored by the statement if the statement does not
> +        contain pointer dereferences and it is not a call/asm site.
> +        This is to avoid double accounting problems when creating
> +        memory partitions.  After computing points-to information,
> +        pointer dereference statistics are used to update the
> +        reference stats of the pointed-to variables, so here we
> +        should only update direct references to symbols.
> + +        Indirect references are not updated here for two reasons: (1)
> +        The first time we compute alias information, the sets
> +        LOADED/STORED are empty for pointer dereferences, (2) After
> +        partitioning, LOADED/STORED may have references to
> +        partitions, not the original pointed-to variables.  So, if we
> +        always counted LOADED/STORED here and during partitioning, we
> +        would count many symbols more than once.
> + +        This does cause some imprecision when a statement has a
> +        combination of direct symbol references and pointer
> +        dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
> +        memory symbols in its argument list, but these cases do not
> +        occur so frequently as to constitute a serious problem.  */
> +       if (STORED_SYMS (stmt))
> +       EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
> +         {
> +           tree sym = referenced_var (i);
> +           pointer_set_insert (ai->written_vars, sym);
> +           if (!stmt_dereferences_ptr_p
> +               && stmt_escape_type != ESCAPE_TO_CALL
> +               && stmt_escape_type != ESCAPE_TO_PURE_CONST
> +               && stmt_escape_type != ESCAPE_TO_ASM)
> +             update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
> +         }
> + +       if (!stmt_dereferences_ptr_p
> +         && LOADED_SYMS (stmt)
> +         && stmt_escape_type != ESCAPE_TO_CALL
> +         && stmt_escape_type != ESCAPE_TO_PURE_CONST
> +         && stmt_escape_type != ESCAPE_TO_ASM)
> +       EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
> +         update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
> +     }
> + }
> + + /* Update various related attributes like escaped addresses,
> +    pointer dereferences for loads and stores.  This is used
> +    when creating name tags and alias sets.  */
> + + static void
> + update_alias_info (struct alias_info *ai)
> + {
> +   basic_block bb;
> + +   FOR_EACH_BB (bb)
> +     {
> +       block_stmt_iterator bsi;
> +       tree phi;
> + +       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
> +       if (is_gimple_reg (PHI_RESULT (phi)))
> +         update_alias_info_1 (phi, ai);
> + +       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
> +       update_alias_info_1 (bsi_stmt (bsi), ai);
> +     }
> + }
> +
>  /* Create memory tags for all the dereferenced pointers and build the
>     ADDRESSABLE_VARS and POINTERS arrays used for building the may-alias
>     sets.  Based on the address escape and points-to information collected
> Index: tree-ssa-structalias.c
> ===================================================================
> *** tree-ssa-structalias.c      (revision 137251)
> --- tree-ssa-structalias.c      (working copy)
> *************** get_constraint_exp_from_ssa_var (tree t)
> *** 2526,2538 ****
>    return cexpr;
>  }
>
> ! /* Process a completed constraint T, and add it to the constraint
> !    list.  FROM_CALL is true if this is a constraint coming from a
> !    call, which means any DEREFs we see are "may-deref's", not
> !    "must-deref"'s.  */
>
>  static void
> ! process_constraint_1 (constraint_t t, bool from_call)
>  {
>    struct constraint_expr rhs = t->rhs;
>    struct constraint_expr lhs = t->lhs;
> --- 2526,2536 ----
>    return cexpr;
>  }
>
> ! /* Process constraint T, performing various simplifications and then
> !    adding it to our list of overall constraints.  */
>
>  static void
> ! process_constraint (constraint_t t)
>  {
>    struct constraint_expr rhs = t->rhs;
>    struct constraint_expr lhs = t->lhs;
> *************** process_constraint_1 (constraint_t t, bo
> *** 2556,2562 ****
>        rhs = t->lhs;
>        t->lhs = t->rhs;
>        t->rhs = rhs;
> !       process_constraint_1 (t, from_call);
>      }
>    /* This can happen in our IR with things like n->a = *p */
>    else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var !=
> anything_id)
> --- 2554,2560 ----
>        rhs = t->lhs;
>        t->lhs = t->rhs;
>        t->rhs = rhs;
> !       process_constraint (t);
>      }
>    /* This can happen in our IR with things like n->a = *p */
>    else if (rhs.type == DEREF && lhs.type == DEREF && rhs.var !=
> anything_id)
> *************** process_constraint_1 (constraint_t t, bo
> *** 2574,2581 ****
>        gcc_assert (!AGGREGATE_TYPE_P (pointedtotype)
>                  || get_varinfo (rhs.var)->is_unknown_size_var);
>
> !       process_constraint_1 (new_constraint (tmplhs, rhs), from_call);
> !       process_constraint_1 (new_constraint (lhs, tmplhs), from_call);
>      }
>    else if (rhs.type == ADDRESSOF && lhs.type == DEREF)
>      {
> --- 2572,2579 ----
>        gcc_assert (!AGGREGATE_TYPE_P (pointedtotype)
>                  || get_varinfo (rhs.var)->is_unknown_size_var);
>
> !       process_constraint (new_constraint (tmplhs, rhs));
> !       process_constraint (new_constraint (lhs, tmplhs));
>      }
>    else if (rhs.type == ADDRESSOF && lhs.type == DEREF)
>      {
> *************** process_constraint_1 (constraint_t t, bo
> *** 2585,2592 ****
>        tree tmpvar = create_tmp_var_raw (pointertype, "derefaddrtmp");
>        struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var
> (tmpvar);
>
> !       process_constraint_1 (new_constraint (tmplhs, rhs), from_call);
> !       process_constraint_1 (new_constraint (lhs, tmplhs), from_call);
>      }
>    else
>      {
> --- 2583,2590 ----
>        tree tmpvar = create_tmp_var_raw (pointertype, "derefaddrtmp");
>        struct constraint_expr tmplhs = get_constraint_exp_from_ssa_var
> (tmpvar);
>
> !       process_constraint (new_constraint (tmplhs, rhs));
> !       process_constraint (new_constraint (lhs, tmplhs));
>      }
>    else
>      {
> *************** process_constraint_1 (constraint_t t, bo
> *** 2595,2610 ****
>      }
>  }
>
> - - /* Process constraint T, performing various simplifications and then
> -    adding it to our list of overall constraints.  */
> - - static void
> - process_constraint (constraint_t t)
> - {
> -   process_constraint_1 (t, false);
> - }
> -
>  /* Return true if T is a variable of a type that could contain
>     pointers.  */
>
> --- 2593,2598 ----
> *************** do_structure_copy (tree lhsop, tree rhso
> *** 3267,3514 ****
>  }
>
>
> - /* Update related alias information kept in AI.  This is used when
> -    building name tags, alias sets and deciding grouping heuristics.
> -    STMT is the statement to process.  This function also updates
> -    ADDRESSABLE_VARS.  */
> - - static void
> - update_alias_info (tree stmt, struct alias_info *ai)
> - {
> -   bitmap addr_taken;
> -   use_operand_p use_p;
> -   ssa_op_iter iter;
> -   bool stmt_dereferences_ptr_p;
> -   enum escape_type stmt_escape_type = is_escape_site (stmt);
> -   struct mem_ref_stats_d *mem_ref_stats = gimple_mem_ref_stats (cfun);
> - -   stmt_dereferences_ptr_p = false;
> - -   if (stmt_escape_type == ESCAPE_TO_CALL
> -       || stmt_escape_type == ESCAPE_TO_PURE_CONST)
> -     {
> -       mem_ref_stats->num_call_sites++;
> -       if (stmt_escape_type == ESCAPE_TO_PURE_CONST)
> -       mem_ref_stats->num_pure_const_call_sites++;
> -     }
> -   else if (stmt_escape_type == ESCAPE_TO_ASM)
> -     mem_ref_stats->num_asm_sites++;
> - -   /* Mark all the variables whose address are taken by the statement.
>  */
> -   addr_taken = addresses_taken (stmt);
> -   if (addr_taken)
> -     bitmap_ior_into (gimple_addressable_vars (cfun), addr_taken);
> - -   /* Process each operand use.  For pointers, determine whether they
> -      are dereferenced by the statement, or whether their value
> -      escapes, etc.  */
> -   FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
> -     {
> -       tree op, var;
> -       var_ann_t v_ann;
> -       struct ptr_info_def *pi;
> -       unsigned num_uses, num_loads, num_stores;
> - -       op = USE_FROM_PTR (use_p);
> - -       /* If STMT is a PHI node, OP may be an ADDR_EXPR.  If so, add it
> -        to the set of addressable variables.  */
> -       if (TREE_CODE (op) == ADDR_EXPR)
> -       {
> -         bitmap addressable_vars = gimple_addressable_vars (cfun);
> - -         gcc_assert (TREE_CODE (stmt) == PHI_NODE);
> -         gcc_assert (addressable_vars);
> - -         /* PHI nodes don't have annotations for pinning the set
> -            of addresses taken, so we collect them here.
> - -            FIXME, should we allow PHI nodes to have annotations
> -            so that they can be treated like regular statements?
> -            Currently, they are treated as second-class
> -            statements.  */
> -         add_to_addressable_set (TREE_OPERAND (op, 0), &addressable_vars);
> -         continue;
> -       }
> - -       /* Ignore constants (they may occur in PHI node arguments).  */
> -       if (TREE_CODE (op) != SSA_NAME)
> -       continue;
> - -       var = SSA_NAME_VAR (op);
> -       v_ann = var_ann (var);
> - -       /* The base variable of an SSA name must be a GIMPLE register, and
> thus
> -        it cannot be aliased.  */
> -       gcc_assert (!may_be_aliased (var));
> - -       /* We are only interested in pointers.  */
> -       if (!POINTER_TYPE_P (TREE_TYPE (op)))
> -       continue;
> - -       pi = get_ptr_info (op);
> - -       /* Add OP to AI->PROCESSED_PTRS, if it's not there already.  */
> -       if (!TEST_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op)))
> -       {
> -         SET_BIT (ai->ssa_names_visited, SSA_NAME_VERSION (op));
> -         VEC_safe_push (tree, heap, ai->processed_ptrs, op);
> -       }
> - -       /* If STMT is a PHI node, then it will not have pointer
> -        dereferences and it will not be an escape point.  */
> -       if (TREE_CODE (stmt) == PHI_NODE)
> -       continue;
> - -       /* Determine whether OP is a dereferenced pointer, and if STMT
> -        is an escape point, whether OP escapes.  */
> -       count_uses_and_derefs (op, stmt, &num_uses, &num_loads,
> &num_stores);
> - -       /* For directly dereferenced pointers we can apply
> -        TBAA-pruning to their points-to set.  We may not count the
> -        implicit dereferences &PTR->FLD here.  */
> -       if (num_loads + num_stores > 0)
> -       pi->is_dereferenced = 1;
> - -       /* Handle a corner case involving address expressions of the
> -        form '&PTR->FLD'.  The problem with these expressions is that
> -        they do not represent a dereference of PTR.  However, if some
> -        other transformation propagates them into an INDIRECT_REF
> -        expression, we end up with '*(&PTR->FLD)' which is folded
> -        into 'PTR->FLD'.
> - -        So, if the original code had no other dereferences of PTR,
> -        the aliaser will not create memory tags for it, and when
> -        &PTR->FLD gets propagated to INDIRECT_REF expressions, the
> -        memory operations will receive no VDEF/VUSE operands.
> - -        One solution would be to have count_uses_and_derefs consider
> -        &PTR->FLD a dereference of PTR.  But that is wrong, since it
> -        is not really a dereference but an offset calculation.
> - -        What we do here is to recognize these special ADDR_EXPR
> -        nodes.  Since these expressions are never GIMPLE values (they
> -        are not GIMPLE invariants), they can only appear on the RHS
> -        of an assignment and their base address is always an
> -        INDIRECT_REF expression.  */
> -       if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
> -         && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == ADDR_EXPR
> -         && !is_gimple_val (GIMPLE_STMT_OPERAND (stmt, 1)))
> -       {
> -         /* If the RHS if of the form &PTR->FLD and PTR == OP, then
> -            this represents a potential dereference of PTR.  */
> -         tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
> -         tree base = get_base_address (TREE_OPERAND (rhs, 0));
> -         if (TREE_CODE (base) == INDIRECT_REF
> -             && TREE_OPERAND (base, 0) == op)
> -           num_loads++;
> -       }
> - -       if (num_loads + num_stores > 0)
> -       {
> -         /* Mark OP as dereferenced.  In a subsequent pass,
> -            dereferenced pointers that point to a set of
> -            variables will be assigned a name tag to alias
> -            all the variables OP points to.  */
> -         pi->memory_tag_needed = 1;
> - -         /* ???  For always executed direct dereferences we can
> -            apply TBAA-pruning to their escape set.  */
> - -         /* If this is a store operation, mark OP as being
> -            dereferenced to store, otherwise mark it as being
> -            dereferenced to load.  */
> -         if (num_stores > 0)
> -           pointer_set_insert (ai->dereferenced_ptrs_store, var);
> -         else
> -           pointer_set_insert (ai->dereferenced_ptrs_load, var);
> - -         /* Update the frequency estimate for all the dereferences of
> -            pointer OP.  */
> -         update_mem_sym_stats_from_stmt (op, stmt, num_loads, num_stores);
> - -         /* Indicate that STMT contains pointer dereferences.  */
> -         stmt_dereferences_ptr_p = true;
> -       }
> - -       if (stmt_escape_type != NO_ESCAPE && num_loads + num_stores <
> num_uses)
> -       {
> -         /* If STMT is an escape point and STMT contains at
> -            least one direct use of OP, then the value of OP
> -            escapes and so the pointed-to variables need to
> -            be marked call-clobbered.  */
> -         pi->value_escapes_p = 1;
> -         pi->escape_mask |= stmt_escape_type;
> - -         /* If the statement makes a function call, assume
> -            that pointer OP will be dereferenced in a store
> -            operation inside the called function.  */
> -         if (get_call_expr_in (stmt)
> -             || stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
> -           {
> -             pointer_set_insert (ai->dereferenced_ptrs_store, var);
> -             pi->memory_tag_needed = 1;
> -           }
> -       }
> -     }
> - -   if (TREE_CODE (stmt) == PHI_NODE)
> -     return;
> - -   /* Mark stored variables in STMT as being written to and update the
> -      memory reference stats for all memory symbols referenced by STMT.  */
> -   if (stmt_references_memory_p (stmt))
> -     {
> -       unsigned i;
> -       bitmap_iterator bi;
> - -       mem_ref_stats->num_mem_stmts++;
> - -       /* Notice that we only update memory reference stats for symbols
> -        loaded and stored by the statement if the statement does not
> -        contain pointer dereferences and it is not a call/asm site.
> -        This is to avoid double accounting problems when creating
> -        memory partitions.  After computing points-to information,
> -        pointer dereference statistics are used to update the
> -        reference stats of the pointed-to variables, so here we
> -        should only update direct references to symbols.
> - -        Indirect references are not updated here for two reasons: (1)
> -        The first time we compute alias information, the sets
> -        LOADED/STORED are empty for pointer dereferences, (2) After
> -        partitioning, LOADED/STORED may have references to
> -        partitions, not the original pointed-to variables.  So, if we
> -        always counted LOADED/STORED here and during partitioning, we
> -        would count many symbols more than once.
> - -        This does cause some imprecision when a statement has a
> -        combination of direct symbol references and pointer
> -        dereferences (e.g., MEMORY_VAR = *PTR) or if a call site has
> -        memory symbols in its argument list, but these cases do not
> -        occur so frequently as to constitute a serious problem.  */
> -       if (STORED_SYMS (stmt))
> -       EXECUTE_IF_SET_IN_BITMAP (STORED_SYMS (stmt), 0, i, bi)
> -         {
> -           tree sym = referenced_var (i);
> -           pointer_set_insert (ai->written_vars, sym);
> -           if (!stmt_dereferences_ptr_p
> -               && stmt_escape_type != ESCAPE_TO_CALL
> -               && stmt_escape_type != ESCAPE_TO_PURE_CONST
> -               && stmt_escape_type != ESCAPE_TO_ASM)
> -             update_mem_sym_stats_from_stmt (sym, stmt, 0, 1);
> -         }
> - -       if (!stmt_dereferences_ptr_p
> -         && LOADED_SYMS (stmt)
> -         && stmt_escape_type != ESCAPE_TO_CALL
> -         && stmt_escape_type != ESCAPE_TO_PURE_CONST
> -         && stmt_escape_type != ESCAPE_TO_ASM)
> -       EXECUTE_IF_SET_IN_BITMAP (LOADED_SYMS (stmt), 0, i, bi)
> -         update_mem_sym_stats_from_stmt (referenced_var (i), stmt, 1, 0);
> -     }
> - }
> - -
>  /* Handle pointer arithmetic EXPR when creating aliasing constraints.
>     Expressions of the type PTR + CST can be handled in two ways:
>
> --- 3255,3260 ----
> *************** make_constraint_to (unsigned id, tree op
> *** 3598,3604 ****
>
>    get_constraint_for (op, &rhsc);
>    for (j = 0; VEC_iterate (ce_s, rhsc, j, c); j++)
> !     process_constraint_1 (new_constraint (includes, *c), true);
>    VEC_free (ce_s, heap, rhsc);
>  }
>
> --- 3344,3350 ----
>
>    get_constraint_for (op, &rhsc);
>    for (j = 0; VEC_iterate (ce_s, rhsc, j, c); j++)
> !     process_constraint (new_constraint (includes, *c));
>    VEC_free (ce_s, heap, rhsc);
>  }
>
> *************** handle_lhs_call (tree lhs)
> *** 3643,3658 ****
>    struct constraint_expr *lhsp;
>
>    get_constraint_for (lhs, &lhsc);
> -   rhsc.var = nonlocal_id;
> -   rhsc.offset = 0;
> -   rhsc.type = ADDRESSOF;
> -   for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> -     process_constraint_1 (new_constraint (*lhsp, rhsc), true);
>    rhsc.var = escaped_id;
>    rhsc.offset = 0;
>    rhsc.type = ADDRESSOF;
>    for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !     process_constraint_1 (new_constraint (*lhsp, rhsc), true);
>    VEC_free (ce_s, heap, lhsc);
>  }
>
> --- 3389,3399 ----
>    struct constraint_expr *lhsp;
>
>    get_constraint_for (lhs, &lhsc);
>    rhsc.var = escaped_id;
>    rhsc.offset = 0;
>    rhsc.type = ADDRESSOF;
>    for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !     process_constraint (new_constraint (*lhsp, rhsc));
>    VEC_free (ce_s, heap, lhsc);
>  }
>
> *************** handle_const_call (tree stmt)
> *** 3680,3686 ****
>        rhsc.offset = 0;
>        rhsc.type = ADDRESSOF;
>        for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !       process_constraint_1 (new_constraint (*lhsp, rhsc), true);
>        VEC_free (ce_s, heap, lhsc);
>        return;
>      }
> --- 3421,3427 ----
>        rhsc.offset = 0;
>        rhsc.type = ADDRESSOF;
>        for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !       process_constraint (new_constraint (*lhsp, rhsc));
>        VEC_free (ce_s, heap, lhsc);
>        return;
>      }
> *************** handle_const_call (tree stmt)
> *** 3690,3696 ****
>    rhsc.offset = 0;
>    rhsc.type = ADDRESSOF;
>    for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !     process_constraint_1 (new_constraint (*lhsp, rhsc), true);
>
>    /* May return arguments.  */
>    FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
> --- 3431,3437 ----
>    rhsc.offset = 0;
>    rhsc.type = ADDRESSOF;
>    for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !     process_constraint (new_constraint (*lhsp, rhsc));
>
>    /* May return arguments.  */
>    FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
> *************** handle_const_call (tree stmt)
> *** 3702,3708 ****
>        get_constraint_for (arg, &argc);
>        for (i = 0; VEC_iterate (ce_s, argc, i, argp); i++)
>          for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !           process_constraint_1 (new_constraint (*lhsp, *argp), true);
>        VEC_free (ce_s, heap, argc);
>        }
>
> --- 3443,3449 ----
>        get_constraint_for (arg, &argc);
>        for (i = 0; VEC_iterate (ce_s, argc, i, argp); i++)
>          for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !           process_constraint (new_constraint (*lhsp, *argp));
>        VEC_free (ce_s, heap, argc);
>        }
>
> *************** handle_pure_call (tree stmt)
> *** 3748,3754 ****
>          rhsc.offset = 0;
>          rhsc.type = ADDRESSOF;
>          for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !           process_constraint_1 (new_constraint (*lhsp, rhsc), true);
>          VEC_free (ce_s, heap, lhsc);
>          return;
>        }
> --- 3489,3495 ----
>          rhsc.offset = 0;
>          rhsc.type = ADDRESSOF;
>          for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !           process_constraint (new_constraint (*lhsp, rhsc));
>          VEC_free (ce_s, heap, lhsc);
>          return;
>        }
> *************** handle_pure_call (tree stmt)
> *** 3759,3765 ****
>        rhsc.offset = 0;
>        rhsc.type = ADDRESSOF;
>        for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !       process_constraint_1 (new_constraint (*lhsp, rhsc), true);
>        VEC_free (ce_s, heap, lhsc);
>      }
>  }
> --- 3500,3506 ----
>        rhsc.offset = 0;
>        rhsc.type = ADDRESSOF;
>        for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); j++)
> !       process_constraint (new_constraint (*lhsp, rhsc));
>        VEC_free (ce_s, heap, lhsc);
>      }
>  }
> *************** find_func_aliases (tree origt)
> *** 3957,3966 ****
>        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
>        int i;
>
> !       if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
> !          || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
> !         && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
> !             || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
>        {
>          do_structure_copy (lhsop, rhsop);
>        }
> --- 3698,3705 ----
>        tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
>        int i;
>
> !       if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
> !         && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
>        {
>          do_structure_copy (lhsop, rhsop);
>        }
> *************** make_constraint_from (varinfo_t vi, int *** 4340,4352 ****
>    process_constraint (new_constraint (lhs, rhs));
>  }
>
> - /* Create a constraint from ANYTHING variable to VI.  */
> - static void
> - make_constraint_from_anything (varinfo_t vi)
> - {
> -   make_constraint_from (vi, anything_id);
> - }
> -
>  /* Count the number of arguments DECL has, and set IS_VARARGS to true
>     if it is a varargs function.  */
>
> --- 4079,4084 ----
> *************** create_variable_info_for (tree decl, con
> *** 4552,4559 ****
>
>    insert_vi_for_tree (vi->decl, vi);
>    VEC_safe_push (varinfo_t, heap, varmap, vi);
> !   if (is_global && (!flag_whole_program || !in_ipa_mode))
> !     make_constraint_from_anything (vi);
>
>    stats.total_vars++;
>    if (use_field_sensitive
> --- 4284,4292 ----
>
>    insert_vi_for_tree (vi->decl, vi);
>    VEC_safe_push (varinfo_t, heap, varmap, vi);
> !   if (is_global && (!flag_whole_program || !in_ipa_mode)
> !       && could_have_pointers (decl))
> !     make_constraint_from (vi, escaped_id);
>
>    stats.total_vars++;
>    if (use_field_sensitive
> *************** create_variable_info_for (tree decl, con
> *** 4633,4640 ****
>          newvi->fullsize = vi->fullsize;
>          insert_into_field_list (vi, newvi);
>          VEC_safe_push (varinfo_t, heap, varmap, newvi);
> !         if (is_global && (!flag_whole_program || !in_ipa_mode))
> !             make_constraint_from_anything (newvi);
>
>          stats.total_vars++;
>        }
> --- 4366,4374 ----
>          newvi->fullsize = vi->fullsize;
>          insert_into_field_list (vi, newvi);
>          VEC_safe_push (varinfo_t, heap, varmap, newvi);
> !         if (is_global && (!flag_whole_program || !in_ipa_mode)
> !             && (!fo->decl || could_have_pointers (fo->decl)))
> !           make_constraint_from (newvi, escaped_id);
>
>          stats.total_vars++;
>        }
> *************** init_base_vars (void)
> *** 5296,5302 ****
>    rhs.type = DEREF;
>    rhs.var = escaped_id;
>    rhs.offset = 0;
> !   process_constraint_1 (new_constraint (lhs, rhs), true);
>
>    /* Create the NONLOCAL variable, used to represent the set of nonlocal
>       memory.  */
> --- 5030,5036 ----
>    rhs.type = DEREF;
>    rhs.var = escaped_id;
>    rhs.offset = 0;
> !   process_constraint (new_constraint (lhs, rhs));
>
>    /* Create the NONLOCAL variable, used to represent the set of nonlocal
>       memory.  */
> *************** init_base_vars (void)
> *** 5339,5345 ****
>    rhs.type = DEREF;
>    rhs.var = callused_id;
>    rhs.offset = 0;
> !   process_constraint_1 (new_constraint (lhs, rhs), true);
>
>    /* Create the INTEGER variable, used to represent that a variable points
>       to an INTEGER.  */
> --- 5073,5079 ----
>    rhs.type = DEREF;
>    rhs.var = callused_id;
>    rhs.offset = 0;
> !   process_constraint (new_constraint (lhs, rhs));
>
>    /* Create the INTEGER variable, used to represent that a variable points
>       to an INTEGER.  */
> *************** init_base_vars (void)
> *** 5372,5378 ****
>    rhs.type = ADDRESSOF;
>    rhs.var = escaped_id;
>    rhs.offset = 0;
> !   process_constraint_1 (new_constraint (lhs, rhs), true);
>
>    /* *ESCAPED = &NONLOCAL.  This is true because we have to assume
>       everything pointed to by escaped can also point to nonlocal. */
> --- 5106,5112 ----
>    rhs.type = ADDRESSOF;
>    rhs.var = escaped_id;
>    rhs.offset = 0;
> !   process_constraint (new_constraint (lhs, rhs));
>
>    /* *ESCAPED = &NONLOCAL.  This is true because we have to assume
>       everything pointed to by escaped can also point to nonlocal. */
> *************** init_base_vars (void)
> *** 5382,5388 ****
>    rhs.type = ADDRESSOF;
>    rhs.var = nonlocal_id;
>    rhs.offset = 0;
> !   process_constraint_1 (new_constraint (lhs, rhs), true);
>  }
>
>  /* Initialize things necessary to perform PTA */
> --- 5116,5122 ----
>    rhs.type = ADDRESSOF;
>    rhs.var = nonlocal_id;
>    rhs.offset = 0;
> !   process_constraint (new_constraint (lhs, rhs));
>  }
>
>  /* Initialize things necessary to perform PTA */
> *************** compute_tbaa_pruning (void)
> *** 5581,5587 ****
>     at the start of the file for an algorithmic overview.  */
>
>  void
> ! compute_points_to_sets (struct alias_info *ai)
>  {
>    struct scc_info *si;
>    basic_block bb;
> --- 5315,5321 ----
>     at the start of the file for an algorithmic overview.  */
>
>  void
> ! compute_points_to_sets (void)
>  {
>    struct scc_info *si;
>    basic_block bb;
> *************** compute_points_to_sets (struct alias_inf
> *** 5600,5617 ****
>        tree phi;
>
>        for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
> !       {
> !         if (is_gimple_reg (PHI_RESULT (phi)))
> !           {
> !             find_func_aliases (phi);
> ! !             /* Update various related attributes like escaped
> !                addresses, pointer dereferences for loads and stores.
> !                This is used when creating name tags and alias
> !                sets.  */
> !             update_alias_info (phi, ai);
> !           }
> !       }
>
>        for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
>        {
> --- 5334,5341 ----
>        tree phi;
>
>        for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
> !       if (is_gimple_reg (PHI_RESULT (phi)))
> !         find_func_aliases (phi);
>
>        for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
>        {
> *************** compute_points_to_sets (struct alias_inf
> *** 5619,5630 ****
>
>          find_func_aliases (stmt);
>
> -         /* Update various related attributes like escaped
> -            addresses, pointer dereferences for loads and stores.
> -            This is used when creating name tags and alias
> -            sets.  */
> -         update_alias_info (stmt, ai);
> -
>          /* The information in CHANGE_DYNAMIC_TYPE_EXPR nodes has now
>             been captured, and we can remove them.  */
>          if (TREE_CODE (stmt) == CHANGE_DYNAMIC_TYPE_EXPR)
> --- 5343,5348 ----
> *************** ipa_pta_execute (void)
> *** 5761,5767 ****
>            {
>              varinfo_t fi = get_varinfo (varid);
>              for (; fi; fi = fi->next)
> !               make_constraint_from_anything (fi);
>            }
>        }
>      }
> --- 5479,5485 ----
>            {
>              varinfo_t fi = get_varinfo (varid);
>              for (; fi; fi = fi->next)
> !               make_constraint_from (fi, anything_id);
>            }
>        }
>      }
> Index: tree-ssa-structalias.h
> ===================================================================
> *** tree-ssa-structalias.h      (revision 137251)
> --- tree-ssa-structalias.h      (working copy)
> ***************
> *** 24,67 ****
>  struct constraint;
>  typedef struct constraint *constraint_t;
>
> - /* Alias information used by compute_may_aliases and its helpers.  */
> - struct alias_info
> - {
> -   /* SSA names visited while collecting points-to information.  If bit I
> -      is set, it means that SSA variable with version I has already been
> -      visited.  */
> -   sbitmap ssa_names_visited;
> - -   /* Array of SSA_NAME pointers processed by the points-to collector.
>  */
> -   VEC(tree,heap) *processed_ptrs;
> - -   /* ADDRESSABLE_VARS contains all the global variables and locals that
> -      have had their address taken.  */
> -   struct alias_map_d **addressable_vars;
> -   size_t num_addressable_vars;
> - -   /* POINTERS contains all the _DECL pointers with unique memory tags
> -      that have been referenced in the program.  */
> -   struct alias_map_d **pointers;
> -   size_t num_pointers;
> - -   /* Variables that have been written to directly (i.e., not through a
> -      pointer dereference).  */
> -   struct pointer_set_t *written_vars;
> - -   /* Pointers that have been used in an indirect store operation.  */
> -   struct pointer_set_t *dereferenced_ptrs_store;
> - -   /* Pointers that have been used in an indirect load operation.  */
> -   struct pointer_set_t *dereferenced_ptrs_load;
> - };
> -
>  /* In tree-ssa-alias.c.  */
>  enum escape_type is_escape_site (tree);
>  void update_mem_sym_stats_from_stmt (tree, tree, long, long);
>
>  /* In tree-ssa-structalias.c.  */
> ! extern void compute_points_to_sets (struct alias_info *);
>  extern void delete_points_to_sets (void);
>  extern void dump_constraint (FILE *, constraint_t);
>  extern void dump_constraints (FILE *);
> --- 24,35 ----
>  struct constraint;
>  typedef struct constraint *constraint_t;
>
>  /* In tree-ssa-alias.c.  */
>  enum escape_type is_escape_site (tree);
>  void update_mem_sym_stats_from_stmt (tree, tree, long, long);
>
>  /* In tree-ssa-structalias.c.  */
> ! extern void compute_points_to_sets (void);
>  extern void delete_points_to_sets (void);
>  extern void dump_constraint (FILE *, constraint_t);
>  extern void dump_constraints (FILE *);
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]