This fixes PR67889.

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

Richard.

2015-10-09  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/67891
        * gimple-match.h (gimple_simplified_result_is_gimple_val):
        New helper.
        (gimple_resimplify1): Declare.
        (gimple_resimplify2): Likewise.
        (gimple_resimplify3): Likewise.
        * gimple-match-head.c (gimple_resimplify1): Export.
        (gimple_resimplify2): Likewise.
        (gimple_resimplify3): Likewise.
        (maybe_push_res_to_seq): Use gimple_simplified_result_is_gimple_val.
        * gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise.
        * tree-ssa-sccvn.c (visit_reference_op_load): Use gimple_resimplify1
        to avoid creating stmts without VN info.

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

Index: gcc/gimple-match.h
===================================================================
*** gcc/gimple-match.h  (revision 228594)
--- gcc/gimple-match.h  (working copy)
*************** private:
*** 40,49 ****
--- 40,67 ----
    int rep;
  };
  
+ /* Return whether OPS[0] with CODE is a non-expression result and
+    a gimple value.  */
+ 
+ inline bool
+ gimple_simplified_result_is_gimple_val (code_helper code, tree *ops)
+ {
+   return (code.is_tree_code ()
+         && (TREE_CODE_LENGTH ((tree_code) code) == 0
+             || ((tree_code) code) == ADDR_EXPR)
+         && is_gimple_val (ops[0]));
+ }
+ 
  extern tree (*mprts_hook) (code_helper, tree, tree *);
  
  bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *,
                      tree (*)(tree), tree (*)(tree));
+ bool gimple_resimplify1 (gimple_seq *, code_helper *, tree, tree *,
+                        tree (*)(tree));
+ bool gimple_resimplify2 (gimple_seq *, code_helper *, tree, tree *,
+                        tree (*)(tree));
+ bool gimple_resimplify3 (gimple_seq *, code_helper *, tree, tree *,
+                        tree (*)(tree));
  tree maybe_push_res_to_seq (code_helper, tree, tree *,
                            gimple_seq *, tree res = NULL_TREE);
  void maybe_build_generic_op (enum tree_code, tree, tree *, tree, tree);
Index: gcc/gimple-match-head.c
===================================================================
*** gcc/gimple-match-head.c     (revision 228594)
--- gcc/gimple-match-head.c     (working copy)
*************** constant_for_folding (tree t)
*** 83,89 ****
     *RES_CODE and *RES_OPS with a simplified and/or canonicalized
     result and returns whether any change was made.  */
  
! static bool
  gimple_resimplify1 (gimple_seq *seq,
                    code_helper *res_code, tree type, tree *res_ops,
                    tree (*valueize)(tree))
--- 83,89 ----
     *RES_CODE and *RES_OPS with a simplified and/or canonicalized
     result and returns whether any change was made.  */
  
! bool
  gimple_resimplify1 (gimple_seq *seq,
                    code_helper *res_code, tree type, tree *res_ops,
                    tree (*valueize)(tree))
