re PR tree-optimization/36945 (PRE/SCCVN do not handle aggregate function arguments...
authorRichard Guenther <rguenther@suse.de>
Tue, 29 Jul 2008 17:09:26 +0000 (17:09 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 29 Jul 2008 17:09:26 +0000 (17:09 +0000)
2008-07-29  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/36945
* tree-ssa-sccvn.h (copy_reference_ops_from_ref): Declare.
* tree-ssa-sccvn.c (copy_reference_ops_from_ref): Export.
Record invariant addresses un-decomposed.
(copy_reference_ops_from_call): Record reference call
arguments properly.  Simplify.
* tree-ssa-pre.c (create_component_ref_by_pieces_1): New
helper split out from ...
(create_component_ref_by_pieces): ... here.  Simplify.
Prepare for recursive invocation for call arguments.
(create_expression_by_pieces): Adjust call to
create_component_ref_by_pieces.
(compute_avail): Process operand 2 of reference ops.

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

From-SVN: r138257

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c [new file with mode: 0644]
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h

index d1929ba0cffda1943920f2f9d51c9efe608f9fbb..9d0388dd5aa9fefafd2d02b55e4f746174240b94 100644 (file)
@@ -1,3 +1,19 @@
+2008-07-29  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/36945
+       * tree-ssa-sccvn.h (copy_reference_ops_from_ref): Declare.
+       * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Export.
+       Record invariant addresses un-decomposed.
+       (copy_reference_ops_from_call): Record reference call
+       arguments properly.  Simplify.
+       * tree-ssa-pre.c (create_component_ref_by_pieces_1): New
+       helper split out from ...
+       (create_component_ref_by_pieces): ... here.  Simplify.
+       Prepare for recursive invocation for call arguments.
+       (create_expression_by_pieces): Adjust call to
+       create_component_ref_by_pieces.
+       (compute_avail): Process operand 2 of reference ops.
+
 2008-07-29  Richard Guenther  <rguenther@suse.de>
 
        * gimplify.c (gimplify_expr): Clear TREE_SIDE_EFFECTS for
index d4e8ddb8701b01117108660feda8b16d5f71f8d0..79568ddab39709b7e11815dd8d8af1e7d33c7ab0 100644 (file)
@@ -1,3 +1,8 @@
+2008-07-29  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/36945
+       * gcc.dg/tree-ssa/ssa-pre-18.c: New testcase.
+
 2008-07-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/36852
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c
new file mode 100644 (file)
index 0000000..5e92934
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-details" } */
+
+struct Bar { int a; int b; };
+struct Foo { int x; struct Bar y; };
+
+int __attribute__((const)) foo (struct Bar);
+
+int bar (int b)
+{
+  struct Foo f;
+  int c;
+  while (b--)
+    {
+      c = foo(f.y);
+    }
+  return c;
+}
+
+/* { dg-final { scan-tree-dump "Replaced foo \\(f.y\\)" "pre" } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
index c772ff2bdaff9e56013644e69f4711689ae97eab..c98a18a772c9e57685bb5bea31bf797bb7a27420 100644 (file)
@@ -2421,64 +2421,56 @@ static VEC(gimple,heap) *inserted_exprs;
    to see which expressions need to be put into GC'able memory  */
 static VEC(gimple, heap) *need_creation;
 
-/* For COMPONENT_REF's and ARRAY_REF's, we can't have any intermediates for the
-   COMPONENT_REF or INDIRECT_REF or ARRAY_REF portion, because we'd end up with
-   trying to rename aggregates into ssa form directly, which is a no
-   no.
-
-   Thus, this routine doesn't create temporaries, it just builds a
-   single access expression for the array, calling
-   find_or_generate_expression to build the innermost pieces.
+/* The actual worker for create_component_ref_by_pieces.  */
 
-   This function is a subroutine of create_expression_by_pieces, and
-   should not be called on it's own unless you really know what you
-   are doing.
-*/
 static tree
-create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
-                               unsigned int operand,
-                               gimple_seq *stmts,
-                               gimple domstmt,
-                               bool in_call)
+create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
+                                 unsigned int *operand, gimple_seq *stmts,
+                                 gimple domstmt)
 {
   vn_reference_op_t currop = VEC_index (vn_reference_op_s, ref->operands,
-                                       operand);
+                                       *operand);
   tree genop;
