re PR middle-end/58956 (wrong code at -O1 and above (affecting gcc 4.6 to trunk))
authorJakub Jelinek <jakub@redhat.com>
Mon, 16 Dec 2013 08:09:05 +0000 (09:09 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 16 Dec 2013 08:09:05 +0000 (09:09 +0100)
PR middle-end/58956
PR middle-end/59470
* gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
(walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
for callback params.
* gimple-walk.c (walk_stmt_load_store_ops): Likewise.
(walk_stmt_load_store_addr_ops): Likewise.  Adjust all callback
calls to supply the gimple operand containing the base tree
as an extra argument.
* tree-ssa-ter.c: Include gimple-walk.h.
(find_ssaname, find_ssaname_in_store): New helper functions.
(find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
same_root_var if USE is used somewhere in the stores of the stmt.
* ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
* ipa-pure-const.c (check_load, check_store, check_ipa_load,
check_ipa_store): Likewise.
* gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
* ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
(verify_non_ssa_vars, visit_bb): Adjust their callers.
* cfgexpand.c (add_scope_conflicts_1): Use
walk_stmt_load_store_addr_fn type for visit variable.
(visit_op, visit_conflict): Remove name of the stmt
argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
* tree-sra.c (asm_visit_addr): Likewise.  Remove name of the data
argument and ATTRIBUTE_UNUSED.
* cgraphbuild.c (mark_address, mark_load, mark_store): Add another
unnamed tree argument.
* gimple-ssa-isolate-paths.c (check_loadstore): Likewise.  Remove
ATTRIBUTE_UNUSED from stmt parameter.

* gcc.target/i386/pr59470.c: New test.

From-SVN: r206009

14 files changed:
gcc/ChangeLog
gcc/cfgexpand.c
gcc/cgraphbuild.c
gcc/gimple-ssa-isolate-paths.c
gcc/gimple-walk.c
gcc/gimple-walk.h
gcc/gimple.c
gcc/ipa-prop.c
gcc/ipa-pure-const.c
gcc/ipa-split.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr59470.c [new file with mode: 0644]
gcc/tree-sra.c
gcc/tree-ssa-ter.c

index 8b61a445cef99fa643a6648e7d633cae231724a5..95d657481322180a184f0ba72583c25b7e072a3e 100644 (file)
@@ -1,3 +1,36 @@
+2013-12-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/58956
+       PR middle-end/59470
+       * gimple-walk.h (walk_stmt_load_store_addr_fn): New typedef.
+       (walk_stmt_load_store_addr_ops, walk_stmt_load_store_ops): Use it
+       for callback params.
+       * gimple-walk.c (walk_stmt_load_store_ops): Likewise.
+       (walk_stmt_load_store_addr_ops): Likewise.  Adjust all callback
+       calls to supply the gimple operand containing the base tree
+       as an extra argument.
+       * tree-ssa-ter.c: Include gimple-walk.h.
+       (find_ssaname, find_ssaname_in_store): New helper functions.
+       (find_replaceable_in_bb): For calls or GIMPLE_ASM, only set
+       same_root_var if USE is used somewhere in the stores of the stmt.
+       * ipa-prop.c (visit_ref_for_mod_analysis): Remove name of the stmt
+       argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
+       * ipa-pure-const.c (check_load, check_store, check_ipa_load,
+       check_ipa_store): Likewise.
+       * gimple.c (gimple_ior_addresses_taken_1, check_loadstore): Likewise.
+       * ipa-split.c (test_nonssa_use, mark_nonssa_use): Likewise.
+       (verify_non_ssa_vars, visit_bb): Adjust their callers.
+       * cfgexpand.c (add_scope_conflicts_1): Use
+       walk_stmt_load_store_addr_fn type for visit variable.
+       (visit_op, visit_conflict): Remove name of the stmt
+       argument and ATTRIBUTE_UNUSED, add another unnamed tree argument.
+       * tree-sra.c (asm_visit_addr): Likewise.  Remove name of the data
+       argument and ATTRIBUTE_UNUSED.
+       * cgraphbuild.c (mark_address, mark_load, mark_store): Add another
+       unnamed tree argument.
+       * gimple-ssa-isolate-paths.c (check_loadstore): Likewise.  Remove
+       ATTRIBUTE_UNUSED from stmt parameter.
+
 2013-12-16  Chung-Lin Tang  <cltang@codesourcery.com>
 
        * opts-common.c (integral_argument): Add support for
index a73bd411926847fc5d06ddb69e317d3448b6bf48..7a939753fdff2105e302baff40319bb5af7a8448 100644 (file)
@@ -365,7 +365,7 @@ stack_var_conflict_p (size_t x, size_t y)
    enter its partition number into bitmap DATA.  */
 
 static bool
-visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+visit_op (gimple, tree op, tree, void *data)
 {
   bitmap active = (bitmap)data;
   op = get_base_address (op);
@@ -385,7 +385,7 @@ visit_op (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
    from bitmap DATA.  */
 
 static bool
-visit_conflict (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+visit_conflict (gimple, tree op, tree, void *data)
 {
   bitmap active = (bitmap)data;
   op = get_base_address (op);
@@ -419,7 +419,7 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)
   edge e;
   edge_iterator ei;
   gimple_stmt_iterator gsi;
-  bool (*visit)(gimple, tree, void *);
+  walk_stmt_load_store_addr_fn visit;
 
   bitmap_clear (work);
   FOR_EACH_EDGE (e, ei, bb->preds)
index f1595fd0aff47cf33cc18630ef5c6a7afc688a07..bf790b0fe61888884a4ed3d8711a13c1cf3a3b66 100644 (file)
@@ -224,7 +224,7 @@ compute_call_stmt_bb_frequency (tree decl, basic_block bb)
 /* Mark address taken in STMT.  */
 
 static bool
-mark_address (gimple stmt, tree addr, void *data)
+mark_address (gimple stmt, tree addr, tree, void *data)
 {
   addr = get_base_address (addr);
   if (TREE_CODE (addr) == FUNCTION_DECL)
@@ -251,7 +251,7 @@ mark_address (gimple stmt, tree addr, void *data)
 /* Mark load of T.  */
 
 static bool
-mark_load (gimple stmt, tree t, void *data)
+mark_load (gimple stmt, tree t, tree, void *data)
 {
   t = get_base_address (t);
   if (t && TREE_CODE (t) == FUNCTION_DECL)
@@ -279,7 +279,7 @@ mark_load (gimple stmt, tree t, void *data)
 /* Mark store of T.  */
 
 static bool
-mark_store (gimple stmt, tree t, void *data)
+mark_store (gimple stmt, tree t, tree, void *data)
 {
   t = get_base_address (t);
   if (t && TREE_CODE (t) == VAR_DECL
index aaa75378b3e07b07cc4ae87c8bec50e1472c716b..dd1f4f8502512d92e9147f3b609ee0a9b7e68a8b 100644 (file)
@@ -55,7 +55,7 @@ static bool cfg_altered;
    This routine only makes a superficial check for a dereference.  Thus,
    it must only be used if it is safe to return a false negative.  */
 static bool
-check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_loadstore (gimple stmt, tree op, tree, void *data)
 {
   if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
       && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
index 4d59ae078c3af0fa9e265ade8514a3506c7ec158..1f8b2f4f0e7f8a534cf2ee78f1999d9ebdfe32fd 100644 (file)
@@ -649,42 +649,46 @@ get_base_loadstore (tree op)
 
 /* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
    VISIT_ADDR if non-NULL on loads, store and address-taken operands
-   passing the STMT, the base of the operand and DATA to it.  The base
-   will be either a decl, an indirect reference (including TARGET_MEM_REF)
-   or the argument of an address expression.
+   passing the STMT, the base of the operand, the operand itself containing
+   the base and DATA to it.  The base will be either a decl, an indirect
+   reference (including TARGET_MEM_REF) or the argument of an address
+   expression.
    Returns the results of these callbacks or'ed.  */
 
 bool
 walk_stmt_load_store_addr_ops (gimple stmt, void *data,
-                              bool (*visit_load)(gimple, tree, void *),
-                              bool (*visit_store)(gimple, tree, void *),
-                              bool (*visit_addr)(gimple, tree, void *))
+                              walk_stmt_load_store_addr_fn visit_load,
+                              walk_stmt_load_store_addr_fn visit_store,
+                              walk_stmt_load_store_addr_fn visit_addr)
 {
   bool ret = false;
   unsigned i;
   if (gimple_assign_single_p (stmt))
     {
-      tree lhs, rhs;
+      tree lhs, rhs, arg;
       if (visit_store)
        {
-         lhs = get_base_loadstore (gimple_assign_lhs (stmt));
+         arg = gimple_assign_lhs (stmt);
+         lhs = get_base_loadstore (arg);
          if (lhs)
-           ret |= visit_store (stmt, lhs, data);
+           ret |= visit_store (stmt, lhs, arg, data);
        }
-      rhs = gimple_assign_rhs1 (stmt);
+      arg = gimple_assign_rhs1 (stmt);
+      rhs = arg;
       while (handled_component_p (rhs))
        rhs = TREE_OPERAND (rhs, 0);
       if (visit_addr)
        {
          if (TREE_CODE (rhs) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+           ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), arg, data);
          else if (TREE_CODE (rhs) == TARGET_MEM_REF
                   && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
+           ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), arg,
+                              data);
          else if (TREE_CODE (rhs) == OBJ_TYPE_REF
                   && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
            ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
-                                                  0), data);
+                                                  0), arg, data);
          else if (TREE_CODE (rhs) == CONSTRUCTOR)
            {
              unsigned int ix;
@@ -692,23 +696,23 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
 
              FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), ix, val)
                if (TREE_CODE (val) == ADDR_EXPR)
-                 ret |= visit_addr (stmt, TREE_OPERAND (val, 0), data);
+                 ret |= visit_addr (stmt, TREE_OPERAND (val, 0), arg, data);
                else if (TREE_CODE (val) == OBJ_TYPE_REF
                         && TREE_CODE (OBJ_TYPE_REF_OBJECT (val)) == ADDR_EXPR)
                  ret |= visit_addr (stmt,
                                     TREE_OPERAND (OBJ_TYPE_REF_OBJECT (val),
-                                                  0), data);
+                                                  0), arg, data);
            }
           lhs = gimple_assign_lhs (stmt);
          if (TREE_CODE (lhs) == TARGET_MEM_REF
               && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
-            ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), data);
+           ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 0), lhs, data);
        }
       if (visit_load)
        {
          rhs = get_base_loadstore (rhs);
          if (rhs)
-           ret |= visit_load (stmt, rhs, data);
+           ret |= visit_load (stmt, rhs, arg, data);
        }
     }
   else if (visit_addr
@@ -721,17 +725,17 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
          if (op == NULL_TREE)
            ;
          else if (TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
          /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
             tree with two operands.  */
          else if (i == 1 && COMPARISON_CLASS_P (op))
            {
              if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
                ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
-                                                      0), data);
+                                                      0), op, data);
              if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
                ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