*************** gimple_resimplify1 (gimple_seq *seq,
*** 139,145 ****
     *RES_CODE and *RES_OPS with a simplified and/or canonicalized
     result and returns whether any change was made.  */
  
! static bool
  gimple_resimplify2 (gimple_seq *seq,
                    code_helper *res_code, tree type, tree *res_ops,
                    tree (*valueize)(tree))
--- 139,145 ----
     *RES_CODE and *RES_OPS with a simplified and/or canonicalized
     result and returns whether any change was made.  */
  
! bool
  gimple_resimplify2 (gimple_seq *seq,
                    code_helper *res_code, tree type, tree *res_ops,
                    tree (*valueize)(tree))
*************** gimple_resimplify2 (gimple_seq *seq,
*** 208,214 ****
     *RES_CODE and *RES_OPS with a simplified and/or canonicalized
     result and returns whether any change was made.  */
  
! static bool
  gimple_resimplify3 (gimple_seq *seq,
                    code_helper *res_code, tree type, tree *res_ops,
                    tree (*valueize)(tree))
--- 208,214 ----
     *RES_CODE and *RES_OPS with a simplified and/or canonicalized
     result and returns whether any change was made.  */
  
! bool
  gimple_resimplify3 (gimple_seq *seq,
                    code_helper *res_code, tree type, tree *res_ops,
                    tree (*valueize)(tree))
*************** maybe_push_res_to_seq (code_helper rcode
*** 308,316 ****
    if (rcode.is_tree_code ())
      {
        if (!res
!         && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
!             || ((tree_code) rcode) == ADDR_EXPR)
!         && is_gimple_val (ops[0]))
        return ops[0];
        if (mprts_hook)
        {
--- 308,314 ----
    if (rcode.is_tree_code ())
      {
        if (!res
!         && gimple_simplified_result_is_gimple_val (rcode, ops))
        return ops[0];
        if (mprts_hook)
        {
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c   (revision 228594)
--- gcc/gimple-fold.c   (working copy)
*************** gimple_fold_stmt_to_constant_1 (gimple *
*** 4926,4935 ****
    if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize))
      {
        tree res = NULL_TREE;
!       if (rcode.is_tree_code ()
!         && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
!             || ((tree_code) rcode) == ADDR_EXPR)
!         && is_gimple_val (ops[0]))
        res = ops[0];
        else if (mprts_hook)
        res = mprts_hook (rcode, gimple_expr_type (stmt), ops);
--- 4932,4938 ----
    if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize))
      {
        tree res = NULL_TREE;
!       if (gimple_simplified_result_is_gimple_val (rcode, ops))
        res = ops[0];
        else if (mprts_hook)
        res = mprts_hook (rcode, gimple_expr_type (stmt), ops);
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c        (revision 228594)
--- gcc/tree-ssa-sccvn.c        (working copy)
*************** visit_reference_op_load (tree lhs, tree
*** 3043,3080 ****
         of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
         So first simplify and lookup this expression to see if it
         is already available.  */
-       gimple_seq stmts = NULL;
        mprts_hook = vn_lookup_simplify_result;
!       tree val = gimple_simplify (VIEW_CONVERT_EXPR, TREE_TYPE (op),
!                                 result, &stmts, vn_valueize);
        mprts_hook = NULL;
!       if (!val)
        {
!         val = vn_nary_op_lookup_pieces (1, VIEW_CONVERT_EXPR,
!                                         TREE_TYPE (op), &result, NULL);
          if (!val)
            {
!             val = make_ssa_name (TREE_TYPE (op));
!             gimple *new_stmt = gimple_build_assign (val, VIEW_CONVERT_EXPR,
!                                                     build1 (VIEW_CONVERT_EXPR,
!                                                             TREE_TYPE (op),
!                                                             result));
!             gimple_seq_add_stmt_without_update (&stmts, new_stmt);
            }
        }
!       if (gimple_seq_empty_p (stmts))
!       /* The expression is already available.  */
!       result = val;
!       else
        {
-         gcc_assert (gimple_seq_singleton_p (stmts));
          /* The expression is not yet available, value-number lhs to
             the new SSA_NAME we created.  */
-         result = val;
          /* Initialize value-number information properly.  */
          VN_INFO_GET (result)->valnum = result;
          VN_INFO (result)->value_id = get_next_value_id ();
!         VN_INFO (result)->expr = stmts;
          VN_INFO (result)->needs_insertion = true;
          /* As all "inserted" statements are singleton SCCs, insert
             to the valid table.  This is strictly needed to
--- 3089,3129 ----
         of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
         So first simplify and lookup this expression to see if it
         is already available.  */
        mprts_hook = vn_lookup_simplify_result;
!       code_helper rcode = VIEW_CONVERT_EXPR;
!       tree ops[3] = { result };
!       bool res = gimple_resimplify1 (NULL, &rcode, TREE_TYPE (op), ops,
!                                    vn_valueize);
        mprts_hook = NULL;
!       gimple *new_stmt = NULL;
!       if (res
!         && gimple_simplified_result_is_gimple_val (rcode, ops))
!       /* The expression is already available.  */
!       result = ops[0];
!       else
        {
!         tree val = vn_lookup_simplify_result (rcode, TREE_TYPE (op), ops);
          if (!val)
            {
!             gimple_seq stmts = NULL;
!             result = maybe_push_res_to_seq (rcode, TREE_TYPE (op), ops,
!                                             &stmts);
!             gcc_assert (result && gimple_seq_singleton_p (stmts));
!             new_stmt = gimple_seq_first_stmt (stmts);
            }
+         else
+           /* The expression is already available.  */
+           result = val;
        }
!       if (new_stmt)
        {
          /* The expression is not yet available, value-number lhs to
             the new SSA_NAME we created.  */
          /* Initialize value-number information properly.  */
          VN_INFO_GET (result)->valnum = result;
          VN_INFO (result)->value_id = get_next_value_id ();
!         gimple_seq_add_stmt_without_update (&VN_INFO (result)->expr,
!                                             new_stmt);
          VN_INFO (result)->needs_insertion = true;
          /* As all "inserted" statements are singleton SCCs, insert
             to the valid table.  This is strictly needed to
*************** visit_reference_op_load (tree lhs, tree
*** 3086,3103 ****
          if (current_info == optimistic_info)
            {
              current_info = valid_info;
!             vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result);
              current_info = optimistic_info;
            }
          else
!           vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result);
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "Inserting name ");
              print_generic_expr (dump_file, result, 0);
              fprintf (dump_file, " for expression ");
!             print_gimple_expr (dump_file, gimple_seq_first_stmt (stmts),
!                                0, TDF_SLIM);
              fprintf (dump_file, "\n");
            }
        }
--- 3135,3151 ----
          if (current_info == optimistic_info)
            {
              current_info = valid_info;
!             vn_nary_op_insert_stmt (new_stmt, result);
              current_info = optimistic_info;
            }
          else
!           vn_nary_op_insert_stmt (new_stmt, result);
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
              fprintf (dump_file, "Inserting name ");
              print_generic_expr (dump_file, result, 0);
              fprintf (dump_file, " for expression ");
!             print_gimple_expr (dump_file, new_stmt, 0, TDF_SLIM);
              fprintf (dump_file, "\n");
            }
        }
Index: gcc/testsuite/gcc.dg/tree-ssa/pr67891.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/pr67891.c     (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/pr67891.c     (working copy)
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre1" } */
+ 
+ unsigned int a, *b;
+ unsigned short c;
+ int d;
+ 
+ void 
+ fn1 ()
+ {
+   b = &d;
+   *b = c = a; 
+   *b = d;
+ }
+ 
+ /* We should remove all loads but that from a.  */
+ /* { dg-final { scan-tree-dump-not "= \[dbc\];" "fre1" } } */

Reply via email to