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]

Re: [patch] (-fstrict-overflow) optimize counted loops on signed iv


agree, this macro was a little bit "heavy".

here is new patch using TYPE_OVERFLOW_UNDEFINED, and added a few comments.

thanks,

ps: unrelated to this patch, but I noticed that in fold-const.c line 4003 TYPE_UNSIGNED is checked twice :

if  (!TYPE_UNSIGNED (arg0_type)
	&& !TYPE_OVERFLOW_UNDEFINED (arg0_type))

-c

Ian Lance Taylor wrote:
"Richard Guenther" <richard.guenther@gmail.com> writes:


Another minor change in this patch is the addition of
FLAG_OVERFLOW_UNDEFINED to avoid testing the overflow flags for each
type like in :

  if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
    || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op1)))
      return false;

That doesn't work unless you want to make unsigned overflow undefined as well.


I think it works in the way that he uses it, but I think it's a bad
idea because it will be error-prone.  And it's a micro-optimization
which should be unnecessary: there won't be any stores between
accesses to the global variables, so the compiler should not need to
load them twice.

Christian, can you test your patch without that change?

Ian


Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c	(.../vendor/tags/4.3.20070209)	(revision 77)
+++ gcc/tree-ssa-loop-niter.c	(.../branches/4.3_devs_loop_overflow)	(revision 77)
@@ -169,6 +169,80 @@
   return true;
 }
 
+/* Checks whether the number of iterations is a constant value if iv1 is relative
+   to iv0. If we are allowed to optimize overflows, it may be a constant when the
+   control variable wraps.
+   iv0 is the chrec for the initial value of the control variable.
+   iv1 is the chrec for the stop value.
+   Optimizes loops like (i = v; i <= v+cst; i++).  */
+
+static bool 
+relative_count_iv (affine_iv *iv0, affine_iv *iv1)
+{
+  enum tree_code code_base0;
+  enum tree_code code_base1;
+
+  tree op0 = iv0->base;
+  tree op1 = iv1->base;
+
+  if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
+      || !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op1)))
+    return false;
+
+  STRIP_SIGN_NOPS (op0);
+  STRIP_SIGN_NOPS (op1);
+
+  code_base0 = TREE_CODE (op0);
+  code_base1 = TREE_CODE (op1);
+
+  /* iv0 -> {a+cst, +/-, cst}, iv1 -> {a+cst, +/-, cst}.  */
+  if ((code_base0 == PLUS_EXPR && code_base1 == PLUS_EXPR)
+      || (code_base0 == MINUS_EXPR && code_base1 == MINUS_EXPR))
+    {
+      tree opb0 = TREE_OPERAND (op0, 0);
+      tree opb1 = TREE_OPERAND (op1, 0);
+
+      STRIP_SIGN_NOPS (opb0);
+      STRIP_SIGN_NOPS (opb1);
+
+      if (TREE_CODE (opb0) == SSA_NAME && TREE_CODE (opb1) == SSA_NAME
+	  && SSA_NAME_DEF_STMT(opb0) == SSA_NAME_DEF_STMT(opb1)
+	  && TREE_CONSTANT (TREE_OPERAND (op0, 1))
+	  && TREE_CONSTANT (TREE_OPERAND (op1, 1)))
+	return true;
+    }
+
+  /* iv0 -> {a, +/-, cst}, iv1 -> {a+cst, +/-, cst}.  */
+  else if (code_base0 == SSA_NAME
+	   && (code_base1 == PLUS_EXPR || code_base1 == MINUS_EXPR))
+    {
+      tree opb1 = TREE_OPERAND (op1, 0);
+
+      STRIP_SIGN_NOPS (opb1);
+
+      if (TREE_CODE (op0) == SSA_NAME && TREE_CODE (opb1) == SSA_NAME
+	  && SSA_NAME_DEF_STMT(op0) == SSA_NAME_DEF_STMT(opb1)
+	  && TREE_CONSTANT (TREE_OPERAND (op1, 1)))
+	return true;
+    }
+
+  /* iv0 -> {a+cst, +/-, cst}, iv1 -> {a, +/-, cst}.  */
+  else if (code_base1 == SSA_NAME
+	   && (code_base0 == PLUS_EXPR || code_base0 == MINUS_EXPR))
+    {
+      tree opb0 = TREE_OPERAND (op0, 0);
+
+      STRIP_SIGN_NOPS (opb0);
+
+      if (TREE_CODE (opb0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME
+	  && SSA_NAME_DEF_STMT(opb0) == SSA_NAME_DEF_STMT(op1)
+	  && TREE_CONSTANT (TREE_OPERAND (op0, 1)))
+	return true;
+    }
+
+  return false;
+}
+
 /* Checks whether we can determine the final value of the control variable
    of the loop with ending condition IV0 < IV1 (computed in TYPE).
    DELTA is the difference IV1->base - IV0->base, STEP is the absolute value
@@ -236,7 +310,8 @@
     niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
 				      niter->assumptions,
 				      assumption);
-  if (!integer_zerop (noloop))
+
+  if (!integer_zerop (noloop) && !relative_count_iv (iv0, iv1))
     niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
 				      niter->may_be_zero,
 				      noloop);
@@ -367,7 +442,8 @@
   if (!integer_nonzerop (assumption))
     niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
 				      niter->assumptions, assumption);
-  if (!integer_zerop (mbz))
+
+  if (!integer_zerop (mbz) && !relative_count_iv (iv0, iv1))
     niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
 				      niter->may_be_zero, mbz);
 }
@@ -413,8 +489,9 @@
 	     
 	 In both cases # of iterations is iv1->base - iv0->base, assuming that
 	 iv1->base >= iv0->base.  */
-      niter->may_be_zero = fold_build2 (LT_EXPR, boolean_type_node,
-					iv1->base, iv0->base);
+      if (!relative_count_iv (iv0, iv1))
+	niter->may_be_zero = fold_build2 (LT_EXPR, boolean_type_node,
+					  iv1->base, iv0->base);
       niter->niter = delta;
       return true;
     }
Index: gcc/testsuite/gcc.dg/strict-overflow-5.c
===================================================================
--- gcc/testsuite/gcc.dg/strict-overflow-5.c	(.../vendor/tags/4.3.20070209)	(revision 0)
+++ gcc/testsuite/gcc.dg/strict-overflow-5.c	(.../branches/4.3_devs_loop_overflow)	(revision 77)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* We can only unroll when using strict overflow semantics.  */
+
+int foo (int i)
+{
+  int index;
+  int r=0;
+ 
+  for (index = i; index <= i+4; index+=2) 
+    r++;
+ 
+  return r;
+}
+
+/* { dg-final { scan-tree-dump-times "r = 3" 1 "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
+

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