On Nov 25, 2013, at 2:57 AM, Richard Biener <[email protected]> wrote:
> On Sat, Nov 23, 2013 at 8:21 PM, Mike Stump <[email protected]> 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 cfg code.
>>
>> Ok?
>
> Hmm, this is an example of a wide_int (a widest_int) being used inside
> a structure with long lifetime. With the patch there are two of those
> per loop plus up to one per statement in a loop body (quadratic in
> the loop depth).
> Now, for the number-of-iterations stuff I really would like to keep things
> cheaper in some way or another. Shrinking MAX_BITSIZE_MODE_ANY_INT
> would be the easiest improvement for x86_64.
> That said, I'd like this to be addressed.
The port can limit the size like so:
/* Keep the OI and XI modes from confusing the compiler into thinking
that these modes could actually be used for computation. They are
only holders for vectors during data movement. */
#define MAX_BITSIZE_MODE_ANY_INT (128)
and that is now done on x86.
Ok?
A copy of the patch is below (unchanged)...
* cfgloop.c
(alloc_loop): Initialize nb_iterations_upper_bound and
nb_iterations_estimate.
(record_niter_bound): Use wide-int interfaces.
(get_estimated_loop_iterations_int): Likewise.
(get_estimated_loop_iterations): Likewise.
(get_max_loop_iterations): Likewise.
* cfgloop.h: Include wide-int.h.
(struct nb_iter_bound): Change bound to widest_int.
(struct loop): Change nb_iterations_upper_bound and
nb_iterations_estimate to widest_int.
(record_niter_bound): Switch to use widest_int.
(get_estimated_loop_iterations): Likewise.
(get_max_loop_iterations): Likewise.
(gcov_type_to_double_int): Rename to gcov_type_to_wide_int and
update for wide-int.
* cgraph.c
(cgraph_add_thunk): Use wide-int interfaces.
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index 09029c9..447302a 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -333,7 +333,8 @@ alloc_loop (void)
loop->exits = ggc_alloc_cleared_loop_exit ();
loop->exits->next = loop->exits->prev = loop->exits;
loop->can_be_parallel = false;
-
+ loop->nb_iterations_upper_bound = 0;
+ loop->nb_iterations_estimate = 0;
return loop;
}
@@ -1784,21 +1785,21 @@ get_loop_location (struct loop *loop)
I_BOUND times. */
void
-record_niter_bound (struct loop *loop, double_int i_bound, bool realistic,
- bool upper)
+record_niter_bound (struct loop *loop, const widest_int &i_bound,
+ bool realistic, bool upper)
{
/* Update the bounds only when there is no previous estimation, or when the
current estimation is smaller. */
if (upper
&& (!loop->any_upper_bound
- || i_bound.ult (loop->nb_iterations_upper_bound)))
+ || wi::ltu_p (i_bound, loop->nb_iterations_upper_bound)))
{
loop->any_upper_bound = true;
loop->nb_iterations_upper_bound = i_bound;
}
if (realistic
&& (!loop->any_estimate
- || i_bound.ult (loop->nb_iterations_estimate)))
+ || wi::ltu_p (i_bound, loop->nb_iterations_estimate)))
{
loop->any_estimate = true;
loop->nb_iterations_estimate = i_bound;
@@ -1808,7 +1809,8 @@ record_niter_bound (struct loop *loop, double_int
i_bound, bool realistic,
number of iterations, use the upper bound instead. */
if (loop->any_upper_bound
&& loop->any_estimate
- && loop->nb_iterations_upper_bound.ult (loop->nb_iterations_estimate))
+ && wi::ltu_p (loop->nb_iterations_upper_bound,
+ loop->nb_iterations_estimate))
loop->nb_iterations_estimate = loop->nb_iterations_upper_bound;
}
@@ -1819,13 +1821,13 @@ record_niter_bound (struct loop *loop, double_int
i_bound, bool realistic,
HOST_WIDE_INT
get_estimated_loop_iterations_int (struct loop *loop)
{
- double_int nit;
+ widest_int nit;
HOST_WIDE_INT hwi_nit;
if (!get_estimated_loop_iterations (loop, &nit))
return -1;
- if (!nit.fits_shwi ())
+ if (!wi::fits_shwi_p (nit))
return -1;
hwi_nit = nit.to_shwi ();
@@ -1856,7 +1858,7 @@ max_stmt_executions_int (struct loop *loop)
returns true. */
bool
-get_estimated_loop_iterations (struct loop *loop, double_int *nit)
+get_estimated_loop_iterations (struct loop *loop, widest_int *nit)
{
/* Even if the bound is not recorded, possibly we can derrive one from
profile. */
@@ -1864,7 +1866,7 @@ get_estimated_loop_iterations (struct loop *loop,
double_int *nit)
{
if (loop->header->count)
{
- *nit = gcov_type_to_double_int
+ *nit = gcov_type_to_wide_int
(expected_loop_iterations_unbounded (loop) + 1);
return true;
}
@@ -1880,7 +1882,7 @@ get_estimated_loop_iterations (struct loop *loop,
double_int *nit)
false, otherwise returns true. */
bool
-get_max_loop_iterations (struct loop *loop, double_int *nit)
+get_max_loop_iterations (struct loop *loop, widest_int *nit)
{
if (!loop->any_upper_bound)
return false;
@@ -1896,13 +1898,13 @@ get_max_loop_iterations (struct loop *loop, double_int
*nit)
HOST_WIDE_INT
get_max_loop_iterations_int (struct loop *loop)
{
- double_int nit;
+ widest_int nit;
HOST_WIDE_INT hwi_nit;
if (!get_max_loop_iterations (loop, &nit))
return -1;
- if (!nit.fits_shwi ())
+ if (!wi::fits_shwi_p (nit))
return -1;
hwi_nit = nit.to_shwi ();
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 68285a6..69fa996 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#define GCC_CFGLOOP_H
#include "double-int.h"
+#include "wide-int.h"
#include "bitmap.h"
#include "sbitmap.h"
#include "function.h"
@@ -62,7 +63,7 @@ struct GTY ((chain_next ("%h.next"))) nb_iter_bound {
overflows (as MAX + 1 is sometimes produced as the estimate on number
of executions of STMT).
b) it is consistent with the result of number_of_iterations_exit. */
- double_int bound;
+ widest_int bound;
/* True if the statement will cause the loop to be leaved the (at most)
BOUND + 1-st time it is executed, that is, all the statements after it
@@ -146,12 +147,12 @@ struct GTY ((chain_next ("%h.next"))) loop {
/* An integer guaranteed to be greater or equal to nb_iterations. Only
valid if any_upper_bound is true. */
- double_int nb_iterations_upper_bound;
+ widest_int nb_iterations_upper_bound;
/* An integer giving an estimate on nb_iterations. Unlike
nb_iterations_upper_bound, there is no guarantee that it is at least
nb_iterations. */
- double_int nb_iterations_estimate;
+ widest_int nb_iterations_estimate;
bool any_upper_bound;
bool any_estimate;
@@ -734,27 +735,27 @@ loop_outermost (struct loop *loop)
return (*loop->superloops)[1];
}
-extern void record_niter_bound (struct loop *, double_int, bool, bool);
+extern void record_niter_bound (struct loop *, const widest_int &, bool, bool);
extern HOST_WIDE_INT get_estimated_loop_iterations_int (struct loop *);
extern HOST_WIDE_INT get_max_loop_iterations_int (struct loop *);
-extern bool get_estimated_loop_iterations (struct loop *loop, double_int *nit);
-extern bool get_max_loop_iterations (struct loop *loop, double_int *nit);
+extern bool get_estimated_loop_iterations (struct loop *loop, widest_int *nit);
+extern bool get_max_loop_iterations (struct loop *loop, widest_int *nit);
extern int bb_loop_depth (const_basic_block);
-/* Converts VAL to double_int. */
+/* Converts VAL to widest_int. */
-static inline double_int
-gcov_type_to_double_int (gcov_type val)
+static inline widest_int
+gcov_type_to_wide_int (gcov_type val)
{
- double_int ret;
+ HOST_WIDE_INT a[2];
- ret.low = (unsigned HOST_WIDE_INT) val;
+ a[0] = (unsigned HOST_WIDE_INT) val;
/* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
the size of type. */
val >>= HOST_BITS_PER_WIDE_INT - 1;
val >>= 1;
- ret.high = (unsigned HOST_WIDE_INT) val;
+ a[1] = (unsigned HOST_WIDE_INT) val;
- return ret;
+ return widest_int::from_array (a, 2);
}
#endif /* GCC_CFGLOOP_H */
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 009a165..cfbd79e 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -646,8 +646,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node
ATTRIBUTE_UNUSED,
node = cgraph_create_node (alias);
gcc_checking_assert (!virtual_offset
- || tree_to_double_int (virtual_offset) ==
- double_int::from_shwi (virtual_value));
+ || wi::eq_p (virtual_offset, virtual_value));
node->thunk.fixed_offset = fixed_offset;
node->thunk.this_adjusting = this_adjusting;
node->thunk.virtual_value = virtual_value;