]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* tree-cfgcleanup. (cleanup_control_expr_graph) <GIMPLE_COND>: Remove
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 17 Sep 2012 14:50:13 +0000 (14:50 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 17 Sep 2012 14:50:13 +0000 (14:50 +0000)
code doing propagation from degenerate PHI nodes.
* tree-ssa-loop-ivcanon.c (propagate_into_all_uses): New function.
(propagate_constants_for_unrolling): Likewise.
(tree_unroll_loops_completely): If the current loop has been unrolled
and its father isn't the entire function, propagate constants within
the new basic blocks by means of propagate_constants_for_unrolling.

From-SVN: r191387

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/loop_optimization12.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/loop_optimization12.ads [new file with mode: 0644]
gcc/tree-cfgcleanup.c
gcc/tree-ssa-loop-ivcanon.c

index f406688442eda35ecc5f91339eab3bc4c300c3c0..587f878be60eb7e14fdf63423e55eace68396fdd 100644 (file)
@@ -1,3 +1,13 @@
+2012-09-17  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * tree-cfgcleanup. (cleanup_control_expr_graph) <GIMPLE_COND>: Remove
+       code doing propagation from degenerate PHI nodes.
+       * tree-ssa-loop-ivcanon.c (propagate_into_all_uses): New function.
+       (propagate_constants_for_unrolling): Likewise.
+       (tree_unroll_loops_completely): If the current loop has been unrolled
+       and its father isn't the entire function, propagate constants within
+       the new basic blocks by means of propagate_constants_for_unrolling.
+
 2012-09-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/54563
index 2cbdb5a4b6dac683ec04fbbbdd4e218c73fabbfd..7581988f70150b9072ff0d3de79dace5a498dbc1 100644 (file)
@@ -1,3 +1,7 @@
+2012-09-17  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/loop_optimization12.ad[sb]: New test.
+
 2012-09-17  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/54285
diff --git a/gcc/testsuite/gnat.dg/loop_optimization12.adb b/gcc/testsuite/gnat.dg/loop_optimization12.adb
new file mode 100644 (file)
index 0000000..2408746
--- /dev/null
@@ -0,0 +1,22 @@
+-- { dg-do compile }
+-- { dg-options "-O2" }
+
+package body Loop_Optimization12 is
+
+  procedure Reset (S : Rec_Ptr) is
+  begin
+    for I in Enum1 loop
+      S.F (I).all := (others =>
+                       (others =>
+                         (others =>
+                           (others =>
+                             (others =>
+                               (others =>
+                                 (others =>
+                                   (others =>
+                                    (others =>
+                                      (others => 0))))))))));
+    end loop;
+  end;
+
+end Loop_Optimization12;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization12.ads b/gcc/testsuite/gnat.dg/loop_optimization12.ads
new file mode 100644 (file)
index 0000000..0ed4e8b
--- /dev/null
@@ -0,0 +1,27 @@
+package Loop_Optimization12 is
+
+  type Enum1 is (A, B, C, D, E, F, G, H, I, J);
+
+  type Enum2 is (A, B, C);
+
+  type Enum3 is (A, B, C, D, E, F);
+
+  type Enum4 is (A, B, C, D);
+
+  type Enum5 is (A, B, C, D, E);
+
+  type Arr is array (Enum3, Enum4, Enum4, Enum5, Enum5, Enum3,
+                     Enum2, Enum3, Enum5, Enum3) of Natural;
+
+  type Arr_Ptr is access Arr;
+  type Ext_Arr is array (Enum1) of Arr_Ptr;
+
+  type Rec is record
+    F : Ext_Arr;
+  end record;
+
+  type Rec_Ptr is access Rec;
+
+  procedure Reset (S : Rec_Ptr);
+
+end Loop_Optimization12;
index 45f33682e30524a88bf766f500edda59d0676948..9c5228614011bf4496957ad304c0d24946159494 100644 (file)
@@ -88,40 +88,11 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi)
       switch (gimple_code (stmt))
        {
        case GIMPLE_COND:
-         {
-           tree lhs = gimple_cond_lhs (stmt);
-           tree rhs = gimple_cond_rhs (stmt);
-           /* For conditions try harder and lookup single-argument
-              PHI nodes.  Only do so from the same basic-block though
-              as other basic-blocks may be dead already.  */
-           if (TREE_CODE (lhs) == SSA_NAME
-               && !name_registered_for_update_p (lhs))
-             {
-               gimple def_stmt = SSA_NAME_DEF_STMT (lhs);
-               if (gimple_code (def_stmt) == GIMPLE_PHI
-                   && gimple_phi_num_args (def_stmt) == 1
-                   && gimple_bb (def_stmt) == gimple_bb (stmt)
-                   && (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME
-                       || !name_registered_for_update_p (PHI_ARG_DEF (def_stmt,
-                                                                      0))))
-                 lhs = PHI_ARG_DEF (def_stmt, 0);
-             }
-           if (TREE_CODE (rhs) == SSA_NAME
-               && !name_registered_for_update_p (rhs))
-             {
-               gimple def_stmt = SSA_NAME_DEF_STMT (rhs);
-               if (gimple_code (def_stmt) == GIMPLE_PHI
-                   && gimple_phi_num_args (def_stmt) == 1
-                   && gimple_bb (def_stmt) == gimple_bb (stmt)
-                   && (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME
-                       || !name_registered_for_update_p (PHI_ARG_DEF (def_stmt,
-                                                                      0))))
-                 rhs = PHI_ARG_DEF (def_stmt, 0);
-             }
-           val = fold_binary_loc (loc, gimple_cond_code (stmt),
-                                  boolean_type_node, lhs, rhs);
-           break;
-         }
+         val = fold_binary_loc (loc, gimple_cond_code (stmt),
+                                boolean_type_node,
+                                gimple_cond_lhs (stmt),
+                                gimple_cond_rhs (stmt));
+         break;
 
        case GIMPLE_SWITCH:
          val = gimple_switch_index (stmt);
index e1584b44e93e4a259609db3a96c5b524309e5bfe..1e44dd4c7355607e633127014d3299910b0a13b5 100644 (file)
@@ -503,6 +503,80 @@ canonicalize_induction_variables (void)
   return 0;
 }
 
