Hi Richard,
Thanks for your suggestions on RFC email, the attached patch adds support for
streaming of poly_int when it's degree <= accel's NUM_POLY_INT_COEFFS.
The patch changes streaming of poly_int as follows:
Streaming out poly_int:
degree = poly_int.degree();
stream out degree;
for (i = 0; i < degree; i++)
stream out poly_int.coeffs[i];
Streaming in poly_int:
stream in degree;
if (degree > NUM_POLY_INT_COEFFS)
fatal_error();
stream in coeffs;
// Set remaining coeffs to zero in case degree < accel's NUM_POLY_INT_COEFFS
for (i = degree; i < NUM_POLY_INT_COEFFS; i++)
poly_int.coeffs[i] = 0;
Patch passes bootstrap+test and LTO bootstrap+test on aarch64-linux-gnu.
LTO bootstrap+test on x86_64-linux-gnu in progress.
I am not quite sure how to test it for offloading since currently it's
(entirely) broken for aarch64->nvptx.
I can give a try with x86_64->nvptx offloading if required (altho I guess LTO
bootstrap should test streaming changes ?)
Signed-off-by: Prathamesh Kulkarni <[email protected]>
Thanks,
Prathamesh
Partially support streaming of poly_int for offloading.
Support streaming of poly_int for offloading when it's degree doesn't exceed
accel's NUM_POLY_INT_COEFFS.
The patch changes streaming of poly_int as follows:
Streaming out poly_int:
degree = poly_int.degree();
stream out degree;
for (i = 0; i < degree; i++)
stream out poly_int.coeffs[i];
Streaming in poly_int (for accelerator):
stream in degree;
if (degree > NUM_POLY_INT_COEFFS)
fatal_error();
stream in coeffs;
// Set remaining coeffs to zero in case degree < accel's NUM_POLY_INT_COEFFS
for (i = degree; i < NUM_POLY_INT_COEFFS; i++)
poly_int.coeffs[i] = 0;
gcc/ChangeLog:
* data-streamer-in.cc (streamer_read_poly_uint64): Stream in poly_int
degree and call poly_int_read_common.
(streamer_read_poly_int64): Likewise.
* data-streamer-out.cc (streamer_write_poly_uint64): Stream out poly_int
degree.
(streamer_write_poly_int64): Likewise.
* data-streamer.h (bp_pack_poly_value): Likewise.
(poly_int_read_common): New function template.
(bp_unpack_poly_value): Stream in poly_int degree and call
poly_int_read_common.
* poly-int.h (C>::degree): New method.
* tree-streamer-in.cc (lto_input_ts_poly_tree_pointers): Stream in
POLY_INT_CST degree, issue a fatal_error if degree is greater than
NUM_POLY_INT_COEFFS, and zero out remaining coeffs.
* tree-streamer-out.cc (write_ts_poly_tree_pointers): Calculate and
stream out POLY_INT_CST degree.
Signed-off-by: Prathamesh Kulkarni <[email protected]>
diff --git a/gcc/data-streamer-in.cc b/gcc/data-streamer-in.cc
index 7dce2928ef0..91cece39b05 100644
--- a/gcc/data-streamer-in.cc
+++ b/gcc/data-streamer-in.cc
@@ -182,10 +182,11 @@ streamer_read_hwi (class lto_input_block *ib)
poly_uint64
streamer_read_poly_uint64 (class lto_input_block *ib)
{
+ unsigned degree = streamer_read_uhwi (ib);
poly_uint64 res;
- for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ for (unsigned int i = 0; i < degree; ++i)
res.coeffs[i] = streamer_read_uhwi (ib);
- return res;
+ return poly_int_read_common (res, degree);
}
/* Read a poly_int64 from IB. */
@@ -193,10 +194,11 @@ streamer_read_poly_uint64 (class lto_input_block *ib)
poly_int64
streamer_read_poly_int64 (class lto_input_block *ib)
{
+ unsigned degree = streamer_read_uhwi (ib);
poly_int64 res;
- for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ for (unsigned int i = 0; i < degree; ++i)
res.coeffs[i] = streamer_read_hwi (ib);
- return res;
+ return poly_int_read_common (res, degree);
}
/* Read gcov_type value from IB. */
diff --git a/gcc/data-streamer-out.cc b/gcc/data-streamer-out.cc
index c237e30f704..b0fb9dedb24 100644
--- a/gcc/data-streamer-out.cc
+++ b/gcc/data-streamer-out.cc
@@ -227,7 +227,9 @@ streamer_write_hwi (struct output_block *ob, HOST_WIDE_INT
work)
void
streamer_write_poly_uint64 (struct output_block *ob, poly_uint64 work)
{
- for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ unsigned degree = work.degree ();
+ streamer_write_uhwi_stream (ob->main_stream, degree);
+ for (unsigned i = 0; i < degree; ++i)
streamer_write_uhwi_stream (ob->main_stream, work.coeffs[i]);
}
@@ -236,7 +238,9 @@ streamer_write_poly_uint64 (struct output_block *ob,
poly_uint64 work)
void
streamer_write_poly_int64 (struct output_block *ob, poly_int64 work)
{
- for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ unsigned degree = work.degree ();
+ streamer_write_uhwi_stream (ob->main_stream, degree);
+ for (unsigned i = 0; i < degree; ++i)
streamer_write_hwi_stream (ob->main_stream, work.coeffs[i]);
}
diff --git a/gcc/data-streamer.h b/gcc/data-streamer.h
index 6a2596134ce..b154c439b8c 100644
--- a/gcc/data-streamer.h
+++ b/gcc/data-streamer.h
@@ -142,7 +142,9 @@ bp_pack_poly_value (struct bitpack_d *bp,
const poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t> &val,
unsigned nbits)
{
- for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ unsigned degree = val.degree ();
+ bp_pack_value (bp, degree, BITS_PER_UNIT * sizeof (unsigned HOST_WIDE_INT));
+ for (unsigned i = 0; i < degree; ++i)
bp_pack_value (bp, val.coeffs[i], nbits);
}
@@ -194,15 +196,33 @@ bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
return val & mask;
}
+template<unsigned N, typename C>
+inline poly_int<N, C>
+poly_int_read_common (poly_int<N, C> x, unsigned degree)
+{
+ if (degree > NUM_POLY_INT_COEFFS)
+ fatal_error (input_location,
+ "%<poly_int%> degree (%u) exceeds value of "
+ "%<NUM_POLY_INT_COEFFS%> (%u)", degree,
+ NUM_POLY_INT_COEFFS);
+ for (unsigned i = degree; i < NUM_POLY_INT_COEFFS; i++)
+ x.coeffs[i] = 0;
+ return x;
+}
+
/* Unpacks a polynomial value from the bit-packing context BP in which each
coefficient has NBITS bits. */
inline poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t>
bp_unpack_poly_value (struct bitpack_d *bp, unsigned nbits)
{
+ unsigned degree
+ = bp_unpack_value (bp, BITS_PER_UNIT * sizeof (unsigned HOST_WIDE_INT));
+
poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t> x;
- for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ for (unsigned i = 0; i < degree; i++)
x.coeffs[i] = bp_unpack_value (bp, nbits);
- return x;
+
+ return poly_int_read_common (x, degree);
}
diff --git a/gcc/poly-int.h b/gcc/poly-int.h
index e3f8d4df716..0df70d392f5 100644
--- a/gcc/poly-int.h
+++ b/gcc/poly-int.h
@@ -422,6 +422,8 @@ public:
poly_int<N, HOST_WIDE_INT> force_shwi () const;
poly_int<N, unsigned HOST_WIDE_INT> force_uhwi () const;
+ unsigned degree (void) const;
+
#if POLY_INT_CONVERSION
operator C () const;
#endif
@@ -678,6 +680,17 @@ poly_int<N, C>::force_uhwi () const
return r;
}
+template<unsigned N, typename C>
+inline unsigned poly_int<N, C>::degree () const
+{
+ unsigned i;
+ /* Find leading non-zero coeff. In case all coeffs are zero,
+ treat it as degree-1 poly_int. */
+ for (i = NUM_POLY_INT_COEFFS - 1; i > 0 && !this->coeffs[i]; i--)
+ ;
+ return i + 1;
+}
+
#if POLY_INT_CONVERSION
/* Provide a conversion operator to constants. */
diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc
index c248a74f7a1..2394ac209f5 100644
--- a/gcc/tree-streamer-in.cc
+++ b/gcc/tree-streamer-in.cc
@@ -671,8 +671,20 @@ static void
lto_input_ts_poly_tree_pointers (class lto_input_block *ib,
class data_in *data_in, tree expr)
{
- for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ unsigned degree = streamer_read_uhwi (ib);
+ if (degree > NUM_POLY_INT_COEFFS)
+ fatal_error (input_location,
+ "%<poly_int%> degree (%u) exceeds value of "
+ "%<NUM_POLY_INT_COEFFS%> (%u)", degree,
+ NUM_POLY_INT_COEFFS);
+
+ unsigned i;
+ for (i = 0; i < degree; ++i)
POLY_INT_CST_COEFF (expr, i) = stream_read_tree_ref (ib, data_in);
+
+ tree coeff_type = TREE_TYPE (POLY_INT_CST_COEFF (expr, 0));
+ for (; i < NUM_POLY_INT_COEFFS; ++i)
+ POLY_INT_CST_COEFF (expr, i) = build_zero_cst (coeff_type);
}
diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc
index b7205287ffb..e28616b9a7a 100644
--- a/gcc/tree-streamer-out.cc
+++ b/gcc/tree-streamer-out.cc
@@ -576,7 +576,14 @@ write_ts_vector_tree_pointers (struct output_block *ob,
tree expr)
static void
write_ts_poly_tree_pointers (struct output_block *ob, tree expr)
{
- for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ unsigned i;
+ for (i = NUM_POLY_INT_COEFFS - 1;
+ i > 0 && integer_zerop (POLY_INT_CST_COEFF (expr, i));
+ i--)
+ ;
+ unsigned degree = i + 1;
+ streamer_write_uhwi_stream (ob->main_stream, degree);
+ for (i = 0; i < degree; ++i)
stream_write_tree_ref (ob, POLY_INT_CST_COEFF (expr, i));
}