-                                                      0), data);
+                                                      0), op, data);
            }
        }
     }
@@ -739,38 +743,39 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
     {
       if (visit_store)
        {
-         tree lhs = gimple_call_lhs (stmt);
-         if (lhs)
+         tree arg = gimple_call_lhs (stmt);
+         if (arg)
            {
-             lhs = get_base_loadstore (lhs);
+             tree lhs = get_base_loadstore (arg);
              if (lhs)
-               ret |= visit_store (stmt, lhs, data);
+               ret |= visit_store (stmt, lhs, arg, data);
            }
        }
       if (visit_load || visit_addr)
        for (i = 0; i < gimple_call_num_args (stmt); ++i)
          {
-           tree rhs = gimple_call_arg (stmt, i);
+           tree arg = gimple_call_arg (stmt, i);
            if (visit_addr
-               && TREE_CODE (rhs) == ADDR_EXPR)
-             ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+               && TREE_CODE (arg) == ADDR_EXPR)
+             ret |= visit_addr (stmt, TREE_OPERAND (arg, 0), arg, data);
            else if (visit_load)
              {
-               rhs = get_base_loadstore (rhs);
+               tree rhs = get_base_loadstore (arg);
                if (rhs)
-                 ret |= visit_load (stmt, rhs, data);
+                 ret |= visit_load (stmt, rhs, arg, data);
              }
          }
       if (visit_addr
          && gimple_call_chain (stmt)
          && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
        ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
-                          data);
+                          gimple_call_chain (stmt), data);
       if (visit_addr
          && gimple_call_return_slot_opt_p (stmt)
          && gimple_call_lhs (stmt) != NULL_TREE
          && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
-       ret |= visit_addr (stmt, gimple_call_lhs (stmt), data);
+       ret |= visit_addr (stmt, gimple_call_lhs (stmt),
+                          gimple_call_lhs (stmt), data);
     }
   else if (gimple_code (stmt) == GIMPLE_ASM)
     {
@@ -786,7 +791,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
            tree link = gimple_asm_output_op (stmt, i);
            tree op = get_base_loadstore (TREE_VALUE (link));
            if (op && visit_store)
-             ret |= visit_store (stmt, op, data);
+             ret |= visit_store (stmt, op, TREE_VALUE (link), data);
            if (visit_addr)
              {
                constraint = TREE_STRING_POINTER
@@ -795,7 +800,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
                parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
                                         &allows_reg, &is_inout);
                if (op && !allows_reg && allows_mem)
-                 ret |= visit_addr (stmt, op, data);
+                 ret |= visit_addr (stmt, op, TREE_VALUE (link), data);
              }
          }
       if (visit_load || visit_addr)
