Hello,

> > > I think this might be a good idea.  I think that this requires
> > > a lot of changes (basically going through all uses of bsi_remove
> > > and remove_phi_node and checking them), but it would be cleaner
> > > than the current situation.
> > Agreed.  Tedious work, but it shouldn't be terribly difficult (famous
> > last words).
> 
> I will give it a try (i.e., if it can be done in one afternoon, I will
> send a patch tomorrow :-).

here is a patch.  It passes bootstrap & regtesting except for one
testcase (g++.dg/opt/reg-stack2.C); I do not have time to work further
on it now.

As expected, more complications than I believed appeared.  The changes
to bsi_remove and release_defs would be basically sufficient for ssa
names for real operands, however we are losing ssa names for virtual
operands everywhere, and on several places relying on that they are not
released.

One problem with the patch seems to be that it appears to increase
compile times significantly (by some 4% on compiling preprocessed gcc
sources), I did not investigate where does this slowdown come from.

Zdenek

Index: tree-ssa-loop-im.c
===================================================================
*** tree-ssa-loop-im.c  (revision 120177)
--- tree-ssa-loop-im.c  (working copy)
*************** free_mem_ref_locs (struct mem_ref_loc *m
*** 897,912 ****
  static void
  rewrite_mem_refs (tree tmp_var, struct mem_ref_loc *mem_refs)
  {
-   tree var;
-   ssa_op_iter iter;
- 
    for (; mem_refs; mem_refs = mem_refs->next)
      {
!       FOR_EACH_SSA_TREE_OPERAND (var, mem_refs->stmt, iter, 
SSA_OP_ALL_VIRTUALS)
!       mark_sym_for_renaming (SSA_NAME_VAR (var));
! 
        *mem_refs->ref = tmp_var;
!       update_stmt (mem_refs->stmt);
      }
  }
  
--- 897,907 ----
  static void
  rewrite_mem_refs (tree tmp_var, struct mem_ref_loc *mem_refs)
  {
    for (; mem_refs; mem_refs = mem_refs->next)
      {
!       push_stmt_changes (&mem_refs->stmt);
        *mem_refs->ref = tmp_var;
!       pop_stmt_changes (&mem_refs->stmt);
      }
  }
  
Index: tree-complex.c
===================================================================
*** tree-complex.c      (revision 120177)
--- tree-complex.c      (working copy)
*************** expand_complex_move (block_stmt_iterator
*** 776,781 ****
--- 776,783 ----
        x = build2_gimple (GIMPLE_MODIFY_STMT, x, r);
        bsi_insert_before (bsi, x, BSI_SAME_STMT);
  
+       push_stmt_changes (&stmt);
+ 
        if (stmt == bsi_stmt (*bsi))
        {
          x = build1 (IMAGPART_EXPR, inner_type, unshare_expr (lhs));
*************** expand_complex_move (block_stmt_iterator
*** 794,800 ****
        }
  
        update_all_vops (stmt);
!       update_stmt (stmt);
      }
  }
  
--- 796,802 ----
        }
  
        update_all_vops (stmt);
!       pop_stmt_changes (&stmt);
      }
  }
  
Index: tree-ssa-loop-manip.c
===================================================================
*** tree-ssa-loop-manip.c       (revision 120177)
--- tree-ssa-loop-manip.c       (working copy)
*************** verify_loop_closed_ssa (void)
*** 423,429 ****
    if (current_loops == NULL)
      return;
  
!   verify_ssa (false);
  
    FOR_EACH_BB (bb)
      {
--- 423,429 ----
    if (current_loops == NULL)
      return;
  
!   verify_ssa (false, false);
  
    FOR_EACH_BB (bb)
      {
Index: tree-tailcall.c
===================================================================
*** tree-tailcall.c     (revision 120177)
--- tree-tailcall.c     (working copy)
*************** eliminate_tail_call (struct tailcall *t)
*** 752,758 ****
        break;
  
        bsi_remove (&bsi, true);
-       release_defs (t);
      }
  
    /* Number of executions of function has reduced by the tailcall.  */
--- 752,757 ----
*************** eliminate_tail_call (struct tailcall *t)
*** 798,804 ****
      }
  
    bsi_remove (&t->call_bsi, true);
