[5/7] middle-end: Add initial support for poly_int64 BIT_FIELD_REF in expand pass [PR96342]

Message ID Z1BIZtEudb64bUvq@arm.com
State New
Headers
Series None |

Commit Message

Tamar Christina Dec. 4, 2024, 12:17 p.m. UTC
  Hi All,

While `poly_int64' has been the default representation of  bitfield size
and offset for some time, there was a lack of support for the use of
non-constant `poly_int64' values for those values throughout the
compiler, limiting the applicability of the BIT_FIELD_REF rtl expression
for variable length vectors, such as those used by SVE.

This patch starts work on extending the functionality of relevant
functions in the expand pass such as to enable their use by the compiler
for such vectors.

gcc/ChangeLog:

	PR target/96342
	* expr.cc (store_constructor): Enable poly_{u}int64 type usage.
	(get_inner_reference): Ditto.
	* expmed.cc (store_bit_field_1): Add is_constant checks to bitsize
	and bitnum.

Co-authored-by: Tamar Christina <tamar.christina@arm.com>

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

Ok for master?

Thanks,
Tamar

---




--
  

Comments

Richard Biener Dec. 4, 2024, 2:26 p.m. UTC | #1
On Wed, Dec 4, 2024 at 1:21 PM Tamar Christina <tamar.christina@arm.com> wrote:
>
> Hi All,
>
> While `poly_int64' has been the default representation of  bitfield size
> and offset for some time, there was a lack of support for the use of
> non-constant `poly_int64' values for those values throughout the
> compiler, limiting the applicability of the BIT_FIELD_REF rtl expression
> for variable length vectors, such as those used by SVE.
>
> This patch starts work on extending the functionality of relevant
> functions in the expand pass such as to enable their use by the compiler
> for such vectors.
>
> gcc/ChangeLog:
>
>         PR target/96342
>         * expr.cc (store_constructor): Enable poly_{u}int64 type usage.
>         (get_inner_reference): Ditto.
>         * expmed.cc (store_bit_field_1): Add is_constant checks to bitsize
>         and bitnum.
>
> Co-authored-by: Tamar Christina <tamar.christina@arm.com>
>
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
>
> Ok for master?
>
> Thanks,
> Tamar
>
> ---
> diff --git a/gcc/expmed.cc b/gcc/expmed.cc
> index 2d5e5243ce8e9c7dd2eeb0996711801d969b3f22..3721d55967ba21516b9a816505e0e999a53c3d2f 100644
> --- a/gcc/expmed.cc
> +++ b/gcc/expmed.cc
> @@ -849,6 +849,10 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
>       polynomial bitnum and bitsize.  */
>
>    /* From here on we need to be looking at a fixed-size insertion.  */
> +
> +  if (!bitsize.is_constant () || !bitnum.is_constant ())
> +       error ("bit field masks of variable size length/offset unsupported");
> +

Nak for this, we'll ICE immediately after anyway.