@@ -805,14 +810,14 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
            tree op = TREE_VALUE (link);
            if (visit_addr
                && TREE_CODE (op) == ADDR_EXPR)
-             ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+             ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
            else if (visit_load || visit_addr)
              {
                op = get_base_loadstore (op);
                if (op)
                  {
                    if (visit_load)
-                     ret |= visit_load (stmt, op, data);
+                     ret |= visit_load (stmt, op, TREE_VALUE (link), data);
                    if (visit_addr)
                      {
                        constraint = TREE_STRING_POINTER
@@ -821,7 +826,8 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
                                                0, oconstraints,
                                                &allows_mem, &allows_reg);
                        if (!allows_reg && allows_mem)
-                         ret |= visit_addr (stmt, op, data);
+                         ret |= visit_addr (stmt, op, TREE_VALUE (link),
+                                            data);
                      }
                  }
              }
@@ -834,12 +840,12 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
        {
          if (visit_addr
              && TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
          else if (visit_load)
            {
-             op = get_base_loadstore (op);
-             if (op)
-               ret |= visit_load (stmt, op, data);
+             tree base = get_base_loadstore (op);
+             if (base)
+               ret |= visit_load (stmt, base, op, data);
            }
        }
     }
@@ -850,7 +856,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
        {
          tree op = gimple_phi_arg_def (stmt, i);
          if (TREE_CODE (op) == ADDR_EXPR)
-           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
        }
     }
   else if (visit_addr
@@ -858,7 +864,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
     {
       tree op = gimple_goto_dest (stmt);
       if (TREE_CODE (op) == ADDR_EXPR)
-       ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+       ret |= visit_addr (stmt, TREE_OPERAND (op, 0), op, data);
     }
 
   return ret;
@@ -869,8 +875,8 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
 
 bool
 walk_stmt_load_store_ops (gimple stmt, void *data,
-                         bool (*visit_load)(gimple, tree, void *),
-                         bool (*visit_store)(gimple, tree, void *))
+                         walk_stmt_load_store_addr_fn visit_load,
+                         walk_stmt_load_store_addr_fn visit_store)
 {
   return walk_stmt_load_store_addr_ops (stmt, data,
                                        visit_load, visit_store, NULL);
index 0b9968a522d2324b24a2ed87ef16e18ea73b038b..82982e48b1a97a3a2012b8245ee444fe36e87ee0 100644 (file)
@@ -89,11 +89,12 @@ extern gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
 extern tree walk_gimple_op (gimple, walk_tree_fn, struct walk_stmt_info *);
 extern tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn,
                              walk_tree_fn, struct walk_stmt_info *);