-   release_defs (call);
  }
  
  /* Add phi nodes for the virtual operands defined in the function to the
--- 797,802 ----
Index: tree-ssa-dse.c
===================================================================
*** tree-ssa-dse.c      (revision 120177)
--- tree-ssa-dse.c      (working copy)
*************** dse_optimize_stmt (struct dom_walk_data 
*** 608,617 ****
  
          /* Remove the dead store.  */
          bsi_remove (&bsi, true);
- 
-         /* And release any SSA_NAMEs set in this statement back to the
-            SSA_NAME manager.  */
-         release_defs (stmt);
        }
  
        record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
--- 608,613 ----
Index: tree-ssa-alias.c
===================================================================
*** tree-ssa-alias.c    (revision 120177)
--- tree-ssa-alias.c    (working copy)
*************** compute_may_aliases (void)
*** 943,953 ****
    {
      block_stmt_iterator bsi;
      basic_block bb;
      FOR_EACH_BB (bb)
        {
          for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
            {
!             update_stmt_if_modified (bsi_stmt (bsi));
            }
        }
    }
--- 943,960 ----
    {
      block_stmt_iterator bsi;
      basic_block bb;
+     tree stmt;
+ 
      FOR_EACH_BB (bb)
        {
          for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
            {
!           stmt = bsi_stmt (bsi);
!           if (stmt_modified_p (stmt))
!             {
!               push_stmt_changes (&stmt);
!               pop_stmt_changes (&stmt);
!             }
            }
        }
    }
Index: tree-ssa-coalesce.c
===================================================================
*** tree-ssa-coalesce.c (revision 120177)
--- tree-ssa-coalesce.c (working copy)
*************** create_outofssa_var_map (coalesce_list_p
*** 1075,1082 ****
          /* Validate that virtual ops don't get used in funny ways.  */
          FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
            {
!             bitmap_set_bit (used_in_virtual_ops, 
!                             DECL_UID (SSA_NAME_VAR (var)));
            }
  
  #endif /* ENABLE_CHECKING */
--- 1075,1083 ----
          /* Validate that virtual ops don't get used in funny ways.  */
          FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
            {
!             tree sym = (TREE_CODE (var) == SSA_NAME
!                         ? SSA_NAME_VAR (var) : var);
!             bitmap_set_bit (used_in_virtual_ops, DECL_UID (sym));
            }
  
  #endif /* ENABLE_CHECKING */
Index: tree-ssa-pre.c
===================================================================
*** tree-ssa-pre.c      (revision 120177)
--- tree-ssa-pre.c      (working copy)
*************** remove_dead_inserted_code (void)
*** 4047,4053 ****
            {
              bsi = bsi_for_stmt (t);
              bsi_remove (&bsi, true);
-             release_defs (t);
            }
        }
      }
