This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR/19210: Add -{f,W}unsafe-loop-optimizations


This patch adds unsafe loop optimizations that were in the old loop optimizer, enabling them only with a specific flag -funsafe-loop-optimizations. At the same time, -Wunsafe-loop-optimizations warns of loops that either could not be safely optimized or were "unsafely" optimized (depending on the presence of the other option).

-Wall, -Wextra and -O options do not enable any of the new flags.

Actually the old loop optimizer was a bit brittle in this respect. At times it checked for such strange loops, like in biv_fits_mode_p where a comment says

     /* If the increment is +1, and the exit test is a <, the BIV
        cannot overflow.  (For <=, we have the problematic case that
        the comparison value might be the maximum value of the range.)  */

But in the end, the loops in the testcases were all optimized.

Bootstrapped/regtested powerpc-apple-darwin, ok for mainline?

Paolo
gcc:
2005-05-05  Paolo Bonzini  <bonzini@gnu.org>
            Zdenek Dvorak  <dvorakz@suse.cz>

	PR tree-optimization/19210
	* common.opt (Wunsafe-loop-optimizations, funsafe-loop-optimizations):
	New.
	* Makefile.in (tree-ssa-loop-niter.o): Depend intl.o.
	* loop-iv.c (get_simple_loop_desc): If -funsafe-loop-optimizations,
	rely on unproven assumptions.
	* predict.c (predict_loops): Adjust call to number_of_iterations_exit.
	* tree-flow.h (number_of_iterations_exit): Add final parameter.
	* tree-scalar-evolution.c (number_of_iterations_in_loop): Adjust call
	to number_of_iterations_exit.
	* tree-ssa-loop-ivopts.c (niter_for_exit): Likewise.
	* tree-ssa-niter.c (find_loop_niter,
	estimate_numbers_of_iterations_loop): Likewise.
	(number_of_iterations_exit): Honor the new options.
	* doc/invoke.texi (Wunsafe-loop-optimizations,
	funsafe-loop-optimizations): Document them.

testsuite:
2005-05-05  Paolo Bonzini  <bonzini@gnu.org>

	* gcc.dg/tree-ssa/pr19210-1.c: New.
	* gcc.dg/tree-ssa/pr19210-2.c: New.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1478
diff -p -u -u -r1.1478 Makefile.in
--- Makefile.in	5 May 2005 03:04:15 -0000	1.1478
+++ Makefile.in	5 May 2005 16:28:26 -0000
@@ -1748,7 +1748,7 @@ tree-ssa-loop-unswitch.o : tree-ssa-loop
 tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
    tree-inline.h output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
-   $(FLAGS_H) tree-pass.h $(SCEV_H) $(TREE_DATA_REF_H)
+   $(FLAGS_H) tree-pass.h $(SCEV_H) $(TREE_DATA_REF_H) intl.h
 tree-ssa-loop-ivcanon.o : tree-ssa-loop-ivcanon.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
    tree-inline.h output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
Index: common.opt
===================================================================
RCS file: /cvs/gcc/gcc/gcc/common.opt,v
retrieving revision 1.70
diff -p -u -u -r1.70 common.opt
--- common.opt	4 May 2005 01:36:09 -0000	1.70
+++ common.opt	5 May 2005 16:28:26 -0000
@@ -89,6 +89,10 @@ Wlarger-than-
 Common RejectNegative Joined UInteger
 -Wlarger-than-<number>	Warn if an object is larger than <number> bytes
 
+Wunsafe-loop-optimizations
+Common Var(warn_unsafe_loop_optimizations)
+Warn if a loop cannot be optimized due to nontrivial assumptions.
+
 Wmissing-noreturn
 Common Var(warn_missing_noreturn)
 Warn about functions which might be candidates for __attribute__((noreturn))
@@ -928,6 +932,13 @@ funroll-all-loops
 Common Report Var(flag_unroll_all_loops)
 Perform loop unrolling for all loops
 
