https://gcc.gnu.org/g:5d30d4f15e836908c16d1f3ef71aaed0bfb7793e

commit 5d30d4f15e836908c16d1f3ef71aaed0bfb7793e
Author: Michael Matz <[email protected]>
Date:   Sun Mar 4 05:48:56 2018 +0100

    update-stmt: add_ssa_op pre-removal
    
    special-case the add_ssa_op code for gimple_set_vuse.  Now
    add_ssa_op isn't really needed anymore, make exchange_complex_op
    reuse a single useop entry if possible.  Leaves in the code
    using add_ssa_op for simple exchanges in under -ftry-patch=2.
    perf stat measurements don't show any speed advantage either way
    (with release checking and compiler built with -O2).
    
    make check is clean (following known-to-me fails):
    FAIL: gcc.dg/20050503-1.c scan-assembler-not call
    FAIL: gcc.dg/torture/pr68264.c   -O0  execution test
    FAIL: gcc.dg/torture/pr68264.c   -Os  execution test
    FAIL: gcc.target/i386/mvc9.c (test for excess errors)
    FAIL: g++.dg/tls/thread_local-order2.C  -std=c++11 execution test
    FAIL: g++.dg/tls/thread_local-order2.C  -std=c++14 execution test
    FAIL: g++.dg/torture/pr67600.C   -O2 -flto -fuse-linker-plugin
    -fno-fat-lto-objects  (test for excess errors)

Diff:
---
 gcc/gimple.c            |  1 +
 gcc/tree-ssa-operands.c | 90 ++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 75 insertions(+), 16 deletions(-)

diff --git a/gcc/gimple.c b/gcc/gimple.c
index e8811a58ddc8..ccc35adaf82a 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1677,6 +1677,7 @@ gimple_assign_set_rhs_with_ops (gimple_stmt_iterator 
*gsi, enum tree_code code,
       gimple *new_stmt = gimple_alloc (gimple_code (stmt), new_rhs_ops + 1);
       memcpy (new_stmt, stmt, gimple_size (gimple_code (stmt)));
       gimple_init_singleton (new_stmt);
+      gimple_set_use_ops (new_stmt, NULL);
       gsi_replace (gsi, new_stmt, false);
       stmt = new_stmt;
 
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index cff247957197..dedf1baf2d68 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -1237,7 +1237,7 @@ diddle_vops (gimple *stmt, int oldvop, int newvop, 
unsigned nop)
 static int
 add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags)
 {
-  use_optype_p *puse;
+  use_optype_p *puse, use;
   int was_vop = 0, newvop;
   if (*pop && SSA_VAR_P (*pop))
     {
@@ -1247,9 +1247,10 @@ add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned 
nop, int flags)
       if (!(flags & opf_no_vops)
          && !is_gimple_reg (*pop) && !virtual_operand_p (*pop))
        was_vop = BF_VUSE | ((flags & opf_def) ? BF_VDEF : 0);
+      use = puse ? *puse : NULL;
     }
   else
-    puse = NULL;
+    use = NULL;
 
   if (nop == 1 && gimple_code (stmt) == GIMPLE_CALL)
     was_vop = get_call_vop_flags (stmt);
@@ -1265,13 +1266,13 @@ add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned 
nop, int flags)
          if (DECL_P (val) && !virtual_operand_p (val))
            cfun->gimple_df->ssa_renaming_needed = 1;
          if (flags & opf_def)
-           gcc_assert (!puse);
+           gcc_assert (!use);
          else
            {
-             if (!puse)
+             if (!use)
                prepend_use_op (stmt, pop);
              else
-               link_imm_use_stmt (&((*puse)->use_ptr), *pop, stmt);
+               link_imm_use_stmt (&(use->use_ptr), *pop, stmt);
            }
        }
       else
@@ -1284,9 +1285,8 @@ add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned 
nop, int flags)
   else
     {
       gcc_assert (!val || is_gimple_min_invariant (val));
-      if (puse)
+      if (use)
        {
-         use_optype_p use = *puse;
          *puse = use->next;
          use->next = gimple_ssa_operands (cfun)->free_uses;
          gimple_ssa_operands (cfun)->free_uses = use;
@@ -1315,7 +1315,7 @@ ensure_vop (gimple *stmt, int flags)
          gimple_set_vdef (stmt, gimple_vop (cfun));
     }
   if (!gimple_vuse (stmt))
-    add_ssa_op (stmt, gimple_vuse_ptr (stmt), gimple_vop (cfun), -1, flags);
+    gimple_set_vuse (stmt, gimple_vop (cfun));
   if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) != SSA_NAME)
     {
       cfun->gimple_df->rename_vops = 1;
@@ -1334,6 +1334,7 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, 
unsigned nop, int flags)
   bool was_volatile;
   unsigned i;
   int oldvop, newvop;