+  ++*operand;
   switch (currop->opcode)
     {
     case CALL_EXPR:
       {
        tree folded;
-       unsigned int i;
-       vn_reference_op_t declop = VEC_index (vn_reference_op_s,
-                                             ref->operands, 1);
-       unsigned int nargs = VEC_length (vn_reference_op_s, ref->operands) - 2;
-       tree *args = XNEWVEC (tree, nargs);
-
-       for (i = 0; i < nargs; i++)
+       unsigned int nargs = 0;
+       tree *args = XNEWVEC (tree, VEC_length (vn_reference_op_s,
+                                               ref->operands) - 1);
+       while (*operand < VEC_length (vn_reference_op_s, ref->operands))
          {
-           args[i] = create_component_ref_by_pieces (block, ref,
-                                                     operand + 2 + i, stmts,
-                                                     domstmt, true);
+           args[nargs] = create_component_ref_by_pieces_1 (block, ref,
+                                                           operand, stmts,
+                                                           domstmt);
+           nargs++;
          }
        folded = build_call_array (currop->type,
-                                  TREE_CODE (declop->op0) == FUNCTION_DECL
-                                  ? build_fold_addr_expr (declop->op0)
-                                  : declop->op0,
+                                  TREE_CODE (currop->op0) == FUNCTION_DECL
+                                  ? build_fold_addr_expr (currop->op0)
+                                  : currop->op0,
                                   nargs, args);
        free (args);
        return folded;
       }
       break;
+    case ADDR_EXPR:
+      if (currop->op0)
+       {
+         gcc_assert (is_gimple_min_invariant (currop->op0));
+         return currop->op0;
+       }
+      /* Fallthrough.  */
     case REALPART_EXPR:
     case IMAGPART_EXPR:
     case VIEW_CONVERT_EXPR:
       {
        tree folded;
-       tree genop0 = create_component_ref_by_pieces (block, ref,
-                                                     operand + 1,
-                                                     stmts, domstmt,
-                                                     in_call);
+       tree genop0 = create_component_ref_by_pieces_1 (block, ref,
+                                                       operand,
+                                                       stmts, domstmt);
        if (!genop0)
          return NULL_TREE;
        folded = fold_build1 (currop->opcode, currop->type,
@@ -2490,45 +2482,25 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
     case MISALIGNED_INDIRECT_REF:
     case INDIRECT_REF:
       {
-       /* Inside a CALL_EXPR op0 is the actual indirect_ref.  */
-       if (in_call)
-         {
-           tree folded;
-           tree op0 = TREE_OPERAND (currop->op0, 0);
-           pre_expr op0expr = get_or_alloc_expr_for (op0);
-           tree genop0 = find_or_generate_expression (block, op0expr, stmts,
-                                                      domstmt);
-           if (!genop0)
-             return NULL_TREE;
-           folded = fold_build1 (currop->opcode, currop->type,
-                                 genop0);
-           return folded;
-         }
-       else
-         {
-
-           tree folded;
-           tree genop1 = create_component_ref_by_pieces (block, ref,
-                                                         operand + 1,
-                                                         stmts, domstmt,
-                                                         in_call);
-           if (!genop1)
-             return NULL_TREE;
-           genop1 = fold_convert (build_pointer_type (currop->type),
-                                  genop1);
+       tree folded;
+       tree genop1 = create_component_ref_by_pieces_1 (block, ref,
+                                                       operand,
+                                                       stmts, domstmt);
+       if (!genop1)
+         return NULL_TREE;
+       genop1 = fold_convert (build_pointer_type (currop->type),
+                              genop1);
 
-           folded = fold_build1 (currop->opcode, currop->type,
-                                 genop1);
-           return folded;
-         }
+       folded = fold_build1 (currop->opcode, currop->type,
+                             genop1);
+       return folded;
       }
       break;
     case BIT_FIELD_REF:
       {
        tree folded;
-       tree genop0 = create_component_ref_by_pieces (block, ref, operand + 1,
-                                                     stmts, domstmt,
-                                                     in_call);
+       tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
+                                                       stmts, domstmt);
        pre_expr op1expr = get_or_alloc_expr_for (currop->op0);
        pre_expr op2expr = get_or_alloc_expr_for (currop->op1);
        tree genop1;
@@ -2553,17 +2525,14 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
     case ARRAY_RANGE_REF:
     case ARRAY_REF:
       {
-       vn_reference_op_t op0expr;
        tree genop0;
        tree genop1 = currop->op0;
        pre_expr op1expr;
        tree genop2 = currop->op1;
        pre_expr op2expr;
        tree genop3;
-       op0expr = VEC_index (vn_reference_op_s, ref->operands, operand + 1);
-       genop0 = create_component_ref_by_pieces (block, ref, operand + 1,
-                                                stmts, domstmt,
-                                                in_call);
+       genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
+                                                  stmts, domstmt);
        if (!genop0)
          return NULL_TREE;
        op1expr = get_or_alloc_expr_for (genop1);
@@ -2589,8 +2558,8 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
        tree op1;
        tree genop2 = currop->op1;
        pre_expr op2expr;
-       op0 = create_component_ref_by_pieces (block, ref, operand + 1,
-                                             stmts, domstmt, in_call);
+       op0 = create_component_ref_by_pieces_1 (block, ref, operand,
+                                               stmts, domstmt);
        if (!op0)
          return NULL_TREE;
        /* op1 should be a FIELD_DECL, which are represented by
@@ -2626,11 +2595,6 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
     case CONST_DECL:
     case RESULT_DECL:
     case FUNCTION_DECL:
-      /* For ADDR_EXPR in a CALL_EXPR, op0 is actually the entire
-        ADDR_EXPR, not just it's operand.  */
-    case ADDR_EXPR:
-      if (currop->opcode == ADDR_EXPR)
-       gcc_assert (currop->op0 != NULL);
       return currop->op0;
 
     default:
@@ -2638,6 +2602,26 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
     }
 }
 
+/* For COMPONENT_REF's and ARRAY_REF's, we can't have any intermediates for the
+   COMPONENT_REF or INDIRECT_REF or ARRAY_REF portion, because we'd end up with
+   trying to rename aggregates into ssa form directly, which is a no no.
+
+   Thus, this routine doesn't create temporaries, it just builds a
+   single access expression for the array, calling
+   find_or_generate_expression to build the innermost pieces.
+
+   This function is a subroutine of create_expression_by_pieces, and
+   should not be called on it's own unless you really know what you
+   are doing.  */
+
+static tree
+create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
+                               gimple_seq *stmts, gimple domstmt)
+{
+  unsigned int op = 0;
+  return create_component_ref_by_pieces_1 (block, ref, &op, stmts, domstmt);
+}
+
 /* Find a leader for an expression, or generate one using
    create_expression_by_pieces if it's ANTIC but
    complex.
@@ -2743,8 +2727,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
     case REFERENCE:
       {
        vn_reference_t ref = PRE_EXPR_REFERENCE (expr);
-       folded = create_component_ref_by_pieces (block, ref, 0, stmts,
-                                                domstmt, false);
+       folded = create_component_ref_by_pieces (block, ref, stmts, domstmt);
       }
       break;
     case NARY:
@@ -3616,6 +3599,8 @@ compute_avail (void)
                      add_to_exp_gen (block, vro->op0);
                    if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
                      add_to_exp_gen (block, vro->op1);
+                   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;
@@ -3688,6 +3673,8 @@ compute_avail (void)
                            add_to_exp_gen (block, vro->op0);
                          if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
                            add_to_exp_gen (block, vro->op1);
+                         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;
index 42d394f554009eef6ef83733dbcee156c28c353b..f6492bdafd830bbf3e27060185e927f54ffa0473 100644 (file)
@@ -557,7 +557,7 @@ shared_vuses_from_stmt (gimple stmt)
 /* Copy the operations present in load/store REF into RESULT, a vector of
    vn_reference_op_s's.  */
 