--- 4047,4052 ----
Index: tree-sra.c
===================================================================
*** tree-sra.c  (revision 120177)
--- tree-sra.c  (working copy)
*************** static void
*** 1972,1978 ****
  sra_replace (block_stmt_iterator *bsi, tree list)
  {
    sra_insert_before (bsi, list);
!   bsi_remove (bsi, false);
    if (bsi_end_p (*bsi))
      *bsi = bsi_last (bsi->bb);
    else
--- 1972,1978 ----
  sra_replace (block_stmt_iterator *bsi, tree list)
  {
    sra_insert_before (bsi, list);
!   bsi_remove (bsi, true);
    if (bsi_end_p (*bsi))
      *bsi = bsi_last (bsi->bb);
    else
*************** scalarize_use (struct sra_elt *elt, tree
*** 1993,2002 ****
      {
        /* If we have a replacement, then updating the reference is as
         simple as modifying the existing statement in place.  */
!       if (is_output)
!       mark_all_v_defs (stmt);
        *expr_p = elt->replacement;
!       update_stmt (stmt);
      }
    else
      {
--- 1993,2001 ----
      {
        /* If we have a replacement, then updating the reference is as
         simple as modifying the existing statement in place.  */
!       push_stmt_changes (&stmt);
        *expr_p = elt->replacement;
!       pop_stmt_changes (&stmt);
      }
    else
      {
Index: tree-ssa-dce.c
===================================================================
*** tree-ssa-dce.c      (revision 120177)
--- tree-ssa-dce.c      (working copy)
*************** remove_dead_stmt (block_stmt_iterator *i
*** 642,648 ****
      }
    
    bsi_remove (i, true);  
-   release_defs (t); 
  }
  
  
--- 642,647 ----
Index: tree-ssa.c
===================================================================
*** tree-ssa.c  (revision 120177)
--- tree-ssa.c  (working copy)
*************** verify_alias_info (void)
*** 566,575 ****
  
  
  /* Verify common invariants in the SSA web.
     TODO: verify the variable annotations.  */
  
  void
! verify_ssa (bool check_modified_stmt)
  {
    size_t i;
    basic_block bb;
--- 566,582 ----
  
  
  /* Verify common invariants in the SSA web.
+ 
+    If CHECK_MODIFIED_STMT is true, it asserts that no statement is marked
+    modified.
+ 
+    If CHECK_RELEASED_NAMES is true, it asserts that all SSA names that no
+    longer appear in the program are released.
+ 
     TODO: verify the variable annotations.  */
  
  void
! verify_ssa (bool check_modified_stmt, bool check_released_names)
  {
    size_t i;
    basic_block bb;
*************** verify_ssa (bool check_modified_stmt)
*** 578,583 ****
--- 585,594 ----
    tree op;
    enum dom_state orig_dom_state = dom_computed[CDI_DOMINATORS];
    bitmap names_defined_in_bb = BITMAP_ALLOC (NULL);
+   bitmap names_in_code = BITMAP_ALLOC (NULL);
+   block_stmt_iterator bsi;
+   tree phi, stmt;
+   use_operand_p use_p;
  
    gcc_assert (!need_ssa_update_p ());
  
*************** verify_ssa (bool check_modified_stmt)
*** 586,597 ****
    timevar_push (TV_TREE_SSA_VERIFY);
  
    /* Keep track of SSA names present in the IL.  */
    for (i = 1; i < num_ssa_names; i++)
      {
        tree name = ssa_name (i);
        if (name)
        {
-         tree stmt;
          TREE_VISITED (name) = 0;
  
          stmt = SSA_NAME_DEF_STMT (name);
--- 597,629 ----
    timevar_push (TV_TREE_SSA_VERIFY);
  
    /* Keep track of SSA names present in the IL.  */
+   FOR_EACH_BB (bb)
+     {
+       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+       {
+         bitmap_set_bit (names_in_code, SSA_NAME_VERSION (PHI_RESULT (phi)));
+         FOR_EACH_PHI_ARG (use_p, phi, iter, SSA_OP_ALL_USES)
+           {
+             op = USE_FROM_PTR (use_p);
+             if (TREE_CODE (op) == SSA_NAME)
+               bitmap_set_bit (names_in_code, SSA_NAME_VERSION (op));
+           }
+       }
+       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+       {
+         stmt = bsi_stmt (bsi);
+         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
+           {
+             bitmap_set_bit (names_in_code, SSA_NAME_VERSION (op));
+           }
+       }
+     }
+ 
    for (i = 1; i < num_ssa_names; i++)
      {
        tree name = ssa_name (i);
        if (name)
        {
          TREE_VISITED (name) = 0;
  
          stmt = SSA_NAME_DEF_STMT (name);
*************** verify_ssa (bool check_modified_stmt)
*** 601,606 ****
--- 633,644 ----
              verify_def (bb, definition_block,
                          name, stmt, !is_gimple_reg (name));
  
+             if (check_released_names
+                 && !bitmap_bit_p (names_in_code, SSA_NAME_VERSION (name)))
+               {
+                 error ("Lost SSA name %d", SSA_NAME_VERSION (name));
+                 goto err;
+               }
            }
        }
      }
*************** verify_ssa (bool check_modified_stmt)
*** 612,620 ****
    FOR_EACH_BB (bb)
      {
        edge e;
-       tree phi;
        edge_iterator ei;
-       block_stmt_iterator bsi;
  
        /* Make sure that all edges have a clear 'aux' field.  */
        FOR_EACH_EDGE (e, ei, bb->preds)
--- 650,656 ----
*************** verify_ssa (bool check_modified_stmt)
*** 640,648 ****
        /* Now verify all the uses and vuses in every statement of the block.  
*/
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
        {
!         tree stmt = bsi_stmt (bsi);
!         use_operand_p use_p;
! 
          if (check_modified_stmt && stmt_modified_p (stmt))
            {
              error ("stmt (%p) marked modified after optimization pass: ",
--- 676,682 ----
        /* Now verify all the uses and vuses in every statement of the block.  
*/
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
        {
!         stmt = bsi_stmt (bsi);
          if (check_modified_stmt && stmt_modified_p (stmt))
            {
              error ("stmt (%p) marked modified after optimization pass: ",
*************** verify_ssa (bool check_modified_stmt)
*** 720,725 ****
--- 754,760 ----
      dom_computed[CDI_DOMINATORS] = orig_dom_state;
    
    BITMAP_FREE (names_defined_in_bb);
+   BITMAP_FREE (names_in_code);
    timevar_pop (TV_TREE_SSA_VERIFY);
    return;
  
Index: tree-vect-transform.c
===================================================================
*** tree-vect-transform.c       (revision 120177)
--- tree-vect-transform.c       (working copy)
*************** vectorizable_store (tree stmt, block_stm
*** 2667,2673 ****
    tree dummy;
    enum dr_alignment_support alignment_support_cheme;
    ssa_op_iter iter;
-   def_operand_p def_p;
    tree def, def_stmt;
    enum vect_def_type dt;
    stmt_vec_info prev_stmt_info = NULL;
--- 2667,2672 ----
*************** vectorizable_store (tree stmt, block_stm
*** 2875,2909 ****
                             vec_oprnd);
          vect_finish_stmt_generation (stmt, new_stmt, bsi);
  
!         /* Set the VDEFs for the vector pointer. If this virtual def
!            has a use outside the loop and a loop peel is performed
!            then the def may be renamed by the peel.  Mark it for
!            renaming so the later use will also be renamed.  */
!         copy_virtual_operands (new_stmt, next_stmt);
!         if (j == 0)
            {
!             /* The original store is deleted so the same SSA_NAMEs
!                can be used.  */
!             FOR_EACH_SSA_TREE_OPERAND (def, next_stmt, iter, SSA_OP_VDEF)
!               {
!                 SSA_NAME_DEF_STMT (def) = new_stmt;
!                 mark_sym_for_renaming (SSA_NAME_VAR (def));
!               }
!             
!             STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt =  new_stmt;
            }
-         else
-           {
-             /* Create new names for all the definitions created by COPY and
-                add replacement mappings for each new name.  */
-             FOR_EACH_SSA_DEF_OPERAND (def_p, new_stmt, iter, SSA_OP_VDEF)
-               {
-                 create_new_def_for (DEF_FROM_PTR (def_p), new_stmt, def_p);
-                 mark_sym_for_renaming (SSA_NAME_VAR (DEF_FROM_PTR (def_p)));
-               }
              
!             STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
!           }
  
          prev_stmt_info = vinfo_for_stmt (new_stmt);
                  next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
--- 2874,2888 ----
                             vec_oprnd);
          vect_finish_stmt_generation (stmt, new_stmt, bsi);
  
!         FOR_EACH_SSA_TREE_OPERAND (def, new_stmt, iter, SSA_OP_VDEF)
            {
!             mark_sym_for_renaming (def);
            }
              
!         if (j == 0)
!           STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt =  new_stmt;
!         else
!           STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
  
          prev_stmt_info = vinfo_for_stmt (new_stmt);
                  next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
Index: tree-outof-ssa.c
===================================================================
*** tree-outof-ssa.c    (revision 120177)
--- tree-outof-ssa.c    (working copy)
*************** rewrite_trees (var_map map, tree *values
*** 757,763 ****
  
          /* Remove any stmts marked for removal.  */
          if (remove)
!           bsi_remove (&si, true);
          else
            bsi_next (&si);
        }
--- 757,771 ----
  
          /* Remove any stmts marked for removal.  */
          if (remove)
!           {
!             /* To avoid interfering with the rewriting of the remaining
!                statements, avoid removing the definition.  */
!             tree def = DEF_FROM_PTR (def_p);
!             if (TREE_CODE (def) == SSA_NAME)
!               SET_DEF (def_p, SSA_NAME_VAR (def));
! 
!             bsi_remove (&si, true);
!           }
          else
            bsi_next (&si);
        }
Index: tree-flow.h
===================================================================
*** tree-flow.h (revision 120177)
--- tree-flow.h (working copy)
*************** extern edge ssa_redirect_edge (edge, bas
*** 753,759 ****
  extern void flush_pending_stmts (edge);
  extern bool tree_ssa_useless_type_conversion (tree);
  extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
! extern void verify_ssa (bool);
  extern void delete_tree_ssa (void);
  extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
  extern bool stmt_references_memory_p (tree);
--- 753,759 ----
  extern void flush_pending_stmts (edge);
  extern bool tree_ssa_useless_type_conversion (tree);
  extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
! extern void verify_ssa (bool, bool);
  extern void delete_tree_ssa (void);
  extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
  extern bool stmt_references_memory_p (tree);
Index: tree-cfg.c
===================================================================
*** tree-cfg.c  (revision 120177)
--- tree-cfg.c  (working copy)
*************** tree_merge_blocks (basic_block a, basic_
*** 1342,1352 ****
          copy = build2_gimple (GIMPLE_MODIFY_STMT, def, use);
          bsi_insert_after (&bsi, copy, BSI_NEW_STMT);
          SSA_NAME_DEF_STMT (def) = copy;
        }
        else
!       replace_uses_by (def, use);
! 
!       remove_phi_node (phi, NULL, false);
      }
  
    /* Ensure that B follows A.  */
--- 1342,1354 ----
          copy = build2_gimple (GIMPLE_MODIFY_STMT, def, use);
          bsi_insert_after (&bsi, copy, BSI_NEW_STMT);
          SSA_NAME_DEF_STMT (def) = copy;
+         remove_phi_node (phi, NULL, false);
        }
        else
!       {
!         replace_uses_by (def, use);
!         remove_phi_node (phi, NULL, true);
!       }
      }
  
    /* Ensure that B follows A.  */
*************** remove_bb (basic_block bb)
*** 2046,2061 ****
          bsi_insert_before (&new_bsi, stmt, BSI_NEW_STMT);
        }
        else
!         {
!         /* Release SSA definitions if we are in SSA.  Note that we
!            may be called when not in SSA.  For example,
!            final_cleanup calls this function via
!            cleanup_tree_cfg.  */
!         if (gimple_in_ssa_p (cfun))
!           release_defs (stmt);
! 
!         bsi_remove (&i, true);
!       }
  
        /* Don't warn for removed gotos.  Gotos are often removed due to
         jump threading, thus resulting in bogus warnings.  Not great,
--- 2048,2054 ----
          bsi_insert_before (&new_bsi, stmt, BSI_NEW_STMT);
        }
        else
!       bsi_remove (&i, true);
  
        /* Don't warn for removed gotos.  Gotos are often removed due to
         jump threading, thus resulting in bogus warnings.  Not great,
*************** bsi_insert_after (block_stmt_iterator *i
*** 2854,2877 ****
  
  
  /* Remove the statement pointed to by iterator I.  The iterator is updated
!    to the next statement.
! 
!    When REMOVE_EH_INFO is true we remove the statement pointed to by
!    iterator I from the EH tables.  Otherwise we do not modify the EH
!    tables.
! 
!    Generally, REMOVE_EH_INFO should be true when the statement is going to
!    be removed from the IL and not reinserted elsewhere.  */
  
  void
! bsi_remove (block_stmt_iterator *i, bool remove_eh_info)
  {
    tree t = bsi_stmt (*i);
    set_bb_for_stmt (t, NULL);
    delink_stmt_imm_use (t);
    tsi_delink (&i->tsi);
    mark_stmt_modified (t);
!   if (remove_eh_info)
      {
        remove_stmt_from_eh_region (t);
        gimple_remove_stmt_histograms (cfun, t);
--- 2847,2871 ----
  
  
  /* Remove the statement pointed to by iterator I.  The iterator is updated
!    to the next statement.  If REALLY_REMOVE is true, the statement
!    will really be removed from the code and not reinserted elsewhere.
!    In that case, ssa names defined in the statement are released and
!    the statement is removed from EH tables.  */
  
  void
! bsi_remove (block_stmt_iterator *i, bool really_remove)
  {
    tree t = bsi_stmt (*i);
+ 
+   if (really_remove
+       && gimple_in_ssa_p (cfun))
+     release_defs (t);
+ 
    set_bb_for_stmt (t, NULL);
    delink_stmt_imm_use (t);
    tsi_delink (&i->tsi);
    mark_stmt_modified (t);
!   if (really_remove)
      {
        remove_stmt_from_eh_region (t);
        gimple_remove_stmt_histograms (cfun, t);
Index: passes.c
===================================================================
*** passes.c    (revision 120177)
--- passes.c    (working copy)
*************** execute_function_todo (void *data)
*** 800,806 ****
  
  #if defined ENABLE_CHECKING
    if (flags & TODO_verify_ssa)
!     verify_ssa (true);
    if (flags & TODO_verify_flow)
      verify_flow_info ();
    if (flags & TODO_verify_stmts)
--- 800,806 ----
  
  #if defined ENABLE_CHECKING
    if (flags & TODO_verify_ssa)
!     verify_ssa (true, true);
    if (flags & TODO_verify_flow)
      verify_flow_info ();
    if (flags & TODO_verify_stmts)
Index: tree-ssanames.c
===================================================================
*** tree-ssanames.c     (revision 120177)
--- tree-ssanames.c     (working copy)
*************** release_ssa_name (tree var)
*** 202,211 ****
--- 202,243 ----
        tree saved_ssa_name_var = SSA_NAME_VAR (var);
        int saved_ssa_name_version = SSA_NAME_VERSION (var);
        use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
+       imm_use_iterator imm_iter;
+       use_operand_p use;
+       tree stmt;
  
  #ifdef ENABLE_CHECKING
        verify_imm_links (stderr, var);
  #endif
+ 
+       /* Rewrite the uses of VAR out of ssa.  This is important especially
+        for virtual operands, in the following scenario:  We have
+ 
+        # a_0 = vdef
+        www ()
+        # a_1 = vdef (a_0)
+        xxx ();
+        # vuse a_1
+        yyy ();
+ 
+        Suppose that the xxx call is removed, symbol a is marked for renaming,
+        and the _1 name is reused for another variable (e.g. b).  We would
+        end up with
+ 
+        # a_0 = vdef
+        www ()
+        # vuse b_1
+        yyy ();
+ 
+        and ssa name updating would not be able to fix the ssa form.  */
+       FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+       {
+         FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
+           {
+             SET_USE (use, saved_ssa_name_var);
+           }
+       }
+ 
        while (imm->next != imm)
        delink_imm_use (imm->next);
  
*************** release_defs (tree stmt)
*** 291,297 ****
    gcc_assert (gimple_in_ssa_p (cfun));
  
    FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
!     if (TREE_CODE (def) == SSA_NAME)
        release_ssa_name (def);
  }
  
--- 323,332 ----
    gcc_assert (gimple_in_ssa_p (cfun));
  
    FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
!     if (TREE_CODE (def) == SSA_NAME
!       /* In case we replaced the definition by a new one, do not release
!          the ssa name when we remove the old definition.  */
!       && SSA_NAME_DEF_STMT (def) == stmt)
        release_ssa_name (def);
  }
  
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c (revision 120177)
--- tree-ssa-operands.c (working copy)
*************** struct scb_d
*** 181,186 ****
--- 181,189 ----
       loaded and stored by the statement.  */
    bitmap loads;
    bitmap stores;
+ 
+   /* The set of virtual ssa names defined by the statement.  */
+   bitmap defs;
  };
  
  typedef struct scb_d *scb_t;
*************** add_stmt_operand (tree *var_p, stmt_ann_
*** 1552,1557 ****
--- 1555,1564 ----
    gcc_assert (SSA_VAR_P (*var_p) && s_ann);
  
    var = *var_p;
+ 
+   /* Verify that we are not using an SSA name that was already released.  */
+   gcc_assert (TREE_CODE (var) != SSA_NAME || !SSA_NAME_IN_FREE_LIST (var));
+ 
    sym = (TREE_CODE (var) == SSA_NAME ? SSA_NAME_VAR (var) : var);
    v_ann = var_ann (sym);
  
*************** push_stmt_changes (tree *stmt_p)
*** 2748,2754 ****
  
    buf->stmt_p = stmt_p;
  
!   if (stmt_references_memory_p (stmt))
      {
        tree op;
        ssa_op_iter i;
--- 2755,2765 ----
  
    buf->stmt_p = stmt_p;
  
!   if (/* push_stmt_changes may be called even for completely new statement,
!        without any annotations.  In that case, it does not have any operands
!        yet.  */
!       stmt_ann (stmt) != NULL
!       && stmt_references_memory_p (stmt))
      {
        tree op;
        ssa_op_iter i;
*************** push_stmt_changes (tree *stmt_p)
*** 2767,2772 ****
--- 2778,2789 ----
          if (buf->stores == NULL)
            buf->stores = BITMAP_ALLOC (NULL);
          bitmap_set_bit (buf->stores, DECL_UID (sym));
+         if (TREE_CODE (op) == SSA_NAME)
+           {
+             if (buf->defs == NULL)
+               buf->defs = BITMAP_ALLOC (NULL);
+             bitmap_set_bit (buf->defs, SSA_NAME_VERSION (op));
+           }
        }
      }
  
*************** pop_stmt_changes (tree *stmt_p)
*** 2814,2819 ****
--- 2831,2838 ----
    ssa_op_iter iter;
    bitmap loads, stores;
    scb_t buf;
+   bitmap_iterator bi;
+   unsigned i;
  
    stmt = *stmt_p;
  
*************** pop_stmt_changes (tree *stmt_p)
*** 2855,2860 ****
--- 2874,2882 ----
          if (stores == NULL)
            stores = BITMAP_ALLOC (NULL);
          bitmap_set_bit (stores, DECL_UID (sym));
+ 
+         if (buf->defs && TREE_CODE (op) == SSA_NAME)
+           bitmap_clear_bit (buf->defs, SSA_NAME_VERSION (op));
        }
      }
  
*************** pop_stmt_changes (tree *stmt_p)
*** 2884,2892 ****
--- 2906,2925 ----
       replacement mapping that would replace every reference of
       SMT.4_20 with SMT.4_16.  */
  
+   /* For now, just release the SSA names whose definitions disappear.  */
+   if (buf->defs)
+     {
+       EXECUTE_IF_SET_IN_BITMAP (buf->defs, 0, i, bi)
+       {
+         tree name = ssa_name (i);
+         release_ssa_name (name);
+       }
+     }
+ 
    /* Free memory used by the buffer.  */
    BITMAP_FREE (buf->loads);
    BITMAP_FREE (buf->stores);
+   BITMAP_FREE (buf->defs);
    BITMAP_FREE (loads);
    BITMAP_FREE (stores);
    buf->stmt_p = NULL;

Reply via email to