https://gcc.gnu.org/g:39b59f1c6b339a131480a9e01ec6d9841279ee4d

commit 39b59f1c6b339a131480a9e01ec6d9841279ee4d
Author: Michael Matz <[email protected]>
Date:   Mon Feb 19 00:50:04 2018 +0100

    no-update-stmt: start hacking
    
    This survives the check-gcc testsuite.
    update_stmt() only checks for valid operands
    update_stmt_for_real() is the former update_stmt
    the operand setters call update_stmt_for_real.
    Various places that directly pointer-modify operands
    need to call update_stmt_for_real as well.

Diff:
---
 gcc/gimple-fold.c                   |  7 ++++
 gcc/gimple-ssa-isolate-paths.c      |  2 +-
 gcc/gimple-ssa-store-merging.c      |  2 +-
 gcc/gimple-ssa-strength-reduction.c |  4 +-
 gcc/gimple-ssa.h                    |  4 +-
 gcc/gimple.c                        |  4 ++
 gcc/gimple.h                        | 83 ++++++++++++++++++++++++++-----------
 gcc/gimplify-me.c                   |  5 ++-
 gcc/ipa-split.c                     |  2 +-
 gcc/omp-simd-clone.c                |  4 +-
 gcc/print-tree.c                    |  4 +-
 gcc/tree-cfg.c                      |  6 +--
 gcc/tree-chkp-opt.c                 |  3 +-
 gcc/tree-inline.c                   |  2 +-
 gcc/tree-into-ssa.c                 |  2 +-
 gcc/tree-parloops.c                 |  4 +-
 gcc/tree-profile.c                  |  6 ++-
 gcc/tree-sra.c                      | 10 ++++-
 gcc/tree-ssa-dom.c                  |  1 +
 gcc/tree-ssa-dse.c                  |  3 +-
 gcc/tree-ssa-forwprop.c             | 12 ++++--
 gcc/tree-ssa-loop-im.c              |  6 ++-
 gcc/tree-ssa-loop-ivopts.c          |  9 ++--
 gcc/tree-ssa-operands.c             | 37 ++++++++++++++++-
 gcc/tree-ssa-phionlycprop.c         | 10 ++++-
 gcc/tree-ssa-sccvn.c                | 11 ++++-
 gcc/tree-ssa-scopedtables.c         |  2 +-
 gcc/tree-ssa-tail-merge.c           |  9 +++-
 gcc/tree-ssa.c                      |  8 +++-
 gcc/tree-vect-patterns.c            |  6 ++-
 gcc/tree-vect-stmts.c               |  4 ++
 gcc/value-prof.c                    |  9 ++--
 32 files changed, 215 insertions(+), 66 deletions(-)

diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index bd8c44a6a607..5091ac003b99 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2882,6 +2882,9 @@ gimple_fold_builtin_snprintf_chk (gimple_stmt_iterator 
*gsi,
   for (unsigned i = 3; i < gimple_call_num_args (stmt) - 2; ++i)
     gimple_call_set_arg (stmt, i, gimple_call_arg (stmt, i + 2));
   gimple_set_num_ops (stmt, gimple_num_ops (stmt) - 2);
+  /* XXX gimple_set_num_ops removes arguments which requires updating
+     the operand cache.  Make that implicit.  */
+  update_stmt_for_real (stmt);
   fold_stmt (gsi);
   return true;
 }
@@ -2978,6 +2981,9 @@ gimple_fold_builtin_sprintf_chk (gimple_stmt_iterator 
*gsi,
   for (unsigned i = 2; i < gimple_call_num_args (stmt) - 2; ++i)
     gimple_call_set_arg (stmt, i, gimple_call_arg (stmt, i + 2));
   gimple_set_num_ops (stmt, gimple_num_ops (stmt) - 2);
+  /* XXX gimple_set_num_ops removes arguments which requires updating
+     the operand cache.  Make that implicit.  */
+  update_stmt_for_real (stmt);
   fold_stmt (gsi);
   return true;
 }
@@ -3944,6 +3950,7 @@ fold_builtin_atomic_compare_exchange 
(gimple_stmt_iterator *gsi)
     }
   gimple_call_set_nothrow (as_a <gcall *> (g),
                           gimple_call_nothrow_p (as_a <gcall *> (stmt)));
+  stmt->bb = NULL; // XXX disable operand updating (makes expected addressable 
again)
   gimple_call_set_lhs (stmt, NULL_TREE);
   gsi_replace (gsi, g, true);
   if (oldlhs)
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c
index 131705d18279..ffea8b262797 100644
--- a/gcc/gimple-ssa-isolate-paths.c
+++ b/gcc/gimple-ssa-isolate-paths.c
@@ -56,7 +56,7 @@ check_loadstore (gimple *stmt, tree op, tree, void *data)
     {
       TREE_THIS_VOLATILE (op) = 1;
       TREE_SIDE_EFFECTS (op) = 1;
-      update_stmt (stmt);
+      gimple_set_has_volatile_ops (stmt, true);
       return true;
     }
   return false;
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 2e1a6ef0e551..33c235fa5160 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -1014,8 +1014,8 @@ bswap_replace (gimple_stmt_iterator gsi, gimple 
*ins_stmt, tree fndecl,
            }
          else if (cur_stmt)
            {
-             gimple_assign_set_rhs_with_ops (&gsi, MEM_REF, val_expr);
              gimple_set_vuse (cur_stmt, n->vuse);
+             gimple_assign_set_rhs_with_ops (&gsi, MEM_REF, val_expr);
              update_stmt (cur_stmt);
            }
          else