+/* Propagate VAL into all uses of SSA_NAME.  */
+
+static void
+propagate_into_all_uses (tree ssa_name, tree val)
+{
+  imm_use_iterator iter;
+  gimple use_stmt;
+
+  FOR_EACH_IMM_USE_STMT (use_stmt, iter, ssa_name)
+    {
+      gimple_stmt_iterator use_stmt_gsi = gsi_for_stmt (use_stmt);
+      use_operand_p use;
+
+      FOR_EACH_IMM_USE_ON_STMT (use, iter)
+       SET_USE (use, val);
+
+      if (is_gimple_assign (use_stmt)
+         && get_gimple_rhs_class (gimple_assign_rhs_code (use_stmt))
+            == GIMPLE_SINGLE_RHS)
+       {
+         tree rhs = gimple_assign_rhs1 (use_stmt);
+
+         if (TREE_CODE (rhs) == ADDR_EXPR)
+           recompute_tree_invariant_for_addr_expr (rhs);
+       }
+
+      fold_stmt_inplace (&use_stmt_gsi);
+      update_stmt (use_stmt);
+    }
+}
+
+/* Propagate constant SSA_NAMEs defined in basic block BB.  */
+
+static void
+propagate_constants_for_unrolling (basic_block bb)
+{
+  gimple_stmt_iterator gsi;
+
+  /* Look for degenerate PHI nodes with constant argument.  */
+  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
+    {
+      gimple phi = gsi_stmt (gsi);
+      tree result = gimple_phi_result (phi);
+      tree arg = gimple_phi_arg_def (phi, 0);
+
+      if (gimple_phi_num_args (phi) == 1 && TREE_CODE (arg) == INTEGER_CST)
+       {
+         propagate_into_all_uses (result, arg);
+         gsi_remove (&gsi, true);
+         release_ssa_name (result);
+       }
+      else
+       gsi_next (&gsi);
+    }
+
+  /* Look for assignments to SSA names with constant RHS.  */
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+    {
+      gimple stmt = gsi_stmt (gsi);
+      tree lhs;
+
+      if (is_gimple_assign (stmt)
+         && (lhs = gimple_assign_lhs (stmt), TREE_CODE (lhs) == SSA_NAME)
+         && gimple_assign_rhs_code (stmt) == INTEGER_CST)
+       {
+         propagate_into_all_uses (lhs, gimple_assign_rhs1 (stmt));
+         gsi_remove (&gsi, true);
+         release_ssa_name (lhs);
+       }
+      else
+       gsi_next (&gsi);
+    }
+}
+
 /* Unroll LOOPS completely if they iterate just few times.  Unless
    MAY_INCREASE_SIZE is true, perform the unrolling only if the
    size of the code does not increase.  */
@@ -510,6 +584,7 @@ canonicalize_induction_variables (void)
 unsigned int
 tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
 {
+  VEC(loop_p,stack) *father_stack = VEC_alloc (loop_p, stack, 16);
   loop_iterator li;
   struct loop *loop;
   bool changed;
@@ -522,22 +597,51 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
 
       FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
        {
+         struct loop *loop_father = loop_outer (loop);
+
          if (may_increase_size && optimize_loop_for_speed_p (loop)
              /* Unroll outermost loops only if asked to do so or they do
                 not cause code growth.  */
-             && (unroll_outer
-                 || loop_outer (loop_outer (loop))))
+             && (unroll_outer || loop_outer (loop_father)))
            ul = UL_ALL;
          else
            ul = UL_NO_GROWTH;
-         changed |= canonicalize_loop_induction_variables
-                      (loop, false, ul, !flag_tree_loop_ivcanon);
+
+         if (canonicalize_loop_induction_variables (loop, false, ul,
+                                                    !flag_tree_loop_ivcanon))
+           {
+             changed = true;
+             /* If we'll continue unrolling, we need to propagate constants
+                within the new basic blocks to fold away induction variable
+                computations; otherwise, the size might blow up before the
+                iteration is complete and the IR eventually cleaned up.  */
+             if (loop_outer (loop_father) && !loop_father->aux)
+               {
+                 VEC_safe_push (loop_p, stack, father_stack, loop_father);
+                 loop_father->aux = loop_father;
+               }
+           }
        }
 
       if (changed)
        {
+         struct loop **iter;
+         unsigned i;
+
          update_ssa (TODO_update_ssa);
 
+         /* Propagate the constants within the new basic blocks.  */
+         FOR_EACH_VEC_ELT (loop_p, father_stack, i, iter)
+           {
+             unsigned j;
+             basic_block *body = get_loop_body_in_dom_order (*iter);
+             for (j = 0; j < (*iter)->num_nodes; j++)
+               propagate_constants_for_unrolling (body[j]);
+             free (body);
+             (*iter)->aux = NULL;
+           }
+         VEC_truncate (loop_p, father_stack, 0);
+
          /* This will take care of removing completely unrolled loops
             from the loop structures so we can continue unrolling now
             innermost loops.  */
@@ -552,5 +656,7 @@ tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
   while (changed
         && ++iteration <= PARAM_VALUE (PARAM_MAX_UNROLL_ITERATIONS));
 
+  VEC_free (loop_p, stack, father_stack);
+
   return 0;
 }