------- Comment #31 from rakdver at atrey dot karlin dot mff dot cuni dot cz  
2006-04-04 10:20 -------
Subject: Re:  [4.2 Regression] Repeated SSA update during loop header copying

> Zdenek: are you using walk_data->interesting_blocks to not visit PHI nodes on
> non-interesting blocks?

No, I am keeping lists of interesting phi nodes in each basic block (see
the patch below -- without the time measurement code, of course).  Using
just interesting_blocks might be simpler, I will try how much that
helps.

Index: tree-into-ssa.c
===================================================================
*** tree-into-ssa.c     (revision 112625)
--- tree-into-ssa.c     (working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 47,52 ****
--- 47,53 ----
  #include "domwalk.h"
  #include "ggc.h"
  #include "params.h"
+ #include "toplev.h"

  /* This file builds the SSA form for a function as described in:
     R. Cytron, J. Ferrante, B. Rosen, M. Wegman, and K. Zadeck. Efficiently
*************** get_default_def_for (tree sym)
*** 777,782 ****
--- 778,800 ----
    return ddef;
  }

+ /* Marks phi node PHI in basic block BB for rewrite.  */
+ 
+ static void
+ mark_phi_for_rewrite (basic_block bb, tree phi)
+ {
+   VEC (tree, heap) *phis_to_rewrite;
+ 
+   if (REWRITE_THIS_STMT (phi))
+     return;
+ 
+   phis_to_rewrite = bb->aux;
+   if (!phis_to_rewrite)
+     phis_to_rewrite = VEC_alloc (tree, heap, 10);
+   REWRITE_THIS_STMT (phi) = 1;
+   VEC_safe_push (tree, heap, phis_to_rewrite, phi);
+   bb->aux = phis_to_rewrite;
+ }

  /* Insert PHI nodes for variable VAR using the iterated dominance
     frontier given in PHI_INSERTION_POINTS.  If UPDATE_P is true, this
*************** insert_phi_nodes_for (tree var, bitmap p
*** 846,852 ****

        /* Mark this PHI node as interesting for update_ssa.  */
        REGISTER_DEFS_IN_THIS_STMT (phi) = 1;
!       REWRITE_THIS_STMT (phi) = 1;
      }
  }

--- 864,870 ----

        /* Mark this PHI node as interesting for update_ssa.  */
        REGISTER_DEFS_IN_THIS_STMT (phi) = 1;
!       mark_phi_for_rewrite (bb, phi);
      }
  }

*************** replace_use (use_operand_p use_p, tree u
*** 1497,1502 ****
--- 1515,1522 ----
      SET_USE (use_p, rdef);
  }

+ unsigned long upi_cas_useful, upi_cas_total;
+ unsigned upi_calls, upi_did;

  /* Visit all the successor blocks of BB looking for PHI nodes.  For
     every PHI node found, check if any of its arguments is in
*************** rewrite_update_phi_arguments (struct dom
*** 1509,1527 ****
  {
    edge e;
    edge_iterator ei;

    FOR_EACH_EDGE (e, ei, bb->succs)
      {
        tree phi;

!       for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
        {
          tree arg;
          use_operand_p arg_p;

!         /* Skip PHI nodes that are not marked for rewrite.  */
!         if (!REWRITE_THIS_STMT (phi))
!           continue;

          arg_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
          arg = USE_FROM_PTR (arg_p);
--- 1529,1556 ----
  {
    edge e;
    edge_iterator ei;
+   unsigned i;
+   unsigned ohi, olo;
+   unsigned long long cas;
+   bool did = false;
+ 
+   rdtsc(ohi, olo);
+   upi_calls++;

    FOR_EACH_EDGE (e, ei, bb->succs)
      {
        tree phi;
+       VEC (tree, heap) *phis_to_rewrite = e->dest->aux;

!       if (!phis_to_rewrite)
!       continue;
! 
!       for (i = 0; VEC_iterate (tree, phis_to_rewrite, i, phi); i++)
        {
          tree arg;
          use_operand_p arg_p;

!         gcc_assert (REWRITE_THIS_STMT (phi));

          arg_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
          arg = USE_FROM_PTR (arg_p);
*************** rewrite_update_phi_arguments (struct dom
*** 1534,1539 ****
--- 1563,1569 ----
              /* When updating a PHI node for a recently introduced
                 symbol we may find NULL arguments.  That's why we
                 take the symbol from the LHS of the PHI node.  */
+             did = true;
              replace_use (arg_p, SSA_NAME_VAR (PHI_RESULT (phi)));
            }
          else
*************** rewrite_update_phi_arguments (struct dom
*** 1541,1555 ****
              tree sym = DECL_P (arg) ? arg : SSA_NAME_VAR (arg);

              if (symbol_marked_for_renaming (sym))
!               replace_use (arg_p, sym);
              else if (is_old_name (arg))
!               replace_use (arg_p, arg);
            }

          if (e->flags & EDGE_ABNORMAL)
            SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (arg_p)) = 1;
        }
      }
  }