diff --git a/gcc/gimple-ssa-strength-reduction.c 
b/gcc/gimple-ssa-strength-reduction.c
index 1c00f094db80..ba418fdbafac 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -1992,7 +1992,9 @@ replace_ref (tree *expr, slsr_cand_t c)
                                /*before=*/true, GSI_SAME_STMT);
   copy_ref_info (mem_ref, *expr);
   *expr = mem_ref;
-  update_stmt (c->cand_stmt);
+  /* XXX change gimple operands via proper wrappers not via
+     pointer store, so no update_stmt would be needed.  */
+  update_stmt_for_real (c->cand_stmt);
 }
 
 /* Replace CAND_REF candidate C, each sibling of candidate C, and each
diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h
index a82857e95292..e4328c50474d 100644
--- a/gcc/gimple-ssa.h
+++ b/gcc/gimple-ssa.h
@@ -167,7 +167,7 @@ gimple_vdef_op (gimple *g)
 /* Mark statement S as modified, and update it.  */
 
 static inline void
-update_stmt (gimple *s)
+update_stmt_for_real (gimple *s)
 {
   if (gimple_has_ops (s))
     {
@@ -176,6 +176,8 @@ update_stmt (gimple *s)
     }
 }
 
+void update_stmt (gimple *);
+
 /* Update statement S if it has been optimized.  */
 
 static inline void
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 9dc4911a36e0..11fa0a8af866 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1594,6 +1594,8 @@ void
 gimple_set_bb (gimple *stmt, basic_block bb)
 {
   stmt->bb = bb;
+  if (flag_try_patch && bb)
+    update_stmt_for_real (stmt);
 
   if (gimple_code (stmt) != GIMPLE_LABEL)
     return;
@@ -1744,6 +1746,8 @@ gimple_copy (gimple *stmt)
   /* Shallow copy all the fields from STMT.  */
   memcpy (copy, stmt, gimple_size (code));
   gimple_init_singleton (copy);
+  copy->bb = NULL;
+  //gimple_set_bb (copy, NULL); // XXX deactivate operand updating in _set_op
 
   /* If STMT has sub-statements, deep-copy them as well.  */
   if (gimple_has_substatements (stmt))
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 265e3e24398c..cf5bb844ab79 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -2402,6 +2402,16 @@ gimple_op_ptr (gimple *gs, unsigned i)
     return NULL;
 }
 
+#include "gimple-ssa.h"
+static inline void
+gimple_set_op_update (gimple *gs, unsigned i, tree val)
+{
+  tree *pop = gimple_op_ptr (gs, i);
+  *pop = val;
+  if (flag_try_patch && gs->bb)
+    update_stmt_for_real (gs);
+}
+
 /* Set operand I of statement GS to OP.  */
 
 static inline void
@@ -2413,7 +2423,8 @@ gimple_set_op (gimple *gs, unsigned i, tree op)
      is_gimple_operand, but that would be wrong.  Different tuples
      accept slightly different sets of tree operands.  Each caller
      should perform its own validation.  */
-  gimple_ops (gs)[i] = op;
+  //gimple_ops (gs)[i] = op;
+  gimple_set_op_update (gs, i, op);
 }
 
 /* Return true if GS is a GIMPLE_ASSIGN.  */
