This fixes PR52548, we were not flow-sensitively pruning EXP_GEN
sets during antic-in computation.  Fixed by simply pruning EXP_GEN
at generation time.

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

Richard.

2012-03-22  Richard Guenther  <rguent...@suse.de>

        PR tree-optimization/52548
        * tree-ssa-pre.c (valid_in_sets): Remove handling of invalidation
        because of clobbers.
        (prune_clobbered_mems): New function.
        (compute_antic_aux): Use it to prune ANTIC_OUT.
        (compute_partial_antic_aux): Use it to prune PA_IN.
        (compute_avail): Only insert expressions into EXP_GEN that
        are not invalidated when translated up to the beginning of
        the block.

        * gcc.dg/tree-ssa/ssa-pre-29.c: New testcase.

Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-29.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-29.c  (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-29.c  (revision 0)
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-pre-details" } */
+ 
+ int flag, hoist, y, z;
+ 
+ void
+ foo (void)
+ {
+   if (flag)
+     y = hoist + 4;
+   else
+     flag = 888;
+   z = hoist + 4;
+   bark ();
+ }
+ 
+ /* We should see the partial redundancy of hoist + 4, not being confused
+    about bark () possibly clobbering hoist.  */
+ 
+ /* { dg-final { scan-tree-dump "Replaced hoist" "pre" } } */
+ /* { dg-final { cleanup-tree-dump "pre" } } */
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c  (revision 185680)
--- gcc/tree-ssa-pre.c  (working copy)
*************** valid_in_sets (bitmap_set_t set1, bitmap
*** 2123,2138 ****
            if (!vro_valid_in_sets (set1, set2, vro))
              return false;
          }
!       if (ref->vuse)
!         {
!           gimple def_stmt = SSA_NAME_DEF_STMT (ref->vuse);
!           if (!gimple_nop_p (def_stmt)
!               && gimple_bb (def_stmt) != block
!               && !dominated_by_p (CDI_DOMINATORS,
!                                   block, gimple_bb (def_stmt)))
!             return false;
!         }
!       return !value_dies_in_block_x (expr, block);
        }
      default:
        gcc_unreachable ();
--- 2123,2129 ----
            if (!vro_valid_in_sets (set1, set2, vro))
              return false;
          }
!       return true;
        }
      default:
        gcc_unreachable ();
*************** clean (bitmap_set_t set, basic_block blo
*** 2179,2184 ****
--- 2170,2207 ----
    VEC_free (pre_expr, heap, exprs);
  }
  
+ /* Clean the set of expressions that are no longer valid in SET because
+    they are clobbered in BLOCK.  */
+ 
+ static void
+ prune_clobbered_mems (bitmap_set_t set, basic_block block)
+ {
+   VEC (pre_expr, heap) *exprs = sorted_array_from_bitmap_set (set);
+   pre_expr expr;
+   int i;
+ 
+   FOR_EACH_VEC_ELT (pre_expr, exprs, i, expr)
+     {
+       vn_reference_t ref;
+       if (expr->kind != REFERENCE)
+       continue;
+ 
+       ref = PRE_EXPR_REFERENCE (expr);
+       if (ref->vuse)
+       {
+         gimple def_stmt = SSA_NAME_DEF_STMT (ref->vuse);
+         if (!gimple_nop_p (def_stmt)
+             && ((gimple_bb (def_stmt) != block
+                  && !dominated_by_p (CDI_DOMINATORS,
+                                      block, gimple_bb (def_stmt)))
+                 || (gimple_bb (def_stmt) == block
+                     && value_dies_in_block_x (expr, block))))
+           bitmap_remove_from_set (set, expr);
+       }
+     }
+   VEC_free (pre_expr, heap, exprs);
+ }
+ 
  static sbitmap has_abnormal_preds;
  
  /* List of blocks that may have changed during ANTIC computation and
*************** compute_antic_aux (basic_block block, bo
*** 2320,2325 ****
--- 2343,2352 ----
        VEC_free (basic_block, heap, worklist);
      }
  
+   /* Prune expressions that are clobbered in block and thus become
+      invalid if translated from ANTIC_OUT to ANTIC_IN.  */
+   prune_clobbered_mems (ANTIC_OUT, block);
+ 
    /* Generate ANTIC_OUT - TMP_GEN.  */
    S = bitmap_set_subtract (ANTIC_OUT, TMP_GEN (block));
  
*************** compute_partial_antic_aux (basic_block b
*** 2474,2479 ****
--- 2501,2510 ----
        VEC_free (basic_block, heap, worklist);
      }
  
+   /* Prune expressions that are clobbered in block and thus become
+      invalid if translated from PA_OUT to PA_IN.  */
+   prune_clobbered_mems (PA_OUT, block);
+ 
    /* PA_IN starts with PA_OUT - TMP_GEN.
       Then we subtract things from ANTIC_IN.  */
    PA_IN (block) = bitmap_set_subtract (PA_OUT, TMP_GEN (block));
*************** compute_avail (void)
*** 4027,4041 ****
                    if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
                      add_to_exp_gen (block, vro->op2);
                  }
!               result = (pre_expr) pool_alloc (pre_expr_pool);
!               result->kind = REFERENCE;
!               result->id = 0;
!               PRE_EXPR_REFERENCE (result) = ref;
! 
!               get_or_alloc_expression_id (result);
!               add_to_value (get_expr_value_id (result), result);
!               if (!in_fre)
!                 bitmap_value_insert_into_set (EXP_GEN (block), result);
                continue;
              }
  
--- 4058,4083 ----
                    if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
                      add_to_exp_gen (block, vro->op2);
                  }
! 
!               /* If the value of the call is not invalidated in
!                  this block until it is computed, add the expression
!                  to EXP_GEN.  */
!               if (!gimple_vuse (stmt)
!                   || gimple_code
!                        (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI
!                   || gimple_bb (SSA_NAME_DEF_STMT
!                                   (gimple_vuse (stmt))) != block)
!                 {
!                   result = (pre_expr) pool_alloc (pre_expr_pool);
!                   result->kind = REFERENCE;
!                   result->id = 0;
!                   PRE_EXPR_REFERENCE (result) = ref;
! 
!                   get_or_alloc_expression_id (result);
!                   add_to_value (get_expr_value_id (result), result);
!                   if (!in_fre)
!                     bitmap_value_insert_into_set (EXP_GEN (block), result);
!                 }
                continue;
              }
  
*************** compute_avail (void)
*** 4095,4100 ****
--- 4137,4168 ----
                          if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
                            add_to_exp_gen (block, vro->op2);
                        }
+ 
+                     /* If the value of the reference is not invalidated in
+                        this block until it is computed, add the expression
+                        to EXP_GEN.  */
+                     if (gimple_vuse (stmt))
+                       {
+                         gimple def_stmt;
+                         bool ok = true;
+                         def_stmt = SSA_NAME_DEF_STMT (gimple_vuse (stmt));
+                         while (!gimple_nop_p (def_stmt)
+                                && gimple_code (def_stmt) != GIMPLE_PHI
+                                && gimple_bb (def_stmt) == block)
+                           {
+                             if (stmt_may_clobber_ref_p
+                                   (def_stmt, gimple_assign_rhs1 (stmt)))
+                               {
+                                 ok = false;
+                                 break;
+                               }
+                             def_stmt
+                               = SSA_NAME_DEF_STMT (gimple_vuse (def_stmt));
+                           }
+                         if (!ok)
+                           continue;
+                       }
+ 
                      result = (pre_expr) pool_alloc (pre_expr_pool);
                      result->kind = REFERENCE;
                      result->id = 0;

Reply via email to