wide-int, tree-ssa

Richard Biener richard.guenther@gmail.com
Tue Nov 26 15:09:00 GMT 2013


On Sat, Nov 23, 2013 at 8:23 PM, Mike Stump <mikestump@comcast.net> wrote:
> Richi has asked the we break the wide-int patch so that the individual port and front end maintainers can review their parts without have to go through the entire patch.    This patch covers the tree-saa code.
>
> Ok?

Same comments as to tree-affine.c apply to tree-ssa-address.c.

@@ -887,8 +886,8 @@ copy_ref_info (tree new_ref, tree old_ref)
                           && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
                               < align)))))
            {
-             unsigned int inc = (mem_ref_offset (old_ref)
-                                 - mem_ref_offset (new_ref)).low;
+             unsigned int inc = (mem_ref_offset (old_ref).to_uhwi ()
+                                 - mem_ref_offset (new_ref).to_uhwi ());
              adjust_ptr_info_misalignment (new_pi, inc);
            }
          else

other patches used .to_short_addr (), also your conversion isn't
correct - previously the subtraction was in infinite precision and only
the result (possibly) truncated.  Now the subtraction operands are
truncated - that looks wrong.

--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -98,6 +98,15 @@ along with GCC; see the file COPYING3.  If not see
    array CONST_VAL[i].VALUE.  That is fed into substitute_and_fold for
    final substitution and folding.

+   This algorithm uses wide-ints at the max precision of the target.
+   This means that, with one uninteresting exception, variables with
+   UNSIGNED types never go to VARYING because the bits above the
+   precision of the type of the variable are always zero.  The
+   uninteresting case is a variable of UNSIGNED type that has the
+   maximum precision of the target.  Such variables can go to VARYING,
+   but this causes no loss of infomation since these variables will
+   never be extended.
+

I don't understand this.  In CCP a SSA name drops to varying when
it's not constant.  How is that related to signedness or precision?!

@@ -511,21 +523,21 @@ set_lattice_value (tree var, prop_value_t new_val)

 static prop_value_t get_value_for_expr (tree, bool);
 static prop_value_t bit_value_binop (enum tree_code, tree, tree, tree);
-static void bit_value_binop_1 (enum tree_code, tree, double_int *,
double_int *,
-                              tree, double_int, double_int,
-                              tree, double_int, double_int);
+static void bit_value_binop_1 (enum tree_code, tree, widest_int *,
widest_int *,
+                              tree, widest_int, widest_int,
+                              tree, widest_int, widest_int);

please don't pass widest_int by value but instead pass it by const reference.
compared to double_int it is really large (most targets passed double_int
in two registers).

+/* Return a widest_int that can be used for bitwise simplifications
    from VAL.  */

-static double_int
-value_to_double_int (prop_value_t val)
+static widest_int
+value_to_wide_int (prop_value_t val)
 {
   if (val.value
       && TREE_CODE (val.value) == INTEGER_CST)
-    return tree_to_double_int (val.value);
-  else
-    return double_int_zero;
+    return wi::to_widest (val.value);
+
+  return 0;
 }

you also get to hope that we optimize all the widest_int return-by-value
code to elide the implied copying ... (not sure if you can do that by
adding a not implemented copy / assignment constructor - C++ folks?)

+  val.lattice_val = val.mask == -1 ? VARYING : CONSTANT;
   if (val.lattice_val == CONSTANT)

you mean this check wrt the toplevel VARYING comment?  It would
be bad if that no longer ends up VARYING.  OTOH I don't know whether
the current check is correct either - we extend the mask according to
the sign of the lattice element.  Thus the wide-int variant looks equivalent.
Note that for unsigned values we have knowledge about the bits
outside of the precision - they are zero, so techincally unsigneds
never go VARYING.

     case LT_EXPR:
     case LE_EXPR:
       {
+       widest_int o1val, o2val, o1mask, o2mask;
        int minmax, maxmin;
+
+       if ((code == GE_EXPR) || (code == GT_EXPR))
+         {
+           o1val = r2val;
+           o1mask = r2mask;
+           o2val = r1val;
+           o2mask = r1mask;
+           code = swap_tree_comparison (code);
+         }
+       else
+         {
+           o1val = r1val;
+           o1mask = r1mask;
+           o2val = r2val;
+           o2mask = r2mask;
+         }

that are pretty expensive copies, no?  Consider using

  const widest_int &o1val = swap ? r2val : r1val;

and so on.  (C++ folks?  Any idea how to avoid the repeated
conditional init in favor of sth that more resembles the original?)

diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 6ea634c..c975a97 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1643,7 +1643,7 @@ mem_refs_may_alias_p (mem_ref_p mem1, mem_ref_p mem2,
   /* Perform BASE + OFFSET analysis -- if MEM1 and MEM2 are based on the same
      object and their offset differ in such a way that the locations cannot
      overlap, then they cannot alias.  */
-  double_int size1, size2;
+  widest_int size1, size2;
   aff_tree off1, off2;

from the names you can know this is offset_int.

diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 476f3a1..aa94400 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -944,7 +944,7 @@ alloc_iv (tree base, tree step)
       && !DECL_P (TREE_OPERAND (base_object, 0)))
     {
       aff_tree comb;
-      double_int size;
+      widest_int size;
       base_object = get_inner_reference_aff (TREE_OPERAND (base_object, 0),
                                             &comb, &size);
       gcc_assert (base_object != NULL_TREE);

likewise.

@@ -529,15 +526,15 @@ end:
    difference of two values in TYPE.  */

 static void
-bounds_add (bounds *bnds, double_int delta, tree type)
+bounds_add (bounds *bnds, widest_int delta, tree type)
 {
   mpz_t mdelta, max;

const widest_int &delta please (please double-check the patches for
widest-int-by-value passing).

@@ -2592,7 +2587,7 @@ derive_constant_upper_bound_ops (tree type, tree op0,

 static void
 do_warn_aggressive_loop_optimizations (struct loop *loop,
-                                      double_int i_bound, gimple stmt)
+                                      widest_int i_bound, gimple stmt)
 {
   /* Don't warn if the loop doesn't have known constant bound.  */
   if (!loop->nb_iterations

Likewise.

@@ -2628,13 +2623,13 @@ do_warn_aggressive_loop_optimizations (struct
loop *loop,
    is taken at last when the STMT is executed BOUND + 1 times.
    REALISTIC is true if BOUND is expected to be close to the real number
    of iterations.  UPPER is true if we are sure the loop iterates at most
-   BOUND times.  I_BOUND is an unsigned double_int upper estimate on BOUND.  */
+   BOUND times.  I_BOUND is an unsigned wide_int upper estimate on BOUND.  */

 static void
-record_estimate (struct loop *loop, tree bound, double_int i_bound,
+record_estimate (struct loop *loop, tree bound, widest_int i_bound,
                 gimple at_stmt, bool is_exit, bool realistic, bool upper)
 {
-  double_int delta;
+  widest_int delta;

   if (dump_file && (dump_flags & TDF_DETAILS))
     {

Likewise.  (this is also about stack-usage in deep call frames, even if
the actual copies might end up being cheap)

 /* Return index of BOUND in BOUNDS array sorted in increasing order.
    Lookup by binary search.  */

 static int
-bound_index (vec<double_int> bounds, double_int bound)
+bound_index (vec<widest_int> bounds, const widest_int &bound)
 {
   unsigned int end = bounds.length ();
   unsigned int begin = 0;

eh... a vec of widest_int ... you know this is of the order of O (# statements)?
Oh well.  At least it's temporary.

diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index d0a6542..2ac7744 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -49,11 +49,11 @@ struct GTY(()) ptr_info_def

 struct GTY (()) range_info_def {
   /* Minimum for value range.  */
-  double_int min;
+  widest_int min;
   /* Maximum for value range.  */
-  double_int max;
+  widest_int max;
   /* Non-zero bits - bits not set are guaranteed to be always zero.  */
-  double_int nonzero_bits;
+  widest_int nonzero_bits;
 };


I've raised this in the other mail - these should remain double_ints for now
as we may have _tons_ of them around (well, I think only the after-IPA
pass pipeline will create them).

The rest of the patch looks ok to me (modulo what I said in the other
mails and what overlaps with code in this patch).

Thanks,
Richard.



More information about the Gcc-patches mailing list