This fixes PR55107 - the way we dealt with fully redundant values
found by PRE phi-translation breaks existing SETs, so don't special
case it in a hacky way but instead create a simple assignment.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2012-12-10  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/55107
        * tree-ssa-pre.c (struct pre_stats): Remove constified field.
        (bitmap_set_replace_value): Add gcc_unreachable.
        (do_regular_insertion): Re-write all_same handling.  Insert
        an assignment instead of a PHI in this case.
        (eliminate_bb): Record availability also for SSA names defined
        by a constant.
        (do_pre): Do not record constified events.
        (execute_fre): Likewise.

        * gcc.dg/torture/pr55107.c: New testcase.
        * gcc.dg/tree-ssa/ssa-pre-5.c: Adjust.

Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c  (revision 194345)
--- gcc/tree-ssa-pre.c  (working copy)
*************** static struct
*** 446,455 ****
  
    /* The number of new PHI nodes added by PRE.  */
    int phis;
- 
-   /* The number of values found constant.  */
-   int constified;
- 
  } pre_stats;
  
  static bool do_partial_partial;
--- 446,451 ----
*************** bitmap_set_replace_value (bitmap_set_t s
*** 867,872 ****
--- 863,870 ----
          return;
        }
      }
+ 
+   gcc_unreachable ();
  }
  
  /* Return true if two bitmap sets are equal.  */
*************** do_regular_insertion (basic_block block,
*** 3325,3331 ****
  
    FOR_EACH_VEC_ELT (exprs, i, expr)
      {
!       if (expr->kind != NAME)
        {
          unsigned int val;
          bool by_some = false;
--- 3323,3330 ----
  
    FOR_EACH_VEC_ELT (exprs, i, expr)
      {
!       if (expr->kind == NARY
!         || expr->kind == REFERENCE)
        {
          unsigned int val;
          bool by_some = false;
*************** do_regular_insertion (basic_block block,
*** 3435,3469 ****
          /* If all edges produce the same value and that value is
             an invariant, then the PHI has the same value on all
             edges.  Note this.  */
!         else if (!cant_insert && all_same && eprime
!                  && (edoubleprime->kind == CONSTANT
!                      || edoubleprime->kind == NAME)
!                  && !value_id_constant_p (val))
            {
!             unsigned int j;
!             bitmap_iterator bi;
!             bitmap exprset = value_expressions[val];
! 
!             unsigned int new_val = get_expr_value_id (edoubleprime);
!             EXECUTE_IF_SET_IN_BITMAP (exprset, 0, j, bi)
!               {
!                 pre_expr expr = expression_for_id (j);
  
!                 if (expr->kind == NAME)
!                   {
!                     vn_ssa_aux_t info = VN_INFO (PRE_EXPR_NAME (expr));
!                     /* Just reset the value id and valnum so it is
!                        the same as the constant we have discovered.  */
!                     if (edoubleprime->kind == CONSTANT)
!                       {
!                         info->valnum = PRE_EXPR_CONSTANT (edoubleprime);
!                         pre_stats.constified++;
!                       }
!                     else
!                       info->valnum = VN_INFO (PRE_EXPR_NAME 
(edoubleprime))->valnum;
!                     info->value_id = new_val;
!                   }
!               }
            }
        }
      }
--- 3434,3461 ----
          /* If all edges produce the same value and that value is
             an invariant, then the PHI has the same value on all
             edges.  Note this.  */
!         else if (!cant_insert && all_same)
            {
!             gcc_assert (edoubleprime->kind == CONSTANT
!                         || edoubleprime->kind == NAME);
  
!             tree temp = make_temp_ssa_name (get_expr_type (expr),
!                                             NULL, "pretmp");
!             gimple assign = gimple_build_assign (temp,
!                                                  edoubleprime->kind == 
CONSTANT ? PRE_EXPR_CONSTANT (edoubleprime) : PRE_EXPR_NAME (edoubleprime));
!             gimple_stmt_iterator gsi = gsi_after_labels (block);
!             gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
! 
!             gimple_set_plf (assign, NECESSARY, false);
!             VN_INFO_GET (temp)->value_id = val;
!             VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
!             if (VN_INFO (temp)->valnum == NULL_TREE)
!               VN_INFO (temp)->valnum = temp;
!             bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp));
!             pre_expr newe = get_or_alloc_expr_for_name (temp);
!             add_to_value (val, newe);
!             bitmap_value_replace_in_set (AVAIL_OUT (block), newe);
!             bitmap_insert_into_set (NEW_SETS (block), newe);
            }
        }
      }
