Break infinite folding loop
Richard Biener
richard.guenther@gmail.com
Thu May 16 09:02:00 GMT 2013
On Thu, May 16, 2013 at 8:42 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> we can get into a cycle where:
> (x<0)|1 becomes (x<0)?-1:1
> and
> (y?-1:1) becomes y|1
>
> Contrary to what I posted in the PR, I am disabling the second
> transformation here. It can be done later (the x86 target partially does it
> in the vcond expansion), and the VEC_COND_EXPR allows us to perform further
> operations:
> (((x<0)|1)*5-1)/2 becomes (untested) (x<0)?-3:2
>
> Also, this is a partial revert of the last patch, which sounds safer. I am
> leaving the vector tests in the disabled transformations in case we decide
> to re-enable them later.
>
> This isn't the end of the story, even for fold-const.c. I kept the
> transformation a?-1:0 -> a, but it does not work because:
>
> /* If we try to convert OP0 to our type, the
> call to fold will try to move the conversion inside
> a COND, which will recurse. In that case, the COND_EXPR
> is probably the best choice, so leave it alone. */
> && type == TREE_TYPE (arg0))
>
> and when a is a comparison, its type is a different type (even looking
> through main variant and canonical), only useless_type_conversion_p notices
> they are so similar, and I would still need a conversion, otherwise the
> front-end complains when I try to assign the result that it has a different
> type than the variable I want to assign it to (I expected the result of the
> comparison to be opaque, and thus no complaining, but apparently not).
Which is why most of these non-trivial transforms should happen on GIMPLE
via what I and Andrew proposed some year(s) ago. But well ...
> Also, we may want to make fold_binary_op_with_conditional_arg more strict on
> how much folding is necessary to consider the transformation worth it. For
> VEC_COND_EXPR where both branches are evaluated anyway, at least if we
> started from a comparison and not already a VEC_COND_EXPR, we could require
> that both branches fold.
>
> But it seems better to fix the ICE quickly and do the rest later.
>
> Passes bootstrap+testsuite on x86_64-linux-gnu.
Ok.
Thanks,
Richard.
> 2013-05-16 Marc Glisse <marc.glisse@inria.fr>
>
> PR middle-end/57286
> gcc/
> * fold-const.c (fold_ternary_loc) <VEC_COND_EXPR>: Disable some
> transformations to avoid an infinite loop.
>
> gcc/testsuite/
> * gcc.dg/pr57286.c: New testcase.
> * gcc.dg/vector-shift-2.c: Don't assume int has size 4.
> * g++.dg/ext/vector22.C: Comment out transformations not
> performed anymore.
>
> --
> Marc Glisse
> Index: testsuite/gcc.dg/pr57286.c
> ===================================================================
> --- testsuite/gcc.dg/pr57286.c (revision 0)
> +++ testsuite/gcc.dg/pr57286.c (revision 0)
> @@ -0,0 +1,7 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O" } */
> +
> +typedef int vec __attribute__ ((vector_size (4*sizeof(int))));
> +void f (vec *x){
> + *x = (*x < 0) | 1;
> +}
>
> Property changes on: testsuite/gcc.dg/pr57286.c
> ___________________________________________________________________
> Added: svn:keywords
> + Author Date Id Revision URL
> Added: svn:eol-style
> + native
>
> Index: testsuite/gcc.dg/vector-shift-2.c
> ===================================================================
> --- testsuite/gcc.dg/vector-shift-2.c (revision 198950)
> +++ testsuite/gcc.dg/vector-shift-2.c (working copy)
> @@ -1,13 +1,13 @@
> /* { dg-do compile } */
> /* { dg-options "-O -fdump-tree-ccp1" } */
>
> -typedef unsigned vec __attribute__ ((vector_size (16)));
> +typedef unsigned vec __attribute__ ((vector_size (4*sizeof(int))));
> void
> f (vec *a)
> {
> vec s = { 5, 5, 5, 5 };
> *a = *a << s;
> }
>
> /* { dg-final { scan-tree-dump "<< 5" "ccp1" } } */
> /* { dg-final { cleanup-tree-dump "ccp1" } } */
> Index: testsuite/g++.dg/ext/vector22.C
> ===================================================================
> --- testsuite/g++.dg/ext/vector22.C (revision 198950)
> +++ testsuite/g++.dg/ext/vector22.C (working copy)
> @@ -1,20 +1,22 @@
> /* { dg-do compile } */
> /* { dg-options "-O -fdump-tree-gimple" } */
>
> typedef unsigned vec __attribute__((vector_size(4*sizeof(int))));
>
> +/* Disabled after PR57286
> void f(vec*a,vec*b){
> *a=(*a)?-1:(*b<10);
> *b=(*b)?(*a<10):0;
> }
> +*/
> void g(vec*a,vec*b){
> *a=(*a)?(*a<*a):-1;
> - *b=(*b)?-1:(*b<*b);
> +// *b=(*b)?-1:(*b<*b);
> }
> void h(vec*a){
> *a=(~*a==5);
> }
>
> /* { dg-final { scan-tree-dump-not "~" "gimple" } } */
> /* { dg-final { scan-tree-dump-not "VEC_COND_EXPR" "gimple" } } */
> /* { dg-final { cleanup-tree-dump "gimple" } } */
> Index: fold-const.c
> ===================================================================
> --- fold-const.c (revision 198950)
> +++ fold-const.c (working copy)
> @@ -14204,20 +14204,26 @@ fold_ternary_loc (location_t loc, enum t
> && TREE_CODE (arg0) == NE_EXPR
> && integer_zerop (TREE_OPERAND (arg0, 1))
> && integer_pow2p (arg1)
> && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
> && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
> arg1, OEP_ONLY_CONST))
> return pedantic_non_lvalue_loc (loc,
> fold_convert_loc (loc, type,
> TREE_OPERAND (arg0,
> 0)));
>
> + /* Disable the transformations below for vectors, since
> + fold_binary_op_with_conditional_arg may undo them immediately,
> + yielding an infinite loop. */
> + if (code == VEC_COND_EXPR)
> + return NULL_TREE;
> +
> /* Convert A ? B : 0 into A && B if A and B are truth values. */
> if (integer_zerop (op2)
> && truth_value_p (TREE_CODE (arg0))
> && truth_value_p (TREE_CODE (arg1))
> && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
> return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR
> :
> TRUTH_ANDIF_EXPR,
> type, fold_convert_loc (loc, type, arg0),
> arg1);
>
> /* Convert A ? B : 1 into !A || B if A and B are truth values. */
>
More information about the Gcc-patches
mailing list