+; Nonzero means that loop optimizer may assume that the induction variables
+; that control loops do not overflow and that the loops with nontrivial
+; exit condition are not infinite
+funsafe-loop-optimizations
+Common Report Var(flag_unsafe_loop_optimizations)
+Allow loop optimizations to assume that loops behave in normal way
+
 ; Nonzero means that unsafe floating-point math optimizations are allowed
 ; for the sake of speed.  IEEE compliance is not guaranteed, and operations
 ; are allowed to assume that their arguments and results are "normal"
Index: loop-iv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-iv.c,v
retrieving revision 2.31
diff -p -u -u -r2.31 loop-iv.c
--- loop-iv.c	1 Apr 2005 14:17:34 -0000	2.31
+++ loop-iv.c	5 May 2005 16:28:27 -0000
@@ -2671,6 +2672,14 @@ get_simple_loop_desc (struct loop *loop)
   find_simple_exit (loop, desc);
   loop->aux = desc;
 
+  if (desc->simple_p && flag_unsafe_loop_optimizations)
+    {
+      /* Assume that no overflow happens and that the loop is finite.  
+	 We already warned at the tree level.  */
+      desc->assumptions = NULL_RTX;
+      desc->infinite = NULL_RTX;
+    }
+
   return desc;
 }
 