*************** do_partial_partial_insertion (basic_bloc
*** 3495,3501 ****
  
    FOR_EACH_VEC_ELT (exprs, i, expr)
      {
!       if (expr->kind != NAME)
        {
          unsigned int val;
          bool by_all = true;
--- 3487,3494 ----
  
    FOR_EACH_VEC_ELT (exprs, i, expr)
      {
!       if (expr->kind == NARY
!         || expr->kind == REFERENCE)
        {
          unsigned int val;
          bool by_all = true;
*************** eliminate_bb (dom_walk_data *, basic_blo
*** 4142,4167 ****
  
        /* Lookup the RHS of the expression, see if we have an
         available computation for it.  If so, replace the RHS with
!        the available computation.
! 
!        See PR43491.
!        We don't replace global register variable when it is a the RHS of
!        a single assign. We do replace local register variable since gcc
!        does not guarantee local variable will be allocated in register.  */
        if (gimple_has_lhs (stmt)
          && TREE_CODE (lhs) == SSA_NAME
-         && !gimple_assign_ssa_name_copy_p (stmt)
-         && (!gimple_assign_single_p (stmt)
-             || (!is_gimple_min_invariant (rhs)
-                 && (gimple_assign_rhs_code (stmt) != VAR_DECL
-                     || !is_global_var (rhs)
-                     || !DECL_HARD_REGISTER (rhs))))
          && !gimple_has_volatile_ops  (stmt))
        {
          tree sprime;
          gimple orig_stmt = stmt;
  
          sprime = eliminate_avail (lhs);
          if (!sprime)
            {
              /* If there is no existing usable leader but SCCVN thinks
--- 4135,4166 ----
  
        /* Lookup the RHS of the expression, see if we have an
         available computation for it.  If so, replace the RHS with
!        the available computation.  */
        if (gimple_has_lhs (stmt)
          && TREE_CODE (lhs) == SSA_NAME
          && !gimple_has_volatile_ops  (stmt))
        {
          tree sprime;
          gimple orig_stmt = stmt;
  
          sprime = eliminate_avail (lhs);
+         /* If there is no usable leader mark lhs as leader for its value.  */
+         if (!sprime)
+           eliminate_push_avail (lhs);
+ 
+         /* See PR43491.  Do not replace a global register variable when
+            it is a the RHS of an assignment.  Do replace local register
+            variables since gcc does not guarantee a local variable will
+            be allocated in register.
+            Do not perform copy propagation or undo constant propagation.  */
+         if (gimple_assign_single_p (stmt)
+             && (TREE_CODE (rhs) == SSA_NAME
+                 || is_gimple_min_invariant (rhs)
+                 || (TREE_CODE (rhs) == VAR_DECL
+                     && is_global_var (rhs)
+                     && DECL_HARD_REGISTER (rhs))))
+           continue;
+ 
          if (!sprime)
            {
              /* If there is no existing usable leader but SCCVN thinks
*************** eliminate_bb (dom_walk_data *, basic_blo
*** 4208,4217 ****
              continue;
            }
  
-         /* If there is no usable leader mark lhs as leader for its value.  */
-         if (!sprime)
-           eliminate_push_avail (lhs);
- 
          if (sprime
              && sprime != lhs
              && (rhs == NULL_TREE
--- 4207,4212 ----
*************** do_pre (void)
*** 4742,4748 ****
    statistics_counter_event (cfun, "PA inserted", pre_stats.pa_insert);
    statistics_counter_event (cfun, "New PHIs", pre_stats.phis);
    statistics_counter_event (cfun, "Eliminated", pre_stats.eliminations);
-   statistics_counter_event (cfun, "Constified", pre_stats.constified);
  
    clear_expression_ids ();
    remove_dead_inserted_code ();
--- 4737,4742 ----
*************** execute_fre (void)
*** 4823,4829 ****
  
    statistics_counter_event (cfun, "Insertions", pre_stats.insertions);
    statistics_counter_event (cfun, "Eliminated", pre_stats.eliminations);
-   statistics_counter_event (cfun, "Constified", pre_stats.constified);
  
    return todo;
  }
--- 4817,4822 ----
Index: gcc/testsuite/gcc.dg/torture/pr55107.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55107.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55107.c      (working copy)
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do compile } */
+ 
+ typedef unsigned short uint16_t;
+ 
+ uint16_t a, b;
+ 
+ uint16_t f(void)
+ {
+   int c, **p;
+   short d = 2, e = 4;
+ 
+   for (;; b++)
+     {
+       int *j, k = 0;
+ 
+       for (; *j; j++)
+       {
+         for(; c; c++)
+           for(; k < 1; k++)
+             {
+               short *f = &d;
+ 
+               if(b)
+                 return *f;
+             }
+       }
+ 
+       if(!c)
+       d *= e;
+ 
+       ((a = d) ? b = 0 : (**p ? : 1) != (d != 1 ? : (a = 0))) != (k ? a : 0)
+         < (a *= c = k) && (**p = 0);
+     }
+ }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c   (revision 194345)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c   (working copy)
*************** foo (int i)
*** 12,16 ****
  }
  /* We should detect that a+b is the same along both edges, and replace it with
     5  */
! /* { dg-final { scan-tree-dump-times "Constified: 1" 1 "pre"} } */
  /* { dg-final { cleanup-tree-dump "pre" } } */
--- 12,17 ----
  }
  /* We should detect that a+b is the same along both edges, and replace it with
     5  */
! /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
! /* { dg-final { scan-tree-dump-times "Insertions" 0 "pre"} } */
  /* { dg-final { cleanup-tree-dump "pre" } } */

Reply via email to