Partially support streaming poly_int for offloading when it's degree <= accel NUM_POLY_INT_COEFFS.

The patch streams-out NUM_POLY_INT_COEFFS from host, and while streaming-in during lto1,
compares it with accelerator's NUM_POLY_INT_COEFFS as follows:

Stream in host_num_poly_int_coeffs;

// NUM_POLY_INT_COEFFS represents accelerator's value here.
if (host_num_poly_int_coeffs == NUM_POLY_INT_COEFFS) // NUM_POLY_INT_COEFFS represents accelerator's value here.
{
  /* Both are equal, proceed to unpacking NUM_POLY_INT_COEFFS words
     from bitstream.  */
}
else if (host_num_poly_int_coeffs < NUM_POLY_INT_COEFFS)
{
  /* Unpack host_num_poly_int_coeffs words and zero out remaining
     higher coeffs (similar to zero-extension).  */
}
else
{
  /* Unpack host_num_poly_int_coeffs words and ensure that degree of
     streamed-out poly_int <= NUM_POLY_INT_COEFFS.  */
}

Signed-off-by: Prathamesh Kulkarni <prathameshk@nvidia.com>

diff --git a/gcc/data-streamer-in.cc b/gcc/data-streamer-in.cc
index 7dce2928ef0..0f5f13fd78d 100644
--- a/gcc/data-streamer-in.cc
+++ b/gcc/data-streamer-in.cc
@@ -183,8 +183,36 @@ poly_uint64
 streamer_read_poly_uint64 (class lto_input_block *ib)
 {
   poly_uint64 res;
-  for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
-    res.coeffs[i] = streamer_read_uhwi (ib);
+  unsigned host_num_poly_int_coeffs = streamer_read_uhwi (ib);
+
+  if (host_num_poly_int_coeffs == NUM_POLY_INT_COEFFS)
+    for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+      res.coeffs[i] = streamer_read_uhwi (ib);
+  else if (host_num_poly_int_coeffs < NUM_POLY_INT_COEFFS)
+    {
+      unsigned i;
+      for (i = 0; i < host_num_poly_int_coeffs; i++)
+	res.coeffs[i] = streamer_read_uhwi (ib);
+      for (; i < NUM_POLY_INT_COEFFS; i++)
+	res.coeffs[i] = 0;
+    }
+  else
+    {
+      unsigned i;
+      for (i = 0; i < NUM_POLY_INT_COEFFS; i++)
+	res.coeffs[i] = streamer_read_uhwi (ib);
+
+      /* Ensure that res has degree <= NUM_POLY_INT_COEFFS.  */
+      for (; i < host_num_poly_int_coeffs; i++)
+	{
+	  uint64_t val = streamer_read_uhwi (ib);
+	  if (val != 0)
+	    fatal_error (input_location,
+			 "Error: poly_int degree exceeds "
+			 "Target NUM_POLY_INT_COEFFS (%d)", NUM_POLY_INT_COEFFS);
+	}
+    }
+
   return res;
 }
 
@@ -194,8 +222,34 @@ poly_int64
 streamer_read_poly_int64 (class lto_input_block *ib)
 {
   poly_int64 res;
-  for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
-    res.coeffs[i] = streamer_read_hwi (ib);
+  unsigned host_num_poly_int_coeffs = streamer_read_uhwi (ib);
+
+  if (host_num_poly_int_coeffs == NUM_POLY_INT_COEFFS)
+    for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+      res.coeffs[i] = streamer_read_hwi (ib);
+  else if (host_num_poly_int_coeffs < NUM_POLY_INT_COEFFS)
+    {
+      unsigned i;
+      for (i = 0; i < host_num_poly_int_coeffs; i++)
+	res.coeffs[i] = streamer_read_hwi (ib);
+      for (; i < NUM_POLY_INT_COEFFS; i++)
+	res.coeffs[i] = 0;
+    }
+  else
+    {
+      unsigned i;
+      for (i = 0; i < NUM_POLY_INT_COEFFS; i++)
+	res.coeffs[i] = streamer_read_hwi (ib);
+
+      for (; i < host_num_poly_int_coeffs; i++)
+	{
+	  int64_t val = streamer_read_hwi (ib);
+	  if (val != 0)
+	    fatal_error (input_location,
+			 "Error: poly_int degree exceeds "
+			 "Target NUM_POLY_INT_COEFFS (%d)", NUM_POLY_INT_COEFFS);
+	}
+    }
   return res;
 }
 
diff --git a/gcc/data-streamer-out.cc b/gcc/data-streamer-out.cc
index c237e30f704..24ba3d5b5d2 100644
--- a/gcc/data-streamer-out.cc
+++ b/gcc/data-streamer-out.cc
@@ -227,6 +227,7 @@ streamer_write_hwi (struct output_block *ob, HOST_WIDE_INT work)
 void
 streamer_write_poly_uint64 (struct output_block *ob, poly_uint64 work)
 {
+  streamer_write_uhwi_stream (ob->main_stream, NUM_POLY_INT_COEFFS);
   for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
     streamer_write_uhwi_stream (ob->main_stream, work.coeffs[i]);
 }
@@ -236,6 +237,7 @@ streamer_write_poly_uint64 (struct output_block *ob, poly_uint64 work)
 void
 streamer_write_poly_int64 (struct output_block *ob, poly_int64 work)
 {
+  streamer_write_uhwi_stream (ob->main_stream, NUM_POLY_INT_COEFFS);
   for (int i = 0; i < NUM_POLY_INT_COEFFS; ++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..bb5682be801 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)
+  bp_pack_value (bp, NUM_POLY_INT_COEFFS,
+		 BITS_PER_UNIT * sizeof(uint64_t));
+  for (unsigned i = 0; i < NUM_POLY_INT_COEFFS; ++i)
     bp_pack_value (bp, val.coeffs[i], nbits);
 }
 
@@ -199,9 +201,34 @@ bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
 inline poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t>
 bp_unpack_poly_value (struct bitpack_d *bp, unsigned nbits)
 {
+  unsigned host_num_poly_int_coeffs
+    = bp_unpack_value (bp, BITS_PER_UNIT * sizeof (uint64_t));
   poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t> x;
-  for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
-    x.coeffs[i] = bp_unpack_value (bp, nbits);
+  if (host_num_poly_int_coeffs == NUM_POLY_INT_COEFFS)
+    for (unsigned i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+      x.coeffs[i] = bp_unpack_value (bp, nbits);
+  else if (host_num_poly_int_coeffs < NUM_POLY_INT_COEFFS)
+    {
+      unsigned i;
+      for (i = 0; i < host_num_poly_int_coeffs; i++)
+ 	x.coeffs[i] = bp_unpack_value (bp, nbits);
+      for (; i < NUM_POLY_INT_COEFFS; i++)
+	x.coeffs[i] = 0;
+    }
+  else
+    {
+      unsigned i;
+      for (i = 0; i < NUM_POLY_INT_COEFFS; i++)
+	x.coeffs[i] = bp_unpack_value (bp, nbits);
+      for (; i < host_num_poly_int_coeffs; i++)
+	{
+	  bitpack_word_t val = bp_unpack_value (bp, nbits);
+	  if (val != 0)
+	    fatal_error (input_location,
+			 "Error: poly_int degree exceeds "
+			 "Target NUM_POLY_INT_COEFFS (%d)", NUM_POLY_INT_COEFFS);
+	}
+    }
   return x;
 }
 
