OSDN Git Service

PR tree-optimization/28411
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 28 Aug 2006 21:15:19 +0000 (21:15 +0000)
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 28 Aug 2006 21:15:19 +0000 (21:15 +0000)
* double-int.c (double_int_div): Use double_int_divmod.
(double_int_divmod, double_int_sdivmod, double_int_udivmod,
double_int_mod, double_int_smod, double_int_umod): New functions.
* double-int.h (double_int_divmod, double_int_sdivmod,
double_int_udivmod, double_int_mod, double_int_smod, double_int_umod):
Declare.
* tree-ssa-loop-ivopts.c (constant_multiple_of): Returns the result
in double_int.
(get_computation_aff, get_computation_cost_at): Handle double_int
return type of constant_multiple_of.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116529 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/double-int.c
gcc/double-int.h
gcc/tree-ssa-loop-ivopts.c

index 733fa47..b333fe2 100644 (file)
@@ -1,3 +1,17 @@
+2006-08-28  Zdenek Dvorak <dvorakz@suse.cz>
+
+       PR tree-optimization/28411
+       * double-int.c (double_int_div): Use double_int_divmod.
+       (double_int_divmod, double_int_sdivmod, double_int_udivmod,
+       double_int_mod, double_int_smod, double_int_umod): New functions.
+       * double-int.h (double_int_divmod, double_int_sdivmod,
+       double_int_udivmod, double_int_mod, double_int_smod, double_int_umod):
+       Declare.
+       * tree-ssa-loop-ivopts.c (constant_multiple_of): Returns the result
+       in double_int.
+       (get_computation_aff, get_computation_cost_at): Handle double_int
+       return type of constant_multiple_of.
+
 2006-08-28  Kazu Hirata  <kazu@codesourcery.com>
 
        PR middle-end/26632
 2006-08-28  Kazu Hirata  <kazu@codesourcery.com>
 
        PR middle-end/26632
index 5a7b51d..3be0abf 100644 (file)
@@ -203,20 +203,48 @@ double_int_neg (double_int a)
 
 /* Returns A / B (computed as unsigned depending on UNS, and rounded as
    specified by CODE).  CODE is enum tree_code in fact, but double_int.h
 
 /* Returns A / B (computed as unsigned depending on UNS, and rounded as
    specified by CODE).  CODE is enum tree_code in fact, but double_int.h
-   must be included before tree.h.  */
+   must be included before tree.h.  The remainder after the division is
+   stored to MOD.  */
 
 double_int
 
 double_int
-double_int_div (double_int a, double_int b, bool uns, unsigned code)
+double_int_divmod (double_int a, double_int b, bool uns, unsigned code,
+                  double_int *mod)
 {
 {
-  unsigned HOST_WIDE_INT rem_lo;
-  HOST_WIDE_INT rem_hi;
   double_int ret;
 
   div_and_round_double (code, uns, a.low, a.high, b.low, b.high,
   double_int ret;
 
   div_and_round_double (code, uns, a.low, a.high, b.low, b.high,
-                       &ret.low, &ret.high, &rem_lo, &rem_hi);
+                       &ret.low, &ret.high, &mod->low, &mod->high);
   return ret;
 }
 
   return ret;
 }
 
+/* The same as double_int_divmod with UNS = false.  */
+
+double_int
+double_int_sdivmod (double_int a, double_int b, unsigned code, double_int *mod)
+{
+  return double_int_divmod (a, b, false, code, mod);
+}
+
+/* The same as double_int_divmod with UNS = true.  */
+
+double_int
+double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod)
+{
+  return double_int_divmod (a, b, true, code, mod);
+}
+
+/* Returns A / B (computed as unsigned depending on UNS, and rounded as
+   specified by CODE).  CODE is enum tree_code in fact, but double_int.h
+   must be included before tree.h.  */
+
+double_int
+double_int_div (double_int a, double_int b, bool uns, unsigned code)
+{
+  double_int mod;
+
+  return double_int_divmod (a, b, uns, code, &mod);
+}
+
 /* The same as double_int_div with UNS = false.  */
 
 double_int
 /* The same as double_int_div with UNS = false.  */
 
 double_int
@@ -233,6 +261,35 @@ double_int_udiv (double_int a, double_int b, unsigned code)
   return double_int_div (a, b, true, code);
 }
 
   return double_int_div (a, b, true, code);
 }
 
+/* Returns A % B (computed as unsigned depending on UNS, and rounded as
+   specified by CODE).  CODE is enum tree_code in fact, but double_int.h
+   must be included before tree.h.  */
+
+double_int
+double_int_mod (double_int a, double_int b, bool uns, unsigned code)
+{
+  double_int mod;
+
+  double_int_divmod (a, b, uns, code, &mod);
+  return mod;
+}
+
+/* The same as double_int_mod with UNS = false.  */
+
+double_int
+double_int_smod (double_int a, double_int b, unsigned code)
+{
+  return double_int_mod (a, b, false, code);
+}
+
+/* The same as double_int_mod with UNS = true.  */
+
+double_int
+double_int_umod (double_int a, double_int b, unsigned code)
+{
+  return double_int_mod (a, b, true, code);
+}
+
 /* Constructs tree in type TYPE from with value given by CST.  */
 
 tree
 /* Constructs tree in type TYPE from with value given by CST.  */
 
 tree
index f37bcb2..eddd7b7 100644 (file)
@@ -116,6 +116,12 @@ unsigned HOST_WIDE_INT double_int_to_uhwi (double_int);
 double_int double_int_div (double_int, double_int, bool, unsigned);
 double_int double_int_sdiv (double_int, double_int, unsigned);
 double_int double_int_udiv (double_int, double_int, unsigned);
 double_int double_int_div (double_int, double_int, bool, unsigned);
 double_int double_int_sdiv (double_int, double_int, unsigned);
 double_int double_int_udiv (double_int, double_int, unsigned);
+double_int double_int_mod (double_int, double_int, bool, unsigned);
+double_int double_int_smod (double_int, double_int, unsigned);
+double_int double_int_umod (double_int, double_int, unsigned);
+double_int double_int_divmod (double_int, double_int, bool, unsigned, double_int *);
+double_int double_int_sdivmod (double_int, double_int, unsigned, double_int *);
+double_int double_int_udivmod (double_int, double_int, unsigned, double_int *);
 bool double_int_negative_p (double_int);
 int double_int_cmp (double_int, double_int, bool);
 int double_int_scmp (double_int, double_int);
 bool double_int_negative_p (double_int);
 int double_int_cmp (double_int, double_int, bool);
 int double_int_scmp (double_int, double_int);
index 2ead549..ae1905d 100644 (file)
@@ -2554,21 +2554,27 @@ tree_int_cst_sign_bit (tree t)
   return (w >> bitno) & 1;
 }
 
   return (w >> bitno) & 1;
 }
 
-/* If we can prove that TOP = cst * BOT for some constant cst in TYPE,
-   return cst.  Otherwise return NULL_TREE.  */
+/* If we can prove that TOP = cst * BOT for some constant cst,
+   store cst to MUL and return true.  Otherwise return false.
+   The returned value is always sign-extended, regardless of the
+   signedness of TOP and BOT.  */
 
 
-static tree
-constant_multiple_of (tree type, tree top, tree bot)
+static bool
+constant_multiple_of (tree top, tree bot, double_int *mul)
 {
 {
-  tree res, mby, p0, p1;
+  tree mby;
   enum tree_code code;
   enum tree_code code;
-  bool negate;
+  double_int res, p0, p1;
+  unsigned precision = TYPE_PRECISION (TREE_TYPE (top));
 
   STRIP_NOPS (top);
   STRIP_NOPS (bot);
 
   if (operand_equal_p (top, bot, 0))
 
   STRIP_NOPS (top);
   STRIP_NOPS (bot);
 
   if (operand_equal_p (top, bot, 0))
-    return build_int_cst (type, 1);
+    {
+      *mul = double_int_one;
+      return true;
+    }
 
   code = TREE_CODE (top);
   switch (code)
 
   code = TREE_CODE (top);
   switch (code)
@@ -2576,60 +2582,40 @@ constant_multiple_of (tree type, tree top, tree bot)
     case MULT_EXPR:
       mby = TREE_OPERAND (top, 1);
       if (TREE_CODE (mby) != INTEGER_CST)
     case MULT_EXPR:
       mby = TREE_OPERAND (top, 1);
       if (TREE_CODE (mby) != INTEGER_CST)
-       return NULL_TREE;
+       return false;
 
 
-      res = constant_multiple_of (type, TREE_OPERAND (top, 0), bot);
-      if (!res)
-       return NULL_TREE;
+      if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &res))
+       return false;
 
 
-      return fold_binary_to_constant (MULT_EXPR, type, res,
-                                     fold_convert (type, mby));
+      *mul = double_int_sext (double_int_mul (res, tree_to_double_int (mby)),
+                             precision);
+      return true;
 
     case PLUS_EXPR:
     case MINUS_EXPR:
 
     case PLUS_EXPR:
     case MINUS_EXPR:
-      p0 = constant_multiple_of (type, TREE_OPERAND (top, 0), bot);
-      if (!p0)
-       return NULL_TREE;
-      p1 = constant_multiple_of (type, TREE_OPERAND (top, 1), bot);
-      if (!p1)
-       return NULL_TREE;
+      if (!constant_multiple_of (TREE_OPERAND (top, 0), bot, &p0)
+         || !constant_multiple_of (TREE_OPERAND (top, 1), bot, &p1))
+       return false;
 
 
-      return fold_binary_to_constant (code, type, p0, p1);
+      if (code == MINUS_EXPR)
+       p1 = double_int_neg (p1);
+      *mul = double_int_sext (double_int_add (p0, p1), precision);
+      return true;
 
     case INTEGER_CST:
       if (TREE_CODE (bot) != INTEGER_CST)
 
     case INTEGER_CST:
       if (TREE_CODE (bot) != INTEGER_CST)
-       return NULL_TREE;
-
-      bot = fold_convert (type, bot);
-      top = fold_convert (type, top);
-
-      /* If BOT seems to be negative, try dividing by -BOT instead, and negate
-        the result afterwards.  */
-      if (tree_int_cst_sign_bit (bot))
-       {
-         negate = true;
-         bot = fold_unary_to_constant (NEGATE_EXPR, type, bot);
-       }
-      else
-       negate = false;
-
-      /* Ditto for TOP.  */
-      if (tree_int_cst_sign_bit (top))
-       {
-         negate = !negate;
-         top = fold_unary_to_constant (NEGATE_EXPR, type, top);
-       }
-
-      if (!zero_p (fold_binary_to_constant (TRUNC_MOD_EXPR, type, top, bot)))
-       return NULL_TREE;
+       return false;
 
 
-      res = fold_binary_to_constant (EXACT_DIV_EXPR, type, top, bot);
-      if (negate)
-       res = fold_unary_to_constant (NEGATE_EXPR, type, res);
-      return res;
+      p0 = double_int_sext (tree_to_double_int (bot), precision);
+      p1 = double_int_sext (tree_to_double_int (top), precision);
+      if (double_int_zero_p (p1))
+       return false;
+      *mul = double_int_sext (double_int_sdivmod (p0, p1, FLOOR_DIV_EXPR, &res),
+                             precision);
+      return double_int_zero_p (res);
 
     default:
 
     default:
-      return NULL_TREE;
+      return false;
     }
 }
 
     }
 }
 
@@ -2986,6 +2972,7 @@ get_computation_aff (struct loop *loop,
   HOST_WIDE_INT ratioi;
   struct affine_tree_combination cbase_aff, expr_aff;
   tree cstep_orig = cstep, ustep_orig = ustep;
   HOST_WIDE_INT ratioi;
   struct affine_tree_combination cbase_aff, expr_aff;
   tree cstep_orig = cstep, ustep_orig = ustep;
+  double_int rat;
 
   if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
     {
 
   if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
     {
@@ -3040,21 +3027,15 @@ get_computation_aff (struct loop *loop,
     }
   else
     {
     }
   else
     {
-      ratio = constant_multiple_of (uutype, ustep_orig, cstep_orig);
-      if (!ratio)
+      if (!constant_multiple_of (ustep_orig, cstep_orig, &rat))
        return false;
        return false;
+      ratio = double_int_to_tree (uutype, rat);
 
       /* Ratioi is only used to detect special cases when the multiplicative
 
       /* Ratioi is only used to detect special cases when the multiplicative
-        factor is 1 or -1, so if we cannot convert ratio to HOST_WIDE_INT,
-        we may set it to 0.  We prefer cst_and_fits_in_hwi/int_cst_value
-        to integer_onep/integer_all_onesp, since the former ignores
-        TREE_OVERFLOW.  */
-      if (cst_and_fits_in_hwi (ratio))
-       ratioi = int_cst_value (ratio);
-      else if (integer_onep (ratio))
-       ratioi = 1;
-      else if (integer_all_onesp (ratio))
-       ratioi = -1;
+        factor is 1 or -1, so if rat does not fit to HOST_WIDE_INT, we may
+        set it to 0.  */
+      if (double_int_fits_in_shwi_p (rat))
+       ratioi = double_int_to_shwi (rat);
       else
        ratioi = 0;
     }
       else
        ratioi = 0;
     }
@@ -3775,19 +3756,13 @@ get_computation_cost_at (struct ivopts_data *data,
     }
   else
     {
     }
   else
     {
-      tree rat;
+      double_int rat;
       
       
-      rat = constant_multiple_of (utype, ustep, cstep);
-    
-      if (!rat)
+      if (!constant_multiple_of (ustep, cstep, &rat))
        return INFTY;
        return INFTY;
-
-      if (cst_and_fits_in_hwi (rat))
-       ratio = int_cst_value (rat);
-      else if (integer_onep (rat))
-       ratio = 1;
-      else if (integer_all_onesp (rat))
-       ratio = -1;
+    
+      if (double_int_fits_in_shwi_p (rat))
+       ratio = double_int_to_shwi (rat);
       else
        return INFTY;
     }
       else
        return INFTY;
     }