Adjust LSHIFT_EXPR handling of multiple_of_p
Commit Message
This removes the odd check of size_type_node when handling left-shifts
as multiplications of 1 << N and instead uses the type as specified.
It also moves left-shift handling next to multiplications where it
semantically belongs.
Boostrap and regtest pending on x86_64-unknown-linux-gnu.
OK? (I failed to short-cut the wide_int_to_tree for a
poly_int_cst_p bottom)
Thanks,
Richard.
2022-01-24 Richard Biener <rguenther@suse.de>
* fold-const.cc (multiple_of_p): Re-write and move LSHIFT_EXPR
handling.
---
gcc/fold-const.cc | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
Comments
Richard Biener <rguenther@suse.de> writes:
> This removes the odd check of size_type_node when handling left-shifts
> as multiplications of 1 << N and instead uses the type as specified.
> It also moves left-shift handling next to multiplications where it
> semantically belongs.
>
> Boostrap and regtest pending on x86_64-unknown-linux-gnu.
>
> OK? (I failed to short-cut the wide_int_to_tree for a
> poly_int_cst_p bottom)
>
> Thanks,
> Richard.
>
> 2022-01-24 Richard Biener <rguenther@suse.de>
>
> * fold-const.cc (multiple_of_p): Re-write and move LSHIFT_EXPR
> handling.
> ---
> gcc/fold-const.cc | 33 ++++++++++++++++-----------------
> 1 file changed, 16 insertions(+), 17 deletions(-)
>
> diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> index b155611578d..a0a4913c45e 100644
> --- a/gcc/fold-const.cc
> +++ b/gcc/fold-const.cc
> @@ -14068,7 +14068,7 @@ int
> multiple_of_p (tree type, const_tree top, const_tree bottom)
> {
> gimple *stmt;
> - tree t1, op1, op2;
> + tree op1, op2;
>
> if (operand_equal_p (top, bottom, 0))
> return 1;
> @@ -14114,6 +14114,21 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
> return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
> || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
>
> + case LSHIFT_EXPR:
> + /* Handle X << CST as X * (1 << CST) and only process the constant. */
> + if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
> + {
> + op1 = TREE_OPERAND (top, 1);
> + if (wi::gtu_p (TYPE_PRECISION (type), wi::to_wide (op1)))
> + {
> + wide_int mul_op
> + = wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
> + return multiple_of_p (type,
> + wide_int_to_tree (type, mul_op), bottom);
> + }
> + }
> + return 0;
> +
LGTM. Sorry for the slow response.
I guess the condition could be written:
if (wi::to_widest (op1) < TYPE_PRECISION (type))
which might be more readable, and also avoids accidentally reinterpreting
a sign.
Thanks,
Richard
> case MINUS_EXPR:
> /* It is impossible to prove if op0 - op1 is multiple of bottom
> precisely, so be conservative here checking if both op0 and op1
> @@ -14133,22 +14148,6 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
> return (multiple_of_p (type, op1, bottom)
> && multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
>
> - case LSHIFT_EXPR:
> - if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
> - {
> - op1 = TREE_OPERAND (top, 1);
> - /* const_binop may not detect overflow correctly,
> - so check for it explicitly here. */
> - if (wi::gtu_p (TYPE_PRECISION (TREE_TYPE (size_one_node)),
> - wi::to_wide (op1))
> - && (t1 = fold_convert (type,
> - const_binop (LSHIFT_EXPR, size_one_node,
> - op1))) != 0
> - && !TREE_OVERFLOW (t1))
> - return multiple_of_p (type, t1, bottom);
> - }
> - return 0;
> -
> CASE_CONVERT:
> /* Can't handle conversions from non-integral or wider integral type. */
> if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)
On Fri, 4 Feb 2022, Richard Sandiford wrote:
> Richard Biener <rguenther@suse.de> writes:
> > This removes the odd check of size_type_node when handling left-shifts
> > as multiplications of 1 << N and instead uses the type as specified.
> > It also moves left-shift handling next to multiplications where it
> > semantically belongs.
> >
> > Boostrap and regtest pending on x86_64-unknown-linux-gnu.
> >
> > OK? (I failed to short-cut the wide_int_to_tree for a
> > poly_int_cst_p bottom)
> >
> > Thanks,
> > Richard.
> >
> > 2022-01-24 Richard Biener <rguenther@suse.de>
> >
> > * fold-const.cc (multiple_of_p): Re-write and move LSHIFT_EXPR
> > handling.
> > ---
> > gcc/fold-const.cc | 33 ++++++++++++++++-----------------
> > 1 file changed, 16 insertions(+), 17 deletions(-)
> >
> > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
> > index b155611578d..a0a4913c45e 100644
> > --- a/gcc/fold-const.cc
> > +++ b/gcc/fold-const.cc
> > @@ -14068,7 +14068,7 @@ int
> > multiple_of_p (tree type, const_tree top, const_tree bottom)
> > {
> > gimple *stmt;
> > - tree t1, op1, op2;
> > + tree op1, op2;
> >
> > if (operand_equal_p (top, bottom, 0))
> > return 1;
> > @@ -14114,6 +14114,21 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
> > return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
> > || multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
> >
> > + case LSHIFT_EXPR:
> > + /* Handle X << CST as X * (1 << CST) and only process the constant. */
> > + if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
> > + {
> > + op1 = TREE_OPERAND (top, 1);
> > + if (wi::gtu_p (TYPE_PRECISION (type), wi::to_wide (op1)))
> > + {
> > + wide_int mul_op
> > + = wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
> > + return multiple_of_p (type,
> > + wide_int_to_tree (type, mul_op), bottom);
> > + }
> > + }
> > + return 0;
> > +
>
> LGTM. Sorry for the slow response.
>
> I guess the condition could be written:
>
> if (wi::to_widest (op1) < TYPE_PRECISION (type))
>
> which might be more readable, and also avoids accidentally reinterpreting
> a sign.
Good idea - I'll adjust, re-test and push.
Thanks,
Richard.
@@ -14068,7 +14068,7 @@ int
multiple_of_p (tree type, const_tree top, const_tree bottom)
{
gimple *stmt;
- tree t1, op1, op2;
+ tree op1, op2;
if (operand_equal_p (top, bottom, 0))
return 1;
@@ -14114,6 +14114,21 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
|| multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
+ case LSHIFT_EXPR:
+ /* Handle X << CST as X * (1 << CST) and only process the constant. */
+ if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
+ {
+ op1 = TREE_OPERAND (top, 1);
+ if (wi::gtu_p (TYPE_PRECISION (type), wi::to_wide (op1)))
+ {
+ wide_int mul_op
+ = wi::one (TYPE_PRECISION (type)) << wi::to_wide (op1);
+ return multiple_of_p (type,
+ wide_int_to_tree (type, mul_op), bottom);
+ }
+ }
+ return 0;
+
case MINUS_EXPR:
/* It is impossible to prove if op0 - op1 is multiple of bottom
precisely, so be conservative here checking if both op0 and op1
@@ -14133,22 +14148,6 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
return (multiple_of_p (type, op1, bottom)
&& multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
- case LSHIFT_EXPR:
- if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
- {
- op1 = TREE_OPERAND (top, 1);
- /* const_binop may not detect overflow correctly,
- so check for it explicitly here. */
- if (wi::gtu_p (TYPE_PRECISION (TREE_TYPE (size_one_node)),
- wi::to_wide (op1))
- && (t1 = fold_convert (type,
- const_binop (LSHIFT_EXPR, size_one_node,
- op1))) != 0
- && !TREE_OVERFLOW (t1))
- return multiple_of_p (type, t1, bottom);
- }
- return 0;
-
CASE_CONVERT:
/* Can't handle conversions from non-integral or wider integral type. */
if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)