@@ -2470,7 +2481,8 @@ gimple_assign_lhs_ptr (gimple *gs)
 static inline void
 gimple_assign_set_lhs (gassign *gs, tree lhs)
 {
-  gs->op[0] = lhs;
+  //gs->op[0] = lhs;
+  gimple_set_op_update (gs, 0, lhs);
 
   if (lhs && TREE_CODE (lhs) == SSA_NAME)
     SSA_NAME_DEF_STMT (lhs) = gs;
@@ -2521,7 +2533,8 @@ gimple_assign_rhs1_ptr (gimple *gs)
 static inline void
 gimple_assign_set_rhs1 (gassign *gs, tree rhs)
 {
-  gs->op[1] = rhs;
+  //gs->op[1] = rhs;
+  gimple_set_op_update (gs, 1, rhs);
 }
 
 static inline void
@@ -2576,7 +2589,8 @@ static inline void
 gimple_assign_set_rhs2 (gassign *gs, tree rhs)
 {
   gcc_gimple_checking_assert (gimple_num_ops (gs) >= 3);
-  gs->op[2] = rhs;
+  //gs->op[2] = rhs;
+  gimple_set_op_update (gs, 2, rhs);
 }
 
 static inline void
@@ -2623,7 +2637,8 @@ static inline void
 gimple_assign_set_rhs3 (gassign *gs, tree rhs)
 {
   gcc_gimple_checking_assert (gimple_num_ops (gs) >= 4);
-  gs->op[3] = rhs;
+  //gs->op[3] = rhs;
+  gimple_set_op_update (gs, 3, rhs);
 }
 
 static inline void
@@ -2827,7 +2842,8 @@ gimple_call_lhs_ptr (gimple *gs)
 static inline void
 gimple_call_set_lhs (gcall *gs, tree lhs)
 {
-  gs->op[0] = lhs;
+  //gs->op[0] = lhs;
+  gimple_set_op_update (gs, 0, lhs);
   if (lhs && TREE_CODE (lhs) == SSA_NAME)
     SSA_NAME_DEF_STMT (lhs) = gs;
 }
@@ -3056,7 +3072,8 @@ static inline void
 gimple_call_set_fn (gcall *gs, tree fn)
 {
   gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
-  gs->op[1] = fn;
+  //gs->op[1] = fn;
+  gimple_set_op_update (gs, 1, fn);
 }
 
 
@@ -3066,8 +3083,9 @@ static inline void
 gimple_call_set_fndecl (gcall *gs, tree decl)
 {
   gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
-  gs->op[1] = build1_loc (gimple_location (gs), ADDR_EXPR,
-                         build_pointer_type (TREE_TYPE (decl)), decl);
+  gimple_call_set_fn (gs,
+                     build1_loc (gimple_location (gs), ADDR_EXPR,
+                                 build_pointer_type (TREE_TYPE (decl)), decl));
 }
 
 static inline void
@@ -3151,7 +3169,8 @@ gimple_call_chain_ptr (gcall *call_stmt)
 static inline void
 gimple_call_set_chain (gcall *call_stmt, tree chain)
 {
-  call_stmt->op[2] = chain;
+  //call_stmt->op[2] = chain;
+  gimple_set_op_update (call_stmt, 2, chain);
 }
 
 
@@ -3212,7 +3231,8 @@ static inline void
 gimple_call_set_arg (gcall *gs, unsigned index, tree arg)
 {
   gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 3);
-  gs->op[index + 3] = arg;
+  //gs->op[index + 3] = arg;
+  gimple_set_op_update (gs, index + 3, arg);
 }
 
 static inline void
@@ -3509,7 +3529,8 @@ gimple_cond_lhs_ptr (gcond *gs)
 static inline void
 gimple_cond_set_lhs (gcond *gs, tree lhs)
 {
-  gs->op[0] = lhs;
+  //gs->op[0] = lhs;
+  gimple_set_op_update (gs, 0, lhs);
 }
 
 
@@ -3544,7 +3565,8 @@ gimple_cond_rhs_ptr (gcond *gs)
 static inline void
 gimple_cond_set_rhs (gcond *gs, tree rhs)
 {
-  gs->op[1] = rhs;
+  //gs->op[1] = rhs;
+  gimple_set_op_update (gs, 1, rhs);
 }
 
 
@@ -3564,7 +3586,8 @@ gimple_cond_true_label (const gcond *gs)
 static inline void
 gimple_cond_set_true_label (gcond *gs, tree label)
 {
-  gs->op[2] = label;
+  //gs->op[2] = label;
+  gimple_set_op_update (gs, 2, label);
 }
 
 
@@ -3574,7 +3597,8 @@ gimple_cond_set_true_label (gcond *gs, tree label)
 static inline void
 gimple_cond_set_false_label (gcond *gs, tree label)
 {
-  gs->op[3] = label;
+  //gs->op[3] = label;
+  gimple_set_op_update (gs, 3, label);
 }
 
 
@@ -3685,7 +3709,8 @@ gimple_label_label (const glabel *gs)
 static inline void
 gimple_label_set_label (glabel *gs, tree label)
 {
-  gs->op[0] = label;
+  //gs->op[0] = label;
+  gimple_set_op_update (gs, 0, label);
 }
 
 
@@ -3704,7 +3729,8 @@ gimple_goto_dest (const gimple *gs)
 static inline void
 gimple_goto_set_dest (ggoto *gs, tree dest)
 {
-  gs->op[0] = dest;
+  //gs->op[0] = dest;
+  gimple_set_op_update (gs, 0, dest);
 }
 
 
@@ -3852,7 +3878,8 @@ gimple_asm_set_input_op (gasm *asm_stmt, unsigned index, 
tree in_op)
 {
   gcc_gimple_checking_assert (index < asm_stmt->ni
                              && TREE_CODE (in_op) == TREE_LIST);
-  asm_stmt->op[index + asm_stmt->no] = in_op;
+  //asm_stmt->op[index + asm_stmt->no] = in_op;
+  gimple_set_op_update (asm_stmt, index + asm_stmt->no, in_op);
 }
 
 
@@ -3872,7 +3899,8 @@ gimple_asm_set_output_op (gasm *asm_stmt, unsigned index, 
tree out_op)
 {
   gcc_gimple_checking_assert (index < asm_stmt->no
                              && TREE_CODE (out_op) == TREE_LIST);
-  asm_stmt->op[index] = out_op;
+  //asm_stmt->op[index] = out_op;
+  gimple_set_op_update (asm_stmt, index, out_op);
 }
 
 