--- 1571,1599 ----
              tree sym = DECL_P (arg) ? arg : SSA_NAME_VAR (arg);

              if (symbol_marked_for_renaming (sym))
!               {
!                 did = true;
!                 replace_use (arg_p, sym);
!               }
              else if (is_old_name (arg))
!               {
!                 did = true;
!                 replace_use (arg_p, arg);
!               }
            }

          if (e->flags & EDGE_ABNORMAL)
            SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (arg_p)) = 1;
        }
      }
+ 
+   cas = ttm_stop (ohi, olo);
+   if (did)
+     {
+       upi_did++;
+       upi_cas_useful += cas;
+     }
+   upi_cas_total += cas;
  }


*************** static inline void
*** 1838,1844 ****
  mark_use_interesting (tree var, tree stmt, basic_block bb, bitmap blocks,
                      bool insert_phi_p)
  {
!   REWRITE_THIS_STMT (stmt) = 1;
    bitmap_set_bit (blocks, bb->index);

    /* If VAR has not been defined in BB, then it is live-on-entry
--- 1882,1891 ----
  mark_use_interesting (tree var, tree stmt, basic_block bb, bitmap blocks,
                      bool insert_phi_p)
  {
!   if (TREE_CODE (stmt) == PHI_NODE)
!     mark_phi_for_rewrite (bb_for_stmt (stmt), stmt);
!   else
!     REWRITE_THIS_STMT (stmt) = 1;
    bitmap_set_bit (blocks, bb->index);

    /* If VAR has not been defined in BB, then it is live-on-entry
*************** update_ssa (unsigned update_flags)
*** 2679,2684 ****
--- 2726,2732 ----
        block_stmt_iterator si;
        tree phi;

+       gcc_assert (bb->aux == NULL);
        for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        {
          REWRITE_THIS_STMT (phi) = 0;
*************** update_ssa (unsigned update_flags)
*** 2835,2840 ****
--- 2883,2897 ----

    /* Free allocated memory.  */
  done:
+   FOR_EACH_BB (bb)
+     {
+       VEC (tree, heap) *phis_to_rewrite = bb->aux;
+       if (!phis_to_rewrite)
+       continue;
+ 
+       VEC_free (tree, heap, phis_to_rewrite);
+       bb->aux = NULL;
+     }
    BITMAP_FREE (blocks);
    delete_update_ssa ();

Index: tree-ssa-loop-ch.c
===================================================================
*** tree-ssa-loop-ch.c  (revision 112625)
--- tree-ssa-loop-ch.c  (working copy)
*************** copy_loop_headers (void)
*** 145,150 ****
--- 145,151 ----
    copied_bbs = XNEWVEC (basic_block, n_basic_blocks);
    bbs_size = n_basic_blocks;

+   printf ("%d %d\n", loops->num, n_basic_blocks);
    for (i = 1; i < loops->num; i++)
      {
        /* Copy at most 20 insns.  */
Index: toplev.h
===================================================================
*** toplev.h    (revision 112625)
--- toplev.h    (working copy)
*************** exact_log2 (unsigned HOST_WIDE_INT x)
*** 189,192 ****
--- 189,206 ----
  extern const char *get_src_pwd               (void);
  extern bool set_src_pwd                      (const char *);

+ #define rdtsc(hi,lo) __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi))
+ 
+ static inline unsigned long ttm_stop(unsigned ohi, unsigned olo)
+ {
+   unsigned nhi, nlo;
+   unsigned long t1, t2;
+ 
+   rdtsc(nhi, nlo);
+ 
+   t1 = (((unsigned long) ohi) << 32) | olo;
+   t2 = (((unsigned long) nhi) << 32) | nlo;
+ 
+   return t2 - t1;
+ }
  #endif /* ! GCC_TOPLEV_H */
Index: main.c
===================================================================
*** main.c      (revision 112625)
--- main.c      (working copy)
*************** Software Foundation, 51 Franklin Street,
*** 25,30 ****
--- 25,33 ----

  int main (int argc, char **argv);

+ extern unsigned long upi_cas_useful, upi_cas_total;
+ extern unsigned upi_calls, upi_did;
+ 
  /* We define main() to call toplev_main(), which is defined in toplev.c.
     We do this in a separate file in order to allow the language front-end
     to define a different main(), if it so desires.  */
*************** int main (int argc, char **argv);
*** 32,36 ****
  int
  main (int argc, char **argv)
  {
!   return toplev_main (argc, (const char **) argv);
  }
--- 35,47 ----
  int
  main (int argc, char **argv)
  {
!   int ret;
!   unsigned ohi, olo;
!   unsigned long total;
! 
!   rdtsc (ohi, olo);
!   ret = toplev_main (argc, (const char **) argv);
!   total = ttm_stop (ohi, olo);
!   printf ("%lu time (%u calls -- %u useful, %lu useful time), total time
%lu\n", upi_cas_total, upi_calls, upi_did, upi_cas_useful, total);
!   return ret;
  }


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26830

Reply via email to