-static void
+void
 copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
 {
   if (TREE_CODE (ref) == TARGET_MEM_REF)
@@ -646,6 +646,13 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
        case SSA_NAME:
          temp.op0 = ref;
          break;
+       case ADDR_EXPR:
+         if (is_gimple_min_invariant (ref))
+           {
+             temp.op0 = ref;
+             break;
+           }
+         /* Fallthrough.  */
          /* These are only interesting for their operands, their
             existence, and their type.  They will never be the last
             ref in the chain of references (IE they require an
@@ -654,15 +661,15 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
        case IMAGPART_EXPR:
        case REALPART_EXPR:
        case VIEW_CONVERT_EXPR:
-       case ADDR_EXPR:
          break;
        default:
          gcc_unreachable ();
-
        }
       VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
 
-      if (REFERENCE_CLASS_P (ref) || TREE_CODE (ref) == ADDR_EXPR)
+      if (REFERENCE_CLASS_P (ref)
+         || (TREE_CODE (ref) == ADDR_EXPR
+             && !is_gimple_min_invariant (ref)))
        ref = TREE_OPERAND (ref, 0);
       else
        ref = NULL_TREE;
@@ -677,7 +684,6 @@ copy_reference_ops_from_call (gimple call,
                              VEC(vn_reference_op_s, heap) **result)
 {
   vn_reference_op_s temp;
-  tree callfn;
   unsigned i;
 
   /* Copy the call_expr opcode, type, function being called, and
@@ -685,33 +691,15 @@ copy_reference_ops_from_call (gimple call,
   memset (&temp, 0, sizeof (temp));
   temp.type = gimple_call_return_type (call);
   temp.opcode = CALL_EXPR;
+  temp.op0 = gimple_call_fn (call);
   VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
 
-  /* FIXME tuples
-     We make no attempt to simplify the called function because
-     the typical &FUNCTION_DECL form is also used in function pointer
-     cases that become constant.  If we simplify the original to
-     FUNCTION_DECL but not the function pointer case (which can
-     happen because we have no fold functions that operate on
-     vn_reference_t), we will claim they are not equivalent.
-
-     An example of this behavior can be see if CALL_EXPR_FN below is
-     replaced with get_callee_fndecl and gcc.dg/tree-ssa/ssa-pre-13.c
-     is compiled.  */
-  callfn = gimple_call_fn (call);
-  temp.type = TREE_TYPE (callfn);
-  temp.opcode = TREE_CODE (callfn);
-  temp.op0 = callfn;
-  VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
-
+  /* Copy the call arguments.  As they can be references as well,
+     just chain them together.  */
   for (i = 0; i < gimple_call_num_args (call); ++i)
     {
       tree callarg = gimple_call_arg (call, i);
-      memset (&temp, 0, sizeof (temp));
-      temp.type = TREE_TYPE (callarg);
-      temp.opcode = TREE_CODE (callarg);
-      temp.op0 = callarg;
-      VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+      copy_reference_ops_from_ref (callarg, result);
     }
   return;
 }
index 923be1931630deb2d7a7a6c94279163d379f0882..d648cd9bb94b7a516b3541707b7aa3349fc0e8ea 100644 (file)
@@ -174,6 +174,7 @@ vn_nary_op_t vn_nary_op_insert_stmt (gimple, tree);
 vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code,
                                       tree, tree, tree, tree,
                                       tree, tree, unsigned int);
+void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
 void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
 tree vn_reference_lookup_pieces (VEC (tree, gc) *,
                                 VEC (vn_reference_op_s, heap) *,