+  use_optype_p *puse = NULL, use = NULL;
 
   start_ssa_stmt_operands ();
   get_expr_operands (stmt, gimple_op_ptr (stmt, nop), flags);
@@ -1343,18 +1344,18 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, 
unsigned nop, int flags)
   oldvop = build_flags & (BF_VDEF | BF_VUSE);
 
   /* Remove all use ops for things in op[nop].  */
-  for (i = 0; i < build_uses.length (); i++)
+  for (i = build_uses.length (); i-- > 0;)
     {
       tree *op = build_uses[i];
-      use_optype_p *puse = find_delink_use_op (stmt, op);
+      puse = find_delink_use_op (stmt, op);
+      use = puse ? *puse : NULL;
       if (!puse)
        /* Normally we should have found the old useop cache.  But debug
           statements might change from SOURCE_BIND (without opcache)
           to DEBUG_BIND (with opcache), so accept that here.  */
        gcc_assert(is_gimple_debug (stmt));
-      else
+      else if (i)
        {
-         use_optype_p use = *puse;
          *puse = use->next;
          use->next = gimple_ssa_operands (cfun)->free_uses;
          gimple_ssa_operands (cfun)->free_uses = use;
@@ -1371,6 +1372,28 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, 
unsigned nop, int flags)
     maybe_add_call_vops (as_a <gcall *> (stmt));
   newvop = build_flags & (BF_VDEF | BF_VUSE);
 
+  /* If we want to reuse an useop, do it now before diddle_vops,
+     as that one might free useops, including the one where *puse
+     points into.  This is useless work if it turns out that
+     we need to revisit all operands, but that doesn't occur very
+     often.  */
+  i = 0;
+  if (use)
+    {
+      if (i < build_uses.length ())
+       {
+         use->use_ptr.use = build_uses[i];
+         link_imm_use_stmt (&(use->use_ptr), *build_uses[i], stmt);
+         i++;
+       }
+      else
+       {
+         *puse = use->next;
+         use->next = gimple_ssa_operands (cfun)->free_uses;
+         gimple_ssa_operands (cfun)->free_uses = use;
+       }
+    }
+
   /* If the op was volatile and now isn't we need to recheck everything.  */
   if (was_volatile && !(build_flags & BF_VOLATILE))
     {
@@ -1384,10 +1407,10 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, 
unsigned nop, int flags)
       return 1;
     }
 
-  for (i = 0; i < build_uses.length (); i++)
+  for (; i < build_uses.length (); i++)
     {
       tree *op = build_uses[i];
-      use_optype_p *puse = find_delink_use_op (stmt, op);
+      puse = find_delink_use_op (stmt, op);
       /* All ops should be new (or removed above), otherwise
          we'd create strange sharing.  */
       gcc_assert (!puse);
@@ -1413,7 +1436,42 @@ gimple_set_vuse (gimple *stmt, tree vuse)
   if (!flag_try_patch || !stmt->bb || !ssa_operands_active (cfun))
     mem_ops_stmt->vuse = vuse;
   else
-    add_ssa_op (stmt, &mem_ops_stmt->vuse, vuse, -1, opf_use);
+    {
+      //add_ssa_op (stmt, &mem_ops_stmt->vuse, vuse, -1, opf_use);
+      tree *pop = &mem_ops_stmt->vuse;
+
+      use_optype_p *puse, use;
+      if (*pop && gimple_use_ops (stmt))
+       {
+         gcc_assert (SSA_VAR_P (*pop));
+         puse = find_delink_use_op (stmt, pop);
+         gcc_assert (&(dyn_cast <gimple_statement_with_ops *> (stmt))->use_ops 
== puse);
+         use = *puse;
+       }
+      else
+       {
+         gcc_assert (!gimple_use_ops (stmt)
+                     || gimple_use_ops (stmt)->use_ptr.use != pop);
+         use = NULL;
+       }
+
+      *pop = vuse;
+
+      if (vuse)
+       {
+         gcc_assert (SSA_VAR_P (vuse) && virtual_operand_p (vuse));
+         if (!use)
+           prepend_use_op (stmt, pop);
+         else
+           link_imm_use_stmt (&(use->use_ptr), *pop, stmt);
+       }
+      else if (use)
+       {
+         *puse = use->next;
+         use->next = gimple_ssa_operands (cfun)->free_uses;
+         gimple_ssa_operands (cfun)->free_uses = use;
+       }
+    }
 }
 
 static void
@@ -1434,7 +1492,7 @@ do_change_in_op (gimple *gs, tree *op_ptr, tree *pop, 
tree val)
        flags = opf_def;
       if (gimple_code (gs) == GIMPLE_DEBUG)
        flags |= opf_no_vops;
-      if (1 && pop == op_ptr
+      if (flag_try_patch == 2 && pop == op_ptr
          && (!old || TREE_CODE (old) == SSA_NAME || is_gimple_val (old))
          && (!val || is_gimple_val (val)))
        {

Reply via email to