Index: predict.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/predict.c,v
retrieving revision 1.145
diff -p -u -u -r1.145 predict.c
--- predict.c	5 Apr 2005 19:04:55 -0000	1.145
+++ predict.c	5 May 2005 16:28:27 -0000
@@ -620,7 +620,7 @@ predict_loops (struct loops *loops_info,
 	    {
 	      tree niter = NULL;
 
-	      if (number_of_iterations_exit (loop, exits[j], &niter_desc))
+	      if (number_of_iterations_exit (loop, exits[j], &niter_desc, false))
 		niter = niter_desc.niter;
 	      if (!niter || TREE_CODE (niter_desc.niter) != INTEGER_CST)
 	        niter = loop_niter_by_eval (loop, exits[j]);
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.101
diff -p -u -u -r2.101 tree-flow.h
--- tree-flow.h	3 May 2005 20:18:31 -0000	2.101
+++ tree-flow.h	5 May 2005 16:28:27 -0000
@@ -697,7 +697,7 @@ void tree_unroll_loops_completely (struc
 void tree_ssa_iv_optimize (struct loops *);
 
 bool number_of_iterations_exit (struct loop *, edge,
-				struct tree_niter_desc *niter);
+				struct tree_niter_desc *niter, bool);
 tree find_loop_niter (struct loop *, edge *);
 tree loop_niter_by_eval (struct loop *, edge);
 tree find_loop_niter_by_eval (struct loop *, edge *);
Index: tree-scalar-evolution.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-scalar-evolution.c,v
retrieving revision 2.23
diff -p -u -u -r2.23 tree-scalar-evolution.c
--- tree-scalar-evolution.c	2 May 2005 08:56:52 -0000	2.23
+++ tree-scalar-evolution.c	5 May 2005 16:28:27 -0000
@@ -2254,7 +2254,7 @@ number_of_iterations_in_loop (struct loo
   if (!exit)
     goto end;
 
-  if (!number_of_iterations_exit (loop, exit, &niter_desc))
+  if (!number_of_iterations_exit (loop, exit, &niter_desc, false))
     goto end;
 
   type = TREE_TYPE (niter_desc.niter);
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.69
diff -p -u -u -r2.69 tree-ssa-loop-ivopts.c
--- tree-ssa-loop-ivopts.c	4 May 2005 13:57:40 -0000	2.69
+++ tree-ssa-loop-ivopts.c	5 May 2005 16:28:27 -0000
@@ -712,7 +712,8 @@ niter_for_exit (struct ivopts_data *data
       nfe_desc = xmalloc (sizeof (struct nfe_cache_elt));
       nfe_desc->exit = exit;
       nfe_desc->valid_p = number_of_iterations_exit (data->current_loop,
-						     exit, &nfe_desc->niter);
+						     exit, &nfe_desc->niter,
+						     true);
       *slot = nfe_desc;
     }
   else
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.26
diff -p -u -u -r2.26 tree-ssa-loop-niter.c
--- tree-ssa-loop-niter.c	3 May 2005 12:19:46 -0000	2.26
+++ tree-ssa-loop-niter.c	5 May 2005 16:28:28 -0000
@@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - S
 #include "basic-block.h"
 #include "output.h"
 #include "diagnostic.h"
+#include "intl.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "cfgloop.h"
@@ -906,11 +907,14 @@ simplify_using_outer_evolutions (struct 
    EXIT (an exit edge of the LOOP) in NITER.  Returns true if some
    useful information could be derived (and fields of NITER has
    meaning described in comments at struct tree_niter_desc
-   declaration), false otherwise.  */
+   declaration), false otherwise.  If WARN is true and
+   -Wunsafe-loop-optimizations was given, warn if the optimizer is
+   going to use potentially unsafe assumptions.  */
 
 bool
 number_of_iterations_exit (struct loop *loop, edge exit,
-			   struct tree_niter_desc *niter)
+			   struct tree_niter_desc *niter,
+			   bool warn)
 {
   tree stmt, cond, type;
   tree op0, base0, step0;
@@ -990,7 +994,45 @@ number_of_iterations_exit (struct loop *
 	  = simplify_using_initial_conditions (loop,
 					       niter->may_be_zero,
 					       &niter->additional_info);
-  return integer_onep (niter->assumptions);
+
+  /* If we can prove that there is overflow or some other source of weird
+     behavior, ignore the loop even with -funsafe-loop-optimizations.  */
+  if (integer_zerop (niter->assumptions))
+    return false;
+
+  if (integer_onep (niter->assumptions))
+    return true;
+
+  /* With -funsafe-loop-optimizations we assume that nothing bad can happen.
+  if (flag_unsafe_loop_optimizations)
+    niter->assumptions = boolean_true_node;
+
+  if (warn)
+    {
+      const char *wording;
+      location_t loc = EXPR_LOCATION (stmt);
+  
+      /* We can provide a more specific warning if one of the operator is
+	 constant and the other advances by 1 or -1.  */
+      if (step1 ? !step0 && (integer_onep (step1) || integer_all_onesp (step1))
+	  	: step0 && (integer_onep (step0) || integer_all_onesp (step0)))
+        wording =
+          flag_unsafe_loop_optimizations
+          ? N_("assuming that the loop is not infinite")
+          : N_("cannot optimize possibly infinite loops");
+      else
+	wording = 
+	  flag_unsafe_loop_optimizations
+	  ? N_("assuming that the loop counter does not overflow")
+	  : N_("cannot optimize loop, the loop counter may overflow");
+
+      if (LOCATION_LINE (loc) > 0)
+	warning (OPT_Wunsafe_loop_optimizations, "%H%s", &loc, gettext (wording));
+      else
+	warning (OPT_Wunsafe_loop_optimizations, "%s", gettext (wording));
+    }
+
+  return flag_unsafe_loop_optimizations;
 }
 
 /* Try to determine the number of iterations of LOOP.  If we succeed,
@@ -1014,7 +1056,7 @@ find_loop_niter (struct loop *loop, edge
       if (!just_once_each_iteration_p (loop, ex->src))
 	continue;
 
-      if (!number_of_iterations_exit (loop, ex, &desc))
+      if (!number_of_iterations_exit (loop, ex, &desc, false))
 	continue;
 
       if (nonzero_p (desc.may_be_zero))
@@ -1351,7 +1393,7 @@ estimate_numbers_of_iterations_loop (str
   exits = get_loop_exit_edges (loop, &n_exits);
   for (i = 0; i < n_exits; i++)
     {
-      if (!number_of_iterations_exit (loop, exits[i], &niter_desc))
+      if (!number_of_iterations_exit (loop, exits[i], &niter_desc, false))
 	continue;
 
       niter = niter_desc.niter;
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.612
diff -p -u -u -r1.612 invoke.texi
--- doc/invoke.texi	3 May 2005 17:55:46 -0000	1.612
+++ doc/invoke.texi	5 May 2005 16:28:29 -0000
@@ -224,7 +224,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wimport  -Wno-import  -Winit-self  -Winline @gol
 -Wno-int-to-pointer-cast @gol
 -Wno-invalid-offsetof  -Winvalid-pch @gol
--Wlarger-than-@var{len}  -Wlong-long @gol
+-Wlarger-than-@var{len}  -Wunsafe-loop-optimizations  -Wlong-long @gol
 -Wmain  -Wmissing-braces  -Wmissing-field-initializers @gol
 -Wmissing-format-attribute  -Wmissing-include-dirs @gol
 -Wmissing-noreturn @gol
@@ -304,7 +304,7 @@ Objective-C and Objective-C++ Dialects}.
 -fno-default-inline  -fno-defer-pop -floop-optimize2 -fmove-loop-invariants @gol
 -fno-function-cse  -fno-guess-branch-probability @gol
 -fno-inline  -fno-math-errno  -fno-peephole  -fno-peephole2 @gol
--funsafe-math-optimizations  -ffinite-math-only @gol
+-funsafe-math-optimizations  -funsafe-loop-optimizations  -ffinite-math-only @gol
 -fno-trapping-math  -fno-zero-initialized-in-bss @gol
 -fomit-frame-pointer  -foptimize-register-move @gol
 -foptimize-sibling-calls  -fprefetch-loop-arrays @gol
@@ -2912,6 +2912,13 @@ global variable or whenever a built-in f
 @opindex Wlarger-than
 Warn whenever an object of larger than @var{len} bytes is defined.
 
+@item -Wunsafe-loop-optimizations
+@opindex Wunsafe-loop-optimizations
+Warn if the loop cannot be optimized because the compiler could not
+assume anything on the bounds of the loop indices.  With
+@option{-funsafe-loop-optimizations} warn if the compiler made
+such assumptions.
+
 @item -Wpointer-arith
 @opindex Wpointer-arith
 Warn about anything that depends on the ``size of'' a function type or
@@ -4617,6 +4624,15 @@ Perform loop optimizations using the new
 (loop unrolling, peeling and unswitching, loop invariant motion) are enabled
 by separate flags.
 
+@item -funsafe-loop-optimizations
+@opindex funsafe-loop-optimizations
+If given, the loop optimizer will assume that loop indices do not
+overflow, and that the loops with nontrivial exit condition are not
+infinite.  This enables a wider range of loop optimizations even if
+the loop optimizer itself cannot prove that these assumptions are valid.
+Using @option{-Wunsafe-loop-optimizations}, the compiler will warn you
+if it finds this kind of loop.
+
 @item -fcrossjumping
 @opindex crossjumping
 Perform cross-jumping transformation.  This transformation unifies equivalent code and save code size.  The
Index: testsuite/gcc.dg/tree-ssa/pr19210-1.c
===================================================================
RCS file: testsuite/gcc.dg/tree-ssa/pr19210-1.c
diff -N testsuite/gcc.dg/tree-ssa/pr19210-1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/tree-ssa/pr19210-1.c	5 May 2005 16:28:29 -0000
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunsafe-loop-optimizations" } */
+extern void g(void);
+
+void
+f (unsigned n)
+{
+  unsigned k;
+  for(k = 0;k <= n;k++) /* { dg-warning "cannot optimize.*infinite loops" } */
+    g();
+
+  for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */
+    g();
+
+  for(k = 5;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */
+    g();
+
+  for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite loops" } */
+    g();
+}
Index: testsuite/gcc.dg/tree-ssa/pr19210-2.c
===================================================================
RCS file: testsuite/gcc.dg/tree-ssa/pr19210-2.c
diff -N testsuite/gcc.dg/tree-ssa/pr19210-2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/tree-ssa/pr19210-2.c	5 May 2005 16:28:29 -0000
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -funsafe-loop-optimizations -Wunsafe-loop-optimizations" } */
+extern void g(void);
+
+void
+f (unsigned n)
+{
+  unsigned k;
+  for(k = 0;k <= n;k++) /* { dg-warning "assuming.*not infinite" } */
+    g();
+
+  for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */
+    g();
+
+  for(k = 5;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */
+    g();
+
+  for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */
+    g();
+
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]