+typedef bool (*walk_stmt_load_store_addr_fn) (gimple, tree, tree, void *);
 extern bool walk_stmt_load_store_addr_ops (gimple, void *,
-                                          bool (*)(gimple, tree, void *),
-                                          bool (*)(gimple, tree, void *),
-                                          bool (*)(gimple, tree, void *));
+                                          walk_stmt_load_store_addr_fn,
+                                          walk_stmt_load_store_addr_fn,
+                                          walk_stmt_load_store_addr_fn);
 extern bool walk_stmt_load_store_ops (gimple, void *,
-                                     bool (*)(gimple, tree, void *),
-                                     bool (*)(gimple, tree, void *));
+                                     walk_stmt_load_store_addr_fn,
+                                     walk_stmt_load_store_addr_fn);
 #endif /* GCC_GIMPLE_WALK_H */
index 077dca5d63c19b19d75318b98e6bcc5ff1200377..38e209fabc9d9bfc8d5adc147c59b759c2fa8003 100644 (file)
@@ -2326,8 +2326,7 @@ gimple_get_alias_set (tree t)
 /* Helper for gimple_ior_addresses_taken_1.  */
 
 static bool
-gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED,
-                             tree addr, void *data)
+gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data)
 {
   bitmap addresses_taken = (bitmap)data;
   addr = get_base_address (addr);
@@ -2496,7 +2495,7 @@ nonfreeing_call_p (gimple call)
    This routine only makes a superficial check for a dereference.  Thus
    it must only be used if it is safe to return a false negative.  */
 static bool
-check_loadstore (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_loadstore (gimple, tree op, tree, void *data)
 {
   if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
       && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
index a753c040b9ed6e8e3602b86558b71e5ebbcdface..5a337f7ce3e3ea2a07da1f269ba8b10ae201c3c8 100644 (file)
@@ -2061,8 +2061,7 @@ ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info,
    passed in DATA.  */
 
 static bool
-visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
-                            tree op, void *data)
+visit_ref_for_mod_analysis (gimple, tree op, tree, void *data)
 {
   struct ipa_node_params *info = (struct ipa_node_params *) data;
 
index a60e078c90c22e3a3ca3a38608cb06922754c55b..fd10fe357f029cfb7ffb9265ffea519de9de1b44 100644 (file)
@@ -589,7 +589,7 @@ check_call (funct_state local, gimple call, bool ipa)
 /* Wrapper around check_decl for loads in local more.  */
 
 static bool
-check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_load (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, false, false);
@@ -601,7 +601,7 @@ check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
 /* Wrapper around check_decl for stores in local more.  */
 
 static bool
-check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_store (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, true, false);
@@ -613,7 +613,7 @@ check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
 /* Wrapper around check_decl for loads in ipa mode.  */
 
 static bool
-check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_ipa_load (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, false, true);
@@ -625,7 +625,7 @@ check_ipa_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
 /* Wrapper around check_decl for stores in ipa mode.  */
 
 static bool
-check_ipa_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+check_ipa_store (gimple, tree op, tree, void *data)
 {
   if (DECL_P (op))
     check_decl ((funct_state)data, op, true, true);
index 390adf1f7983febd1020df0800fa987dbda1f321..6d9334882ed39d7d128d3d9d8b5fa98a1e9f63f0 100644 (file)
@@ -156,7 +156,7 @@ static tree find_retval (basic_block return_bb);
    variable, check it if it is present in bitmap passed via DATA.  */
 
 static bool
-test_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
+test_nonssa_use (gimple, tree t, tree, void *data)
 {
   t = get_base_address (t);
 
@@ -249,7 +249,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
            }
          if (gimple_code (stmt) == GIMPLE_LABEL
              && test_nonssa_use (stmt, gimple_label_label (stmt),
-                                 non_ssa_vars))
+                                 NULL_TREE, non_ssa_vars))
          {
            ok = false;
            goto done;
@@ -278,7 +278,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
              if (virtual_operand_p (gimple_phi_result (stmt)))
                continue;
              if (TREE_CODE (op) != SSA_NAME
-                 && test_nonssa_use (stmt, op, non_ssa_vars))
+                 && test_nonssa_use (stmt, op, op, non_ssa_vars))
                {
                  ok = false;
                  goto done;
@@ -714,7 +714,7 @@ find_retval (basic_block return_bb)
    Return true when access to T prevents splitting the function.  */
 
 static bool
-mark_nonssa_use (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
+mark_nonssa_use (gimple, tree t, tree, void *data)
 {
   t = get_base_address (t);
 
@@ -874,7 +874,7 @@ visit_bb (basic_block bb, basic_block return_bb,
            if (TREE_CODE (op) == SSA_NAME)
              bitmap_set_bit (used_ssa_names, SSA_NAME_VERSION (op));
            else
-             can_split &= !mark_nonssa_use (stmt, op, non_ssa_vars);
+             can_split &= !mark_nonssa_use (stmt, op, op, non_ssa_vars);
          }
       }
   return can_split;
index f143da257feafa009af84ac2c0a1e0f50caf047a..e7c54bc2898fbed7394a0e5c4a4cb986b698c2d9 100644 (file)
@@ -1,3 +1,9 @@
+2013-12-16  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/58956
+       PR middle-end/59470
+       * gcc.target/i386/pr59470.c: New test.
+
 2013-12-14   Jan Hubicka  <jh@suse.cz>
 
        PR ipa/59265
diff --git a/gcc/testsuite/gcc.target/i386/pr59470.c b/gcc/testsuite/gcc.target/i386/pr59470.c
new file mode 100644 (file)
index 0000000..0d9952f
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR middle-end/58956 */
+/* PR middle-end/59470 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int a, b, d[1024];
+
+int
+main ()
+{
+  int c = a;
+  asm ("{movl $6, (%2); movl $1, %0|mov dword ptr [%2], 6; mov %0, 1}"
+       : "=r" (d[c]) : "rm" (b), "r" (&a) : "memory");
+  if (d[0] != 1 || d[6] != 0)
+    __builtin_abort ();
+  return 0;
+}
index ebd42185c98bf57f303b9a39a791894888e893fb..47765416e68e13216f5d3fec9d42f969d16d8974 100644 (file)
@@ -1223,8 +1223,7 @@ build_accesses_from_assign (gimple stmt)
    GIMPLE_ASM operands with memory constrains which cannot be scalarized.  */
 
 static bool
-asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
-               void *data ATTRIBUTE_UNUSED)
+asm_visit_addr (gimple, tree op, tree, void *)
 {
   op = get_base_address (op);
   if (op
index 22ae47b766b04a1950bd8b8b98d9c5e26020b11f..cefe47c6d5f3c9d6b149ab5f2f4baac1808b5748 100644 (file)
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-ter.h"
 #include "tree-outof-ssa.h"
 #include "flags.h"
+#include "gimple-walk.h"
 
 
 /* Temporary Expression Replacement (TER)
@@ -554,6 +555,30 @@ mark_replaceable (temp_expr_table_p tab, tree var, bool more_replacing)
 }
 
 
+/* Helper function for find_ssaname_in_stores.  Called via walk_tree to
+   find a SSA_NAME DATA somewhere in *TP.  */
+
+static tree
+find_ssaname (tree *tp, int *walk_subtrees, void *data)
+{
+  tree var = (tree) data;
+  if (*tp == var)
+    return var;
+  else if (IS_TYPE_OR_DECL_P (*tp))
+    *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+/* Helper function for find_replaceable_in_bb.  Return true if SSA_NAME DATA
+   is used somewhere in T, which is a store in the statement.  Called via
+   walk_stmt_load_store_addr_ops.  */
+
+static bool
+find_ssaname_in_store (gimple, tree, tree t, void *data)
+{
+  return walk_tree (&t, find_ssaname, data, NULL) != NULL_TREE;
+}
+
 /* This function processes basic block BB, and looks for variables which can
    be replaced by their expressions.  Results are stored in the table TAB.  */
 
@@ -618,7 +643,27 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
                      && gimple_assign_single_p (def_stmt)
                      && stmt_may_clobber_ref_p (stmt,
                                                 gimple_assign_rhs1 (def_stmt)))
-                   same_root_var = true;
+                   {
+                     /* For calls, it is not a problem if USE is among
+                        call's arguments or say OBJ_TYPE_REF argument,
+                        all those necessarily need to be evaluated before
+                        the call that may clobber the memory.  But if
+                        LHS of the call refers to USE, expansion might
+                        evaluate it after the call, prevent TER in that
+                        case.
+                        For inline asm, allow TER of loads into input
+                        arguments, but disallow TER for USEs that occur
+                        somewhere in outputs.  */
+                     if (is_gimple_call (stmt)
+                         || gimple_code (stmt) == GIMPLE_ASM)
+                       {
+                         if (walk_stmt_load_store_ops (stmt, use, NULL,
+                                                       find_ssaname_in_store))
+                           same_root_var = true;
+                       }
+                     else
+                       same_root_var = true;
+                   }
                }
 
              /* Mark expression as replaceable unless stmt is volatile, or the