tree-optimization/114121 - chrec_fold_{plus,multiply} and recursion
The following addresses endless recursion in the chrec_fold_{plus,multiply} functions when handling sign-conversions. We only need to apply tricks when we'd fail (there's a chrec in the converted operand) and we need to make sure to not turn the other operand into something worse (for the chrec-vs-chrec case). PR tree-optimization/114121 * tree-chrec.cc (chrec_fold_plus_1): Guard recursion with converted operand properly. (chrec_fold_multiply): Likewise. Handle missed recursion. * gcc.dg/torture/pr114312.c: New testcase.
This commit is contained in:
parent
4aa87b8560
commit
73dac51b32
2 changed files with 107 additions and 84 deletions
15
gcc/testsuite/gcc.dg/torture/pr114312.c
Normal file
15
gcc/testsuite/gcc.dg/torture/pr114312.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target bitint } */
|
||||
|
||||
#if __BITINT_MAXWIDTH__ >= 129
|
||||
typedef _BitInt(129) B;
|
||||
B b;
|
||||
|
||||
B
|
||||
foo(void)
|
||||
{
|
||||
_BitInt(64) a = 1;
|
||||
a &= b * b;
|
||||
return b << a;
|
||||
}
|
||||
#endif
|
|
@ -251,23 +251,27 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
|
|||
return chrec_fold_plus_poly_poly (code, type, op0, op1);
|
||||
|
||||
CASE_CONVERT:
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_plus_1 (code, optype,
|
||||
chrec_convert (optype,
|
||||
op0, NULL),
|
||||
TREE_OPERAND (op1, 0)),
|
||||
NULL);
|
||||
if (tree_contains_chrecs (op1, NULL))
|
||||
if (tree_contains_chrecs (op1, NULL))
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
{
|
||||
tree tem = chrec_convert (optype, op0, NULL);
|
||||
if (TREE_CODE (tem) == POLYNOMIAL_CHREC)
|
||||
return chrec_convert (type,
|
||||
chrec_fold_plus_1 (code, optype,
|
||||
tem,
|
||||
TREE_OPERAND
|
||||
(op1, 0)),
|
||||
NULL);
|
||||
}
|
||||
return chrec_dont_know;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
default:
|
||||
|
@ -284,26 +288,27 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
|
|||
}
|
||||
|
||||
CASE_CONVERT:
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_plus_1 (code, optype,
|
||||
TREE_OPERAND (op0, 0),
|
||||
chrec_convert (optype,
|
||||
op1, NULL)),
|
||||
NULL);
|
||||
if (tree_contains_chrecs (op0, NULL))
|
||||
if (tree_contains_chrecs (op0, NULL))
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_plus_1 (code, optype,
|
||||
TREE_OPERAND (op0, 0),
|
||||
chrec_convert (optype,
|
||||
op1, NULL)),
|
||||
NULL);
|
||||
return chrec_dont_know;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
default:
|
||||
gcc_checking_assert (!tree_contains_chrecs (op0, NULL));
|
||||
switch (TREE_CODE (op1))
|
||||
{
|
||||
case POLYNOMIAL_CHREC:
|
||||
|
@ -325,24 +330,24 @@ chrec_fold_plus_1 (enum tree_code code, tree type,
|
|||
: build_int_cst_type (type, -1)));
|
||||
|
||||
CASE_CONVERT:
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_plus_1 (code, optype,
|
||||
chrec_convert (optype,
|
||||
op0, NULL),
|
||||
TREE_OPERAND (op1, 0)),
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (tree_contains_chrecs (op1, NULL))
|
||||
return chrec_dont_know;
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_plus_1 (code, optype,
|
||||
chrec_convert (optype,
|
||||
op0,
|
||||
NULL),
|
||||
TREE_OPERAND (op1, 0)),
|
||||
NULL);
|
||||
return chrec_dont_know;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
default:
|
||||
|
@ -440,24 +445,26 @@ chrec_fold_multiply (tree type,
|
|||
return chrec_fold_multiply_poly_poly (type, op0, op1);
|
||||
|
||||
CASE_CONVERT:
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_multiply (optype,
|
||||
chrec_convert (optype,
|
||||
op0, NULL),
|
||||
TREE_OPERAND (op1, 0)),
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (tree_contains_chrecs (op1, NULL))
|
||||
return chrec_dont_know;
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op1, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
{
|
||||
tree tem = chrec_convert (optype, op0, NULL);
|
||||
if (TREE_CODE (tem) == POLYNOMIAL_CHREC)
|
||||
return chrec_convert (type,
|
||||
chrec_fold_multiply (optype, tem,
|
||||
TREE_OPERAND
|
||||
(op1, 0)),
|
||||
NULL);
|
||||
}
|
||||
return chrec_dont_know;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
default:
|
||||
|
@ -506,27 +513,28 @@ chrec_fold_multiply (tree type,
|
|||
}
|
||||
|
||||
CASE_CONVERT:
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_multiply (optype,
|
||||
TREE_OPERAND (op0, 0),
|
||||
chrec_convert (optype,
|
||||
op1, NULL)),
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (tree_contains_chrecs (op0, NULL))
|
||||
return chrec_dont_know;
|
||||
{
|
||||
/* We can strip sign-conversions to signed by performing the
|
||||
operation in unsigned. */
|
||||
tree optype = TREE_TYPE (TREE_OPERAND (op0, 0));
|
||||
if (INTEGRAL_TYPE_P (type)
|
||||
&& INTEGRAL_TYPE_P (optype)
|
||||
&& tree_nop_conversion_p (type, optype)
|
||||
&& TYPE_UNSIGNED (optype))
|
||||
return chrec_convert (type,
|
||||
chrec_fold_multiply (optype,
|
||||
TREE_OPERAND (op0, 0),
|
||||
chrec_convert (optype,
|
||||
op1,
|
||||
NULL)),
|
||||
NULL);
|
||||
return chrec_dont_know;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
default:
|
||||
gcc_checking_assert (!tree_contains_chrecs (op0, NULL));
|
||||
if (integer_onep (op0))
|
||||
return op1;
|
||||
|
||||
|
@ -540,7 +548,7 @@ chrec_fold_multiply (tree type,
|
|||
|
||||
CASE_CONVERT:
|
||||
if (tree_contains_chrecs (op1, NULL))
|
||||
return chrec_dont_know;
|
||||
return chrec_fold_multiply (type, op1, op0);
|
||||
/* FALLTHRU */
|
||||
|
||||
default:
|
||||
|
|
Loading…
Add table
Reference in a new issue