@@ -3893,7 +3921,9 @@ gimple_asm_set_clobber_op (gasm *asm_stmt, unsigned 
index, tree clobber_op)
 {
   gcc_gimple_checking_assert (index < asm_stmt->nc
                              && TREE_CODE (clobber_op) == TREE_LIST);
-  asm_stmt->op[index + asm_stmt->ni + asm_stmt->no] = clobber_op;
+  //asm_stmt->op[index + asm_stmt->ni + asm_stmt->no] = clobber_op;
+  gimple_set_op_update (asm_stmt, index + asm_stmt->ni + asm_stmt->no,
+                       clobber_op);
 }
 
 /* Return label operand INDEX of GIMPLE_ASM ASM_STMT.  */
@@ -3912,7 +3942,9 @@ gimple_asm_set_label_op (gasm *asm_stmt, unsigned index, 
tree label_op)
 {
   gcc_gimple_checking_assert (index < asm_stmt->nl
                              && TREE_CODE (label_op) == TREE_LIST);
-  asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc] = label_op;
+  //asm_stmt->op[index + asm_stmt->ni + asm_stmt->nc] = label_op;
+  gimple_set_op_update (asm_stmt, index + asm_stmt->ni + asm_stmt->nc,
+                       label_op);
 }
 
 /* Return the string representing the assembly instruction in
@@ -4551,7 +4583,8 @@ static inline void
 gimple_switch_set_index (gswitch *gs, tree index)
 {
   gcc_gimple_checking_assert (SSA_VAR_P (index) || CONSTANT_CLASS_P (index));
-  gs->op[0] = index;
+  //gs->op[0] = index;
+  gimple_set_op_update (gs, 0, index);
 }
 
 
@@ -4573,7 +4606,8 @@ gimple_switch_set_label (gswitch *gs, unsigned index, 
tree label)
   gcc_gimple_checking_assert (gimple_num_ops (gs) > index + 1
                              && (label == NULL_TREE
                                  || TREE_CODE (label) == CASE_LABEL_EXPR));
-  gs->op[index + 1] = label;
+  //gs->op[index + 1] = label;
+  gimple_set_op_update (gs, index + 1, label);
 }
 
 /* Return the default label for a switch statement.  */
@@ -6219,7 +6253,8 @@ gimple_return_retval (const greturn *gs)
 static inline void
 gimple_return_set_retval (greturn *gs, tree retval)
 {
-  gs->op[0] = retval;
+  //gs->op[0] = retval;
+  gimple_set_op_update (gs, 0, retval);
 }
 
 
diff --git a/gcc/gimplify-me.c b/gcc/gimplify-me.c
index 137a5662ccf5..eca7681ff0d2 100644
--- a/gcc/gimplify-me.c
+++ b/gcc/gimplify-me.c
@@ -316,7 +316,10 @@ gimple_regimplify_operands (gimple *stmt, 
gimple_stmt_iterator *gsi_p)
 
   pop_gimplify_context (NULL);
 
-  update_stmt (stmt);
+  /* XXX some of the above transforms directly change gimple ops
+     instead of going through setters.  Once rewritten, update_stmt
+     isn't necessary.  */
+  update_stmt_for_real (stmt);
 }
 
 
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index b03ae02924aa..3d18f071e347 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1359,7 +1359,7 @@ split_function (basic_block return_bb, struct split_point 
*split_point,
            if (gimple_vuse (stmt))
              {
                gimple_set_vuse (stmt, NULL_TREE);
-               update_stmt (stmt);
+               update_stmt_for_real (stmt); // XXX find better way to set vuse
              }
            if (gimple_vdef (stmt))
              break;
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
index b15adf0bada4..92a5fd8bc330 100644
--- a/gcc/omp-simd-clone.c
+++ b/gcc/omp-simd-clone.c
@@ -1012,7 +1012,9 @@ ipa_simd_modify_function_body (struct cgraph_node *node,
 
          if (info.modified)
            {
-             update_stmt (stmt);
+             /* XXX direct operand changes via walk_gimple_op make
+                this necessary:  */
+             update_stmt_for_real (stmt);
              if (maybe_clean_eh_stmt (stmt))
                gimple_purge_dead_eh_edges (gimple_bb (stmt));
            }
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index caf5f2601475..41c5bfcb8379 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -369,6 +369,8 @@ print_node (FILE *file, const char *prefix, tree node, int 
indent,
       if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
        fputs (" suppress-debug", file);
 
+      if (code == FUNCTION_DECL && DECL_PURE_P (node))
+       fputs (" pure", file);
       if (code == FUNCTION_DECL
          && DECL_FUNCTION_SPECIFIC_TARGET (node))
        fputs (" function-specific-target", file);
@@ -383,7 +385,7 @@ print_node (FILE *file, const char *prefix, tree node, int 
indent,
        fputs (" built-in", file);
       if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node))
        fputs (" static-chain", file);
-      if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node))
+      if (code == FUNCTION_DECL && decl_is_tm_clone (node))
        fputs (" tm-clone", file);
 
       if (code == FIELD_DECL && DECL_PACKED (node))
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 2ada965edd61..fca7a2f7287b 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -7033,7 +7033,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block 
bb,
         the current function.  */
       free_stmt_operands (cfun, stmt);
       push_cfun (dest_cfun);
-      update_stmt (stmt);
+      update_stmt_for_real (stmt);
       pop_cfun ();
     }
 
