On Fri, 11 Jun 2021, Jakub Jelinek wrote: > Hi! > > simplify_relational_operation callees typically return just const0_rtx > or const_true_rtx and then simplify_relational_operation attempts to fix > that up if the comparison result has vector mode, or floating mode, > or punt if it has scalar mode and vector mode operands (it doesn't know how > exactly to deal with the scalar masks). > But, simplify_logical_relational_operation has a special case, where > it attempts to fold (x < y) | (x >= y) etc. and if it determines it is > always true, it just returns const_true_rtx, without doing the dances that > simplify_relational_operation does. > That results in an ICE on the following testcase, where such folding happens > during expansion (of debug stmts into DEBUG_INSNs) and we ICE because > all of sudden a VOIDmode rtx appears where it expects a vector (V4SImode) > rtx. > > The following patch fixes that by moving the adjustement into a separate > helper routine and using it from both simplify_relational_operation and > simplify_logical_relational_operation. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Thanks, Richard. > 2021-06-11 Jakub Jelinek <ja...@redhat.com> > > PR rtl-optimization/101008 > * simplify-rtx.c (relational_result): New function. > (simplify_logical_relational_operation, > simplify_relational_operation): Use it. > > * gcc.dg/pr101008.c: New test. > > --- gcc/simplify-rtx.c.jj 2021-05-04 21:02:24.000000000 +0200 > +++ gcc/simplify-rtx.c 2021-06-10 13:56:48.946628822 +0200 > @@ -2294,6 +2294,53 @@ comparison_code_valid_for_mode (enum rtx > gcc_unreachable (); > } > } > + > +/* Canonicalize RES, a scalar const0_rtx/const_true_rtx to the right > + false/true value of comparison with MODE where comparison operands > + have CMP_MODE. */ > + > +static rtx > +relational_result (machine_mode mode, machine_mode cmp_mode, rtx res) > +{ > + if (SCALAR_FLOAT_MODE_P (mode)) > + { > + if (res == const0_rtx) > + return CONST0_RTX (mode); > +#ifdef FLOAT_STORE_FLAG_VALUE > + REAL_VALUE_TYPE val = FLOAT_STORE_FLAG_VALUE (mode); > + return const_double_from_real_value (val, mode); > +#else > + return NULL_RTX; > +#endif > + } > + if (VECTOR_MODE_P (mode)) > + { > + if (res == const0_rtx) > + return CONST0_RTX (mode); > +#ifdef VECTOR_STORE_FLAG_VALUE > + rtx val = VECTOR_STORE_FLAG_VALUE (mode); > + if (val == NULL_RTX) > + return NULL_RTX; > + if (val == const1_rtx) > + return CONST1_RTX (mode); > + > + return gen_const_vec_duplicate (mode, val); > +#else > + return NULL_RTX; > +#endif > + } > + /* For vector comparison with scalar int result, it is unknown > + if the target means here a comparison into an integral bitmask, > + or comparison where all comparisons true mean const_true_rtx > + whole result, or where any comparisons true mean const_true_rtx > + whole result. For const0_rtx all the cases are the same. */ > + if (VECTOR_MODE_P (cmp_mode) > + && SCALAR_INT_MODE_P (mode) > + && res == const_true_rtx) > + return NULL_RTX; > + > + return res; > +} > > /* Simplify a logical operation CODE with result mode MODE, operating on OP0 > and OP1, which should be both relational operations. Return 0 if no such > @@ -2329,7 +2376,7 @@ simplify_context::simplify_logical_relat > int mask = mask0 | mask1; > > if (mask == 15) > - return const_true_rtx; > + return relational_result (mode, GET_MODE (op0), const_true_rtx); > > code = mask_to_comparison (mask); > > @@ -5315,51 +5362,7 @@ simplify_context::simplify_relational_op > > tem = simplify_const_relational_operation (code, cmp_mode, op0, op1); > if (tem) > - { > - if (SCALAR_FLOAT_MODE_P (mode)) > - { > - if (tem == const0_rtx) > - return CONST0_RTX (mode); > -#ifdef FLOAT_STORE_FLAG_VALUE > - { > - REAL_VALUE_TYPE val; > - val = FLOAT_STORE_FLAG_VALUE (mode); > - return const_double_from_real_value (val, mode); > - } > -#else > - return NULL_RTX; > -#endif > - } > - if (VECTOR_MODE_P (mode)) > - { > - if (tem == const0_rtx) > - return CONST0_RTX (mode); > -#ifdef VECTOR_STORE_FLAG_VALUE > - { > - rtx val = VECTOR_STORE_FLAG_VALUE (mode); > - if (val == NULL_RTX) > - return NULL_RTX; > - if (val == const1_rtx) > - return CONST1_RTX (mode); > - > - return gen_const_vec_duplicate (mode, val); > - } > -#else > - return NULL_RTX; > -#endif > - } > - /* For vector comparison with scalar int result, it is unknown > - if the target means here a comparison into an integral bitmask, > - or comparison where all comparisons true mean const_true_rtx > - whole result, or where any comparisons true mean const_true_rtx > - whole result. For const0_rtx all the cases are the same. */ > - if (VECTOR_MODE_P (cmp_mode) > - && SCALAR_INT_MODE_P (mode) > - && tem == const_true_rtx) > - return NULL_RTX; > - > - return tem; > - } > + return relational_result (mode, cmp_mode, tem); > > /* For the following tests, ensure const0_rtx is op1. */ > if (swap_commutative_operands_p (op0, op1) > --- gcc/testsuite/gcc.dg/pr101008.c.jj 2021-06-10 14:20:02.230559294 > +0200 > +++ gcc/testsuite/gcc.dg/pr101008.c 2021-06-10 14:19:36.518911260 +0200 > @@ -0,0 +1,18 @@ > +/* PR rtl-optimization/101008 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -g" } */ > + > +typedef unsigned __attribute__((__vector_size__(32))) U; > +typedef unsigned __attribute__((__vector_size__(16))) V; > + > +int c, r; > + > +V v; > + > +void > +foo(void) > +{ > + U u = __builtin_shufflevector (v, (V)(v != c) | (V)(c == v), > + 4, 3, 5, 5, 1, 2, 3, 0); > + r = ((union { U a; int b; }) u).b; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)