>    unsigned HOST_WIDE_INT ibitsize = bitsize.to_constant ();
>    unsigned HOST_WIDE_INT ibitnum = bitnum.to_constant ();
>
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index 70f2ecec99839e6247ed7601e0bff67e7aa38ba4..2d90d7aac296077cc0bda8a1b4732b1cd44a610d 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -7897,15 +7897,15 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>        {
>         unsigned HOST_WIDE_INT idx;
>         constructor_elt *ce;
> -       int i;
> +       poly_int64 i;
>         bool need_to_clear;
>         insn_code icode = CODE_FOR_nothing;
>         tree elt;
>         tree elttype = TREE_TYPE (type);
>         int elt_size = vector_element_bits (type);
>         machine_mode eltmode = TYPE_MODE (elttype);
> -       HOST_WIDE_INT bitsize;
> -       HOST_WIDE_INT bitpos;
> +       poly_int64 bitsize;
> +       poly_int64 bitpos;
>         rtvec vector = NULL;
>         poly_uint64 n_elts;
>         unsigned HOST_WIDE_INT const_n_elts;
> @@ -8002,7 +8002,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>                          ? TREE_TYPE (CONSTRUCTOR_ELT (exp, 0)->value)
>                          : elttype);
>         if (VECTOR_TYPE_P (val_type))
> -         bitsize = tree_to_uhwi (TYPE_SIZE (val_type));
> +         bitsize = tree_to_poly_uint64 (TYPE_SIZE (val_type));
>         else
>           bitsize = elt_size;
>
> @@ -8015,12 +8015,12 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>           need_to_clear = true;
>         else
>           {
> -           unsigned HOST_WIDE_INT count = 0, zero_count = 0;
> +           poly_uint64 count = 0, zero_count = 0;
>             tree value;
>
>             FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
>               {
> -               int n_elts_here = bitsize / elt_size;
> +               poly_int64 n_elts_here = exact_div (bitsize, elt_size);
>                 count += n_elts_here;
>                 if (mostly_zeros_p (value))
>                   zero_count += n_elts_here;
> @@ -8029,7 +8029,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>             /* Clear the entire vector first if there are any missing elements,
>                or if the incidence of zero elements is >= 75%.  */
>             need_to_clear = (maybe_lt (count, n_elts)
> -                            || 4 * zero_count >= 3 * count);
> +                            || maybe_gt (4 * zero_count, 3 * count));
>           }
>
>         if (need_to_clear && maybe_gt (size, 0) && !vector)
> @@ -8058,9 +8058,9 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>            element of TARGET, determined by counting the elements.  */
>         for (idx = 0, i = 0;
>              vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
> -            idx++, i += bitsize / elt_size)
> +            idx++, i += exact_div (bitsize, elt_size))
>           {
> -           HOST_WIDE_INT eltpos;
> +           poly_int64 eltpos;
>             tree value = ce->value;

That seems incomplete.  We also have

            if (ce->index)
              eltpos = tree_to_uhwi (ce->index);
            else
              eltpos = i;

which should use tree_to_poly_int64 then?  And if .to_constant () below works,
why not use constant_multiple_p instead of exact_div?

It seems to me the code interweaves two cases with multi-exclusive conditions
where only one is expected to have poly-ints but the changes make sure to
obfuscate this even more ...

Note we have GIMPLE verification that vector CTOR have no holes and no
or incrementing INTEGER_CST indices unless the components are vectors
themselves in which case the CTOR has to be full and CTOR_NELTS *
subparts of element
should be known_eq to subparts of the CTOR vector type.

>             if (cleared && initializer_zerop (value))
> @@ -8081,7 +8081,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>                   }
>                 else
>                   gcc_assert (TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE);
> -               RTVEC_ELT (vector, eltpos) = expand_normal (value);
> +               RTVEC_ELT (vector, eltpos.to_constant ()) = expand_normal (value);
>               }
>             else
>               {
> @@ -8457,10 +8457,10 @@ get_inner_reference (tree exp, poly_int64 *pbitsize,
>
>    if (size_tree != 0)
>      {
> -      if (! tree_fits_uhwi_p (size_tree))
> -       mode = BLKmode, *pbitsize = -1;
> +      if (poly_int_tree_p (size_tree, pbitsize))
> +       ;
>        else
> -       *pbitsize = tree_to_uhwi (size_tree);
> +       mode = BLKmode, *pbitsize = -1;
>      }
>
>    *preversep = reverse_storage_order_for_component_p (exp);
>
>
>
>
> --
  
Tamar Christina Dec. 9, 2024, 1:05 p.m. UTC | #2
> >         if (need_to_clear && maybe_gt (size, 0) && !vector)
> > @@ -8058,9 +8058,9 @@ store_constructor (tree exp, rtx target, int cleared,
> poly_int64 size,
> >            element of TARGET, determined by counting the elements.  */
> >         for (idx = 0, i = 0;
> >              vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
> > -            idx++, i += bitsize / elt_size)
> > +            idx++, i += exact_div (bitsize, elt_size))
> >           {
> > -           HOST_WIDE_INT eltpos;
> > +           poly_int64 eltpos;
> >             tree value = ce->value;
> 
> That seems incomplete.  We also have
> 
>             if (ce->index)
>               eltpos = tree_to_uhwi (ce->index);
>             else
>               eltpos = i;
> 
> which should use tree_to_poly_int64 then?  And if .to_constant () below works,
> why not use constant_multiple_p instead of exact_div?
> 
> It seems to me the code interweaves two cases with multi-exclusive conditions
> where only one is expected to have poly-ints but the changes make sure to
> obfuscate this even more ...
> 
> Note we have GIMPLE verification that vector CTOR have no holes and no
> or incrementing INTEGER_CST indices unless the components are vectors
> themselves in which case the CTOR has to be full and CTOR_NELTS *
> subparts of element
> should be known_eq to subparts of the CTOR vector type.
> 

Done,

gcc/ChangeLog:

	PR target/96342
	* expr.cc (store_constructor): Enable poly_{u}int64 type usage.
	(get_inner_reference): Ditto.

Co-authored-by: Tamar Christina <tamar.christina@arm.com>

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

Ok for master?

Thanks,
Tamar

-- inline copy of patch --

diff --git a/gcc/expr.cc b/gcc/expr.cc
index 980ac415cfc7e2f7cf666637e756f857758688fc..4c6039c6608c0d9db3d1796eeab2129cb844433f 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7901,15 +7901,14 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
       {
 	unsigned HOST_WIDE_INT idx;
 	constructor_elt *ce;
-	int i;
 	bool need_to_clear;
 	insn_code icode = CODE_FOR_nothing;
 	tree elt;
 	tree elttype = TREE_TYPE (type);
 	int elt_size = vector_element_bits (type);
 	machine_mode eltmode = TYPE_MODE (elttype);
-	HOST_WIDE_INT bitsize;
-	HOST_WIDE_INT bitpos;
+	poly_int64 bitsize;
+	poly_int64 bitpos;
 	rtvec vector = NULL;
 	poly_uint64 n_elts;
 	unsigned HOST_WIDE_INT const_n_elts;
@@ -8006,7 +8005,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 			 ? TREE_TYPE (CONSTRUCTOR_ELT (exp, 0)->value)
 			 : elttype);
 	if (VECTOR_TYPE_P (val_type))
-	  bitsize = tree_to_uhwi (TYPE_SIZE (val_type));
+	  bitsize = tree_to_poly_uint64 (TYPE_SIZE (val_type));
 	else
 	  bitsize = elt_size;
 
@@ -8019,12 +8018,12 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 	  need_to_clear = true;
 	else
 	  {
-	    unsigned HOST_WIDE_INT count = 0, zero_count = 0;
+	    poly_uint64 count = 0, zero_count = 0;
 	    tree value;
 
 	    FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
 	      {
-		int n_elts_here = bitsize / elt_size;
+		poly_int64 n_elts_here = exact_div (bitsize, elt_size);
 		count += n_elts_here;
 		if (mostly_zeros_p (value))
 		  zero_count += n_elts_here;
@@ -8033,7 +8032,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 	    /* Clear the entire vector first if there are any missing elements,
 	       or if the incidence of zero elements is >= 75%.  */
 	    need_to_clear = (maybe_lt (count, n_elts)
-			     || 4 * zero_count >= 3 * count);
+			     || maybe_gt (4 * zero_count, 3 * count));
 	  }
 
 	if (need_to_clear && maybe_gt (size, 0) && !vector)
@@ -8060,9 +8059,13 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 
         /* Store each element of the constructor into the corresponding
 	   element of TARGET, determined by counting the elements.  */
-	for (idx = 0, i = 0;
-	     vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
-	     idx++, i += bitsize / elt_size)
+	HOST_WIDE_INT chunk_size = 0;
+	bool chunk_multiple_p = constant_multiple_p (bitsize, elt_size,
+						     &chunk_size);
+	gcc_assert (chunk_multiple_p || vec_vec_init_p);
+
+	for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
+	     idx++)
 	  {
 	    HOST_WIDE_INT eltpos;
 	    tree value = ce->value;
@@ -8073,7 +8076,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 	    if (ce->index)
 	      eltpos = tree_to_uhwi (ce->index);
 	    else
-	      eltpos = i;
+	      eltpos = idx * chunk_size;
 
 	    if (vector)
 	      {
@@ -8461,10 +8464,8 @@ get_inner_reference (tree exp, poly_int64 *pbitsize,
 
   if (size_tree != 0)
     {
-      if (! tree_fits_uhwi_p (size_tree))
+      if (!poly_int_tree_p (size_tree, pbitsize))
 	mode = BLKmode, *pbitsize = -1;
-      else
-	*pbitsize = tree_to_uhwi (size_tree);
     }
 
   *preversep = reverse_storage_order_for_component_p (exp);
  
Richard Biener Dec. 10, 2024, 2:21 p.m. UTC | #3
On Mon, 9 Dec 2024, Tamar Christina wrote:

> > >         if (need_to_clear && maybe_gt (size, 0) && !vector)
> > > @@ -8058,9 +8058,9 @@ store_constructor (tree exp, rtx target, int cleared,
> > poly_int64 size,
> > >            element of TARGET, determined by counting the elements.  */
> > >         for (idx = 0, i = 0;
> > >              vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
> > > -            idx++, i += bitsize / elt_size)
> > > +            idx++, i += exact_div (bitsize, elt_size))
> > >           {
> > > -           HOST_WIDE_INT eltpos;
> > > +           poly_int64 eltpos;
> > >             tree value = ce->value;
> > 
> > That seems incomplete.  We also have
> > 
> >             if (ce->index)
> >               eltpos = tree_to_uhwi (ce->index);
> >             else
> >               eltpos = i;
> > 
> > which should use tree_to_poly_int64 then?  And if .to_constant () below works,
> > why not use constant_multiple_p instead of exact_div?
> > 
> > It seems to me the code interweaves two cases with multi-exclusive conditions
> > where only one is expected to have poly-ints but the changes make sure to
> > obfuscate this even more ...
> > 
> > Note we have GIMPLE verification that vector CTOR have no holes and no
> > or incrementing INTEGER_CST indices unless the components are vectors
> > themselves in which case the CTOR has to be full and CTOR_NELTS *
> > subparts of element
> > should be known_eq to subparts of the CTOR vector type.
> > 
> 
> Done,

OK.

Thanks,
Richard.

> gcc/ChangeLog:
> 
> 	PR target/96342
> 	* expr.cc (store_constructor): Enable poly_{u}int64 type usage.
> 	(get_inner_reference): Ditto.
> 
> Co-authored-by: Tamar Christina <tamar.christina@arm.com>
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
> 
> Ok for master?
> 
> Thanks,
> Tamar
> 
> -- inline copy of patch --
> 
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index 980ac415cfc7e2f7cf666637e756f857758688fc..4c6039c6608c0d9db3d1796eeab2129cb844433f 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -7901,15 +7901,14 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>        {
>  	unsigned HOST_WIDE_INT idx;
>  	constructor_elt *ce;
> -	int i;
>  	bool need_to_clear;
>  	insn_code icode = CODE_FOR_nothing;
>  	tree elt;
>  	tree elttype = TREE_TYPE (type);
>  	int elt_size = vector_element_bits (type);
>  	machine_mode eltmode = TYPE_MODE (elttype);
> -	HOST_WIDE_INT bitsize;
> -	HOST_WIDE_INT bitpos;
> +	poly_int64 bitsize;
> +	poly_int64 bitpos;
>  	rtvec vector = NULL;
>  	poly_uint64 n_elts;
>  	unsigned HOST_WIDE_INT const_n_elts;
> @@ -8006,7 +8005,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>  			 ? TREE_TYPE (CONSTRUCTOR_ELT (exp, 0)->value)
>  			 : elttype);
>  	if (VECTOR_TYPE_P (val_type))
> -	  bitsize = tree_to_uhwi (TYPE_SIZE (val_type));
> +	  bitsize = tree_to_poly_uint64 (TYPE_SIZE (val_type));
>  	else
>  	  bitsize = elt_size;
>  
> @@ -8019,12 +8018,12 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>  	  need_to_clear = true;
>  	else
>  	  {
> -	    unsigned HOST_WIDE_INT count = 0, zero_count = 0;
> +	    poly_uint64 count = 0, zero_count = 0;
>  	    tree value;
>  
>  	    FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
>  	      {
> -		int n_elts_here = bitsize / elt_size;
> +		poly_int64 n_elts_here = exact_div (bitsize, elt_size);
>  		count += n_elts_here;
>  		if (mostly_zeros_p (value))
>  		  zero_count += n_elts_here;
> @@ -8033,7 +8032,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>  	    /* Clear the entire vector first if there are any missing elements,
>  	       or if the incidence of zero elements is >= 75%.  */
>  	    need_to_clear = (maybe_lt (count, n_elts)
> -			     || 4 * zero_count >= 3 * count);
> +			     || maybe_gt (4 * zero_count, 3 * count));
>  	  }
>  
>  	if (need_to_clear && maybe_gt (size, 0) && !vector)
> @@ -8060,9 +8059,13 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>  
>          /* Store each element of the constructor into the corresponding
>  	   element of TARGET, determined by counting the elements.  */
> -	for (idx = 0, i = 0;
> -	     vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
> -	     idx++, i += bitsize / elt_size)
> +	HOST_WIDE_INT chunk_size = 0;
> +	bool chunk_multiple_p = constant_multiple_p (bitsize, elt_size,
> +						     &chunk_size);
> +	gcc_assert (chunk_multiple_p || vec_vec_init_p);
> +
> +	for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
> +	     idx++)
>  	  {
>  	    HOST_WIDE_INT eltpos;
>  	    tree value = ce->value;
> @@ -8073,7 +8076,7 @@ store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
>  	    if (ce->index)
>  	      eltpos = tree_to_uhwi (ce->index);
>  	    else
> -	      eltpos = i;
> +	      eltpos = idx * chunk_size;
>  
>  	    if (vector)
>  	      {
> @@ -8461,10 +8464,8 @@ get_inner_reference (tree exp, poly_int64 *pbitsize,
>  
>    if (size_tree != 0)
>      {
> -      if (! tree_fits_uhwi_p (size_tree))
> +      if (!poly_int_tree_p (size_tree, pbitsize))
>  	mode = BLKmode, *pbitsize = -1;
> -      else
> -	*pbitsize = tree_to_uhwi (size_tree);
>      }
>  
>    *preversep = reverse_storage_order_for_component_p (exp);
>
  

Patch

diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index 2d5e5243ce8e9c7dd2eeb0996711801d969b3f22..3721d55967ba21516b9a816505e0e999a53c3d2f 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -849,6 +849,10 @@  store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum,
      polynomial bitnum and bitsize.  */
 
   /* From here on we need to be looking at a fixed-size insertion.  */
+
+  if (!bitsize.is_constant () || !bitnum.is_constant ())
+	error ("bit field masks of variable size length/offset unsupported");
+
   unsigned HOST_WIDE_INT ibitsize = bitsize.to_constant ();
   unsigned HOST_WIDE_INT ibitnum = bitnum.to_constant ();
 
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 70f2ecec99839e6247ed7601e0bff67e7aa38ba4..2d90d7aac296077cc0bda8a1b4732b1cd44a610d 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -7897,15 +7897,15 @@  store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
       {
 	unsigned HOST_WIDE_INT idx;
 	constructor_elt *ce;
-	int i;
+	poly_int64 i;
 	bool need_to_clear;
 	insn_code icode = CODE_FOR_nothing;
 	tree elt;
 	tree elttype = TREE_TYPE (type);
 	int elt_size = vector_element_bits (type);
 	machine_mode eltmode = TYPE_MODE (elttype);
-	HOST_WIDE_INT bitsize;
-	HOST_WIDE_INT bitpos;
+	poly_int64 bitsize;
+	poly_int64 bitpos;
 	rtvec vector = NULL;
 	poly_uint64 n_elts;
 	unsigned HOST_WIDE_INT const_n_elts;
@@ -8002,7 +8002,7 @@  store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 			 ? TREE_TYPE (CONSTRUCTOR_ELT (exp, 0)->value)
 			 : elttype);
 	if (VECTOR_TYPE_P (val_type))
-	  bitsize = tree_to_uhwi (TYPE_SIZE (val_type));
+	  bitsize = tree_to_poly_uint64 (TYPE_SIZE (val_type));
 	else
 	  bitsize = elt_size;
 
@@ -8015,12 +8015,12 @@  store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 	  need_to_clear = true;
 	else
 	  {
-	    unsigned HOST_WIDE_INT count = 0, zero_count = 0;
+	    poly_uint64 count = 0, zero_count = 0;
 	    tree value;
 
 	    FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
 	      {
-		int n_elts_here = bitsize / elt_size;
+		poly_int64 n_elts_here = exact_div (bitsize, elt_size);
 		count += n_elts_here;
 		if (mostly_zeros_p (value))
 		  zero_count += n_elts_here;
@@ -8029,7 +8029,7 @@  store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 	    /* Clear the entire vector first if there are any missing elements,
 	       or if the incidence of zero elements is >= 75%.  */
 	    need_to_clear = (maybe_lt (count, n_elts)
-			     || 4 * zero_count >= 3 * count);
+			     || maybe_gt (4 * zero_count, 3 * count));
 	  }
 
 	if (need_to_clear && maybe_gt (size, 0) && !vector)
@@ -8058,9 +8058,9 @@  store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 	   element of TARGET, determined by counting the elements.  */
 	for (idx = 0, i = 0;
 	     vec_safe_iterate (CONSTRUCTOR_ELTS (exp), idx, &ce);
-	     idx++, i += bitsize / elt_size)
+	     idx++, i += exact_div (bitsize, elt_size))
 	  {
-	    HOST_WIDE_INT eltpos;
+	    poly_int64 eltpos;
 	    tree value = ce->value;
 
 	    if (cleared && initializer_zerop (value))
@@ -8081,7 +8081,7 @@  store_constructor (tree exp, rtx target, int cleared, poly_int64 size,
 		  }
 		else
 		  gcc_assert (TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE);
-		RTVEC_ELT (vector, eltpos) = expand_normal (value);
+		RTVEC_ELT (vector, eltpos.to_constant ()) = expand_normal (value);
 	      }
 	    else
 	      {
@@ -8457,10 +8457,10 @@  get_inner_reference (tree exp, poly_int64 *pbitsize,
 
   if (size_tree != 0)
     {
-      if (! tree_fits_uhwi_p (size_tree))
-	mode = BLKmode, *pbitsize = -1;
+      if (poly_int_tree_p (size_tree, pbitsize))
+	;
       else
-	*pbitsize = tree_to_uhwi (size_tree);
+	mode = BLKmode, *pbitsize = -1;
     }
 
   *preversep = reverse_storage_order_for_component_p (exp);