@@ -9367,10 +9367,10 @@ execute_fixup_cfg (void)
                  if (gimple_purge_dead_abnormal_call_edges (bb))
                    todo |= TODO_cleanup_cfg;
 
-                 if (gimple_in_ssa_p (cfun))
+                 if (gimple_in_ssa_p (cfun) && gimple_vuse (stmt))
                    {
                      todo |= TODO_update_ssa | TODO_cleanup_cfg;
-                     update_stmt (stmt);
+                     update_stmt_for_real (stmt);
                    }
                }
 
diff --git a/gcc/tree-chkp-opt.c b/gcc/tree-chkp-opt.c
index 5a005a6a7b63..df90016de5dc 100644
--- a/gcc/tree-chkp-opt.c
+++ b/gcc/tree-chkp-opt.c
@@ -1238,7 +1238,8 @@ chkp_reduce_bounds_lifetime (void)
 
              gimple_set_vdef (stmt, NULL_TREE);
              gimple_set_vuse (stmt, NULL_TREE);
-             update_stmt (stmt);
+             /* XXX only needed to reset vops. */
+             update_stmt_for_real (stmt);
            }
        }
       else
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 5a0a2525c0ca..1696ba9d3598 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2919,7 +2919,7 @@ copy_debug_stmt (gdebug *stmt, copy_body_data *id)
 
   processing_debug_stmt = 0;
 
-  update_stmt (stmt);
+  update_stmt_for_real (stmt);
 }
 
 /* Process deferred debug stmts.  In order to give values better odds
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index f4af33c1303a..195443f2d82c 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -646,7 +646,7 @@ mark_def_sites (basic_block bb, gimple *stmt, bitmap kills)
 
   /* Since this is the first time that we rewrite the program into SSA
      form, force an operand scan on every statement.  */
-  update_stmt (stmt);
+  update_stmt_for_real (stmt);
 
   gcc_checking_assert (blocks_to_update == NULL);
   set_register_defs (stmt, false);
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 3a788ccf1b74..a3276e7d40ee 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -739,8 +739,10 @@ eliminate_local_variables_stmt (edge entry, 
gimple_stmt_iterator *gsi,
       walk_gimple_op (stmt, eliminate_local_variables_1, &dta.info);
     }
 
+  /* XXX If we weren't changing the gimple ops via direct pointer
+     access we wouldn't need to do this:  */
   if (dta.changed)
-    update_stmt (stmt);
+    update_stmt_for_real (stmt);
 }
 
 /* Eliminates the references to local variables from the single entry
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index f96bd4b97048..9f3b8aff5667 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -715,7 +715,9 @@ tree_profiling (void)
        node->set_pure_flag (false, false);
       }
 
-  /* Update call statements and rebuild the cgraph.  */
+  /* As callees const/pure status might have changed we now may need
+     vdefs or vuses on call statements, so update all of them
+     a nd rebuild the cgraph.  */
   FOR_EACH_DEFINED_FUNCTION (node)
     {
       basic_block bb;
@@ -738,7 +740,7 @@ tree_profiling (void)
            {
              gimple *stmt = gsi_stmt (gsi);
              if (is_gimple_call (stmt))
-               update_stmt (stmt);
+               update_stmt_for_real (stmt);
            }
        }
 
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index b513676152fc..3be6d2ca09a6 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -3848,7 +3848,10 @@ sra_modify_function_body (void)
 
          if (modified)
            {
-             update_stmt (stmt);
+             /* XXX Use proper gimple operand setter to update
+                operands instead of in-place modifications, so no
+                update_stmt is necessary.  */
+             update_stmt_for_real (stmt);
              if (maybe_clean_eh_stmt (stmt)
                  && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
                cfg_changed = true;
@@ -5113,7 +5116,10 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec 
adjustments)
 
          if (modified)
            {
-             update_stmt (stmt);
+             /* XXX Use proper gimple operand setter to update
+                operands instead of in-place modifications, so no
+                update_stmt is necessary.  */
+             update_stmt_for_real (stmt);
              if (maybe_clean_eh_stmt (stmt)
                  && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
                cfg_changed = true;
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index a6f176c5def0..329aed6da0d6 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1687,6 +1687,7 @@ record_equivalences_from_stmt (gimple *stmt, int 
may_optimize_p,
         }
       else
         new_stmt = gimple_build_assign (rhs, lhs);
+      /* XXX jeez, the above might construct statements like '3 = *p_42' */
 
       gimple_set_vuse (new_stmt, gimple_vdef (stmt));
 
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 9220fea7f2ec..bcaed1675cd8 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -388,7 +388,8 @@ increment_start_addr (gimple *stmt, tree *where, int 
increment)
       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
       gsi_insert_before (&gsi, newop, GSI_SAME_STMT);
       *where = tem;
-      update_stmt (gsi_stmt (gsi));
+      /* XXX don't use direct operand change via pointer.  */
+      update_stmt_for_real (gsi_stmt (gsi));
       return;
     }
 
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 58ec6b47a5bb..31286868c34f 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -779,6 +779,10 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
          TREE_OPERAND (lhs, 1)
            = wide_int_to_tree (TREE_TYPE (TREE_OPERAND (lhs, 1)), off);
          tidy_after_forward_propagate_addr (use_stmt);
+         /* XXX fix the horrible in-place changes of tree operands, instead use
+            SET_USE and friends, so no update_stmt is necessary.
+            E.g. &TREE_OPERAND(lhs,0) will be some ssa use operand on 
use_stmt. */
+         update_stmt_for_real (use_stmt);
          /* Continue propagating into the RHS if this was not the only use.  */
          if (single_use_p)
            return true;
@@ -825,6 +829,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
          TREE_SIDE_EFFECTS (new_lhs) = TREE_SIDE_EFFECTS (lhs);
          *def_rhs_basep = saved;
          tidy_after_forward_propagate_addr (use_stmt);
+         update_stmt_for_real (use_stmt);
          /* Continue propagating into the RHS if this was not the
             only use.  */
          if (single_use_p)
@@ -871,6 +876,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
            = wide_int_to_tree (TREE_TYPE (TREE_OPERAND (rhs, 1)), off);
          fold_stmt_inplace (use_stmt_gsi);
          tidy_after_forward_propagate_addr (use_stmt);
+         update_stmt_for_real (use_stmt);
          return res;
        }
       /* If the RHS is a plain dereference and the value type is the same as
@@ -912,6 +918,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
          *def_rhs_basep = saved;
          fold_stmt_inplace (use_stmt_gsi);
          tidy_after_forward_propagate_addr (use_stmt);
+         update_stmt_for_real (use_stmt);
          return res;
        }
     }
@@ -1939,9 +1946,8 @@ simplify_permutation (gimple_stmt_iterator *gsi)
        return 0;
       orig = (ident == 1) ? gimple_assign_rhs1 (def_stmt)
                          : gimple_assign_rhs2 (def_stmt);
-      gimple_assign_set_rhs1 (stmt, unshare_expr (orig));
-      gimple_assign_set_rhs_code (stmt, TREE_CODE (orig));
-      gimple_set_num_ops (stmt, 2);
+      gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (orig),
+                                     unshare_expr (orig));
       update_stmt (stmt);
       return remove_prop_source_from_use (op0) ? 2 : 1;
     }
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 030aac0b6163..4dddd3056bc5 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1666,8 +1666,12 @@ struct rewrite_mem_ref_loc
 bool
 rewrite_mem_ref_loc::operator () (mem_ref_loc *loc)
 {
+  /* XXX should use proper gimple operand setters so that
+     update_stmt isn't needed. (At this point we replace a real
+     memref (in top-level operand) with a tmp VAR_DECL which is
+     going to become an SSA name) */
   *loc->ref = tmp_var;
-  update_stmt (loc->stmt);
+  update_stmt_for_real (loc->stmt);
   return false;
 }
 
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index b3135717f22c..4cd8298226f4 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -7217,7 +7217,7 @@ rewrite_groups (struct ivopts_data *data)
          for (j = 0; j < group->vuses.length (); j++)
            {
              rewrite_use_nonlinear_expr (data, group->vuses[j], cand);
-             update_stmt (group->vuses[j]->stmt);
+             update_stmt_for_real (group->vuses[j]->stmt);
            }
        }
       else if (address_p (group->type))
@@ -7225,7 +7225,7 @@ rewrite_groups (struct ivopts_data *data)
          for (j = 0; j < group->vuses.length (); j++)
            {
              rewrite_use_address (data, group->vuses[j], cand);
-             update_stmt (group->vuses[j]->stmt);
+             update_stmt_for_real (group->vuses[j]->stmt);
            }
        }
       else
@@ -7235,7 +7235,7 @@ rewrite_groups (struct ivopts_data *data)
          for (j = 0; j < group->vuses.length (); j++)
            {
              rewrite_use_compare (data, group->vuses[j], cand);
-             update_stmt (group->vuses[j]->stmt);
+             update_stmt_for_real (group->vuses[j]->stmt);
            }
        }
     }
@@ -7365,7 +7365,8 @@ remove_unused_ivs (struct ivopts_data *data)
                  FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
                    SET_USE (use_p, comp);
 
-                 update_stmt (stmt);
+                 /* XXX blaeh, debug statement operands are complicated. */
+                 update_stmt_for_real (stmt);
                }
            }
        }
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 41dcb56001dd..0c23dba4ce14 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -835,6 +835,9 @@ get_expr_operands (struct function *fn, gimple *stmt, tree 
*expr_p, int flags)
 
     case BIT_INSERT_EXPR:
     case COMPOUND_EXPR:
+      //abort(); // happens in debug insns
+      /* FALLTHRU */
+
     case OBJ_TYPE_REF:
     case ASSERT_EXPR:
     do_binary:
@@ -851,6 +854,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree 
*expr_p, int flags)
     case WIDEN_MULT_MINUS_EXPR:
     case FMA_EXPR:
       {
+       abort(); // hmm, but might exist hidden down in debug stmts? yes!
        get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags);
        get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags);
        get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), flags);
@@ -865,12 +869,15 @@ get_expr_operands (struct function *fn, gimple *stmt, 
tree *expr_p, int flags)
       return;
 
     default:
+      if (codeclass == tcc_constant || codeclass == tcc_type)
+       return;
+      /*fprintf(stderr, "XXX");
+      debug_tree (expr);
+      fputs ("\n", stderr);*/
       if (codeclass == tcc_unary)
        goto do_unary;
       if (codeclass == tcc_binary || codeclass == tcc_comparison)
        goto do_binary;
-      if (codeclass == tcc_constant || codeclass == tcc_type)
-       return;
     }
 
   /* If we get here, something has gone wrong.  */
@@ -1084,6 +1091,32 @@ update_stmt_operands (struct function *fn, gimple *stmt)
   timevar_pop (TV_TREE_OPS);
 }
 
+void
+update_stmt (gimple *s)
+{
+  if (gimple_has_ops (s) && ssa_operands_active (cfun))
+    {
+      if (!flag_try_patch)
+       update_stmt_for_real (s);
+      else
+       {
+         /* Cleanup stale per-statement operands.  Those happen
+            when non-SSA-names are placed into operands via SET_USE. */
+         gimple_statement_with_ops *ops_stmt =
+             dyn_cast <gimple_statement_with_ops *> (s);
+         use_optype_p *ptr = &ops_stmt->use_ops;
+         while (*ptr)
+           {
+             if (!USE_OP_PTR(*ptr)->prev && !SSA_VAR_P (USE_OP (*ptr)))
+               *ptr = (*ptr)->next;
+             else
+               ptr = &((*ptr)->next);
+           }
+         if (verify_ssa_operands (cfun, s))
+           print_gimple_stmt (stderr, s, 0, TDF_VOPS);
+       }
+    }
+}
 
 /* Swap operands EXP0 and EXP1 in statement STMT.  No attempt is done
    to test the validity of the swap operation.  */
diff --git a/gcc/tree-ssa-phionlycprop.c b/gcc/tree-ssa-phionlycprop.c
index 632df271fb7c..0cd501aa3cbe 100644
--- a/gcc/tree-ssa-phionlycprop.c
+++ b/gcc/tree-ssa-phionlycprop.c
@@ -158,6 +158,8 @@ propagate_rhs_into_lhs (gimple *stmt, tree lhs, tree rhs,
              continue;
            }
 
+         int old_call_flags
+               = is_gimple_call (use_stmt) ? gimple_call_flags (use_stmt) : 0;
          /* Dump details.  */
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
@@ -208,7 +210,13 @@ propagate_rhs_into_lhs (gimple *stmt, tree lhs, tree rhs,
 
          /* Sometimes propagation can expose new operands to the
             renamer.  */
-         update_stmt (use_stmt);
+         /* XXX the updating fixes the vops in case an indirect call
+            became direct and known const/pure.  */
+         if (is_gimple_call (use_stmt)
+             && old_call_flags != gimple_call_flags (use_stmt))
+           update_stmt_for_real (use_stmt);
+         else
+           update_stmt (use_stmt);
 
          /* Dump details.  */
          if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 1463c1d41165..4da4d105e80d 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -5417,6 +5417,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
       tree sprime = NULL_TREE;
       gimple *stmt = gsi_stmt (gsi);
       tree lhs = gimple_get_lhs (stmt);
+      int old_call_flags = is_gimple_call (stmt) ? gimple_call_flags (stmt) : 
0;
       if (lhs && TREE_CODE (lhs) == SSA_NAME
          && !gimple_has_volatile_ops (stmt)
          /* See PR43491.  Do not replace a global register variable when
@@ -5761,7 +5762,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
 
       /* Visit indirect calls and turn them into direct calls if
         possible using the devirtualization machinery.  Do this before
-        checking for required EH/abnormal/noreturn cleanup as devird
+        checking for required EH/abnormal/noreturn cleanup as devirt
         may expose more of those.  */
       if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
        {
@@ -5851,7 +5852,13 @@ eliminate_dom_walker::before_dom_children (basic_block b)
              if (dump_file && (dump_flags & TDF_DETAILS))
                fprintf (dump_file, "  Removed AB side-effects.\n");
            }
-         update_stmt (stmt);
+         /* XXX the updating fixes the vops in case an indirect call
+            became direct and known const/pure.  */
+         if (is_gimple_call (stmt)
+             && old_call_flags != gimple_call_flags (stmt))
+           update_stmt_for_real (stmt);
+         else
+           update_stmt (stmt);
          if (vdef != gimple_vdef (stmt))
            VN_INFO (vdef)->valnum = vuse;
        }
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
index 2a40fdae0a27..827787cb72f9 100644
--- a/gcc/tree-ssa-scopedtables.c
+++ b/gcc/tree-ssa-scopedtables.c
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "options.h"
 #include "function.h"
 #include "basic-block.h"
 #include "tree.h"
@@ -33,7 +34,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-eh.h"
 #include "internal-fn.h"
 #include "tree-dfa.h"
-#include "options.h"
 #include "params.h"
 
 static bool hashable_expr_equal_p (const struct hashable_expr *,
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index f482ce197cd8..ddba1de98061 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -702,7 +702,14 @@ find_same_succ_bb (basic_block bb, same_succ **same_p)
   edge_iterator ei;
   edge e;
 
-  if (bb == NULL)
+  /* Ignore blocks without successors here.  Merging them potentially
+     merges syntactic scopes and destroys sharing of local variables because
+     the clobbers stopping the scope aren't reachable.
+     If the blocks do have successors the clobbers will be reachable and
+     the problem doesn't happen.
+
+     Those blocks can still be merged later by RTL cross jumping.  */
+  if (bb == NULL || !EDGE_COUNT (bb->succs))
     return;
   bitmap_set_bit (same->bbs, bb->index);
   FOR_EACH_EDGE (e, ei, bb->succs)
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index d197f99bdd23..13b9a0e5c298 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -479,7 +479,9 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, 
tree var)
       else
        gimple_debug_bind_reset_value (stmt);
 
-      update_stmt (stmt);
+      /* XXX nested debug expressions are hard for SSA operands.
+         Forcibly update the whole statement.  */
+      update_stmt_for_real (stmt);
     }
 }
 
@@ -2021,7 +2023,9 @@ execute_update_addresses_taken (void)
 
            if (gimple_references_memory_p (stmt)
                || is_gimple_debug (stmt))
-             update_stmt (stmt);
+             /* XXX maybe find better way of removing vops for statements
+                which now no longer refer to memory due to non-address-taken */
+             update_stmt_for_real (stmt);
 
            gsi_next (&gsi);
          }
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 5c2578f04659..ac7e883e4d43 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -4417,7 +4417,8 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple 
*pattern_stmt,
       pattern_stmt_info = new_stmt_vec_info (pattern_stmt, vinfo);
       set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
     }
-  gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt));
+  //gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt));
+  pattern_stmt->bb = gimple_bb (orig_stmt); // XXX
 
   STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt;
   STMT_VINFO_DEF_TYPE (pattern_stmt_info)
@@ -4440,7 +4441,8 @@ vect_mark_pattern_stmts (gimple *orig_stmt, gimple 
*pattern_stmt,
              def_stmt_info = new_stmt_vec_info (def_stmt, vinfo);
              set_vinfo_for_stmt (def_stmt, def_stmt_info);
            }
-         gimple_set_bb (def_stmt, gimple_bb (orig_stmt));
+         //gimple_set_bb (def_stmt, gimple_bb (orig_stmt));
+         def_stmt->bb = gimple_bb (orig_stmt); // XXX
          STMT_VINFO_RELATED_STMT (def_stmt_info) = orig_stmt;
          STMT_VINFO_DEF_TYPE (def_stmt_info) = vect_internal_def;
          if (STMT_VINFO_VECTYPE (def_stmt_info) == NULL_TREE)
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 1e8ccbce2af0..49716c09af2c 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -9758,7 +9758,10 @@ free_stmt_vec_info (gimple *stmt)
        {
          gimple_seq seq = STMT_VINFO_PATTERN_DEF_SEQ (patt_info);
          gimple *patt_stmt = STMT_VINFO_STMT (patt_info);
+         /* XXX This resets BB, but patt_stmt still is linked
+            in the imm-use lists of all operands */
          gimple_set_bb (patt_stmt, NULL);
+         delink_stmt_imm_use (patt_stmt);
          tree lhs = gimple_get_lhs (patt_stmt);
          if (lhs && TREE_CODE (lhs) == SSA_NAME)
            release_ssa_name (lhs);
@@ -9769,6 +9772,7 @@ free_stmt_vec_info (gimple *stmt)
                {
                  gimple *seq_stmt = gsi_stmt (si);
                  gimple_set_bb (seq_stmt, NULL);
+                 delink_stmt_imm_use (seq_stmt);
                  lhs = gimple_get_lhs (seq_stmt);
                  if (lhs && TREE_CODE (lhs) == SSA_NAME)
                    release_ssa_name (lhs);
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 16cdbd64f46d..d6ac350e4ca1 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -1336,7 +1336,8 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node 
*direct_call,
     }
   gimple_set_vdef (icall_stmt, NULL_TREE);
   gimple_set_vuse (icall_stmt, NULL_TREE);
-  update_stmt (icall_stmt);
+  /* XXX only needed to reset vops. */
+  update_stmt_for_real (icall_stmt);
   dcall_stmt = as_a <gcall *> (gimple_copy (icall_stmt));
   gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
   dflags = flags_from_decl_or_type (direct_call->decl);
@@ -1422,7 +1423,8 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node 
*direct_call,
                }
              gimple_set_vdef (iretbnd_stmt, NULL_TREE);
              gimple_set_vuse (iretbnd_stmt, NULL_TREE);
-             update_stmt (iretbnd_stmt);
+             /* XXX only needed to reset vops. */
+             update_stmt_for_real (iretbnd_stmt);
 
              result = gimple_call_lhs (iretbnd_stmt);
              phi = create_phi_node (result, join_bb);
@@ -1655,7 +1657,8 @@ gimple_stringop_fixed_value (gcall *vcall_stmt, tree 
icall_size, profile_probabi
     }
   gimple_set_vdef (vcall_stmt, NULL);
   gimple_set_vuse (vcall_stmt, NULL);
-  update_stmt (vcall_stmt);
+  /* XXX only needed to reset vops. */
+  update_stmt_for_real (vcall_stmt);
   icall_stmt = as_a <gcall *> (gimple_copy (vcall_stmt));
   gimple_call_set_arg (icall_stmt, size_arg,
                       fold_convert (optype, icall_size));

Reply via email to