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 <prathame...@nvidia.com> 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 <prathame...@nvidia.com> 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)); }