This is another case where a C_MAYBE_CONST_EXPR leaks into the gimplifier. Starting with r229128 and thus introduction of build_vec_cmp we now create VEC_COND_EXPR when building a vector comparison. The C_MAYBE_CONST_EXPR originated in build_compound_literal when creating a COMPOUND_LITERAL_EXPR. This is then made a part of op0 of a VEC_COND_EXPR. But c_fully_fold_internal doesn't know what to do with VEC_COND_EXPRs so the C_MAYBE_CONST_EXPR went unnoticed into fold, oops. The fix here is to teach c_fully_fold_internal how to handle VEC_COND_EXPRs, which is what this patch attempts to do.
Bootstrapped/regtested on x86_64-linux, ok for trunk? 2016-04-01 Marek Polacek <pola...@redhat.com> PR c/70307 * c-fold.c (c_fully_fold_internal): Handle VEC_COND_EXPR. * gcc.dg/torture/pr70307.c: New test. diff --git gcc/c/c-fold.c gcc/c/c-fold.c index f07917f..d512824 100644 --- gcc/c/c-fold.c +++ gcc/c/c-fold.c @@ -528,6 +528,23 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, *maybe_const_itself &= op2_const_self; goto out; + case VEC_COND_EXPR: + orig_op0 = op0 = TREE_OPERAND (expr, 0); + op1 = TREE_OPERAND (expr, 1); + op2 = TREE_OPERAND (expr, 2); + op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, + maybe_const_itself, for_int_const); + STRIP_TYPE_NOPS (op0); + + /* OP1 will be a vector of -1 and OP2 a vector if 0, as created in + build_vec_cmp -- no need to fold them. */ + + if (op0 != orig_op0) + ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2); + else + ret = fold (expr); + goto out; + case EXCESS_PRECISION_EXPR: /* Each case where an operand with excess precision may be encountered must remove the EXCESS_PRECISION_EXPR around diff --git gcc/testsuite/gcc.dg/torture/pr70307.c gcc/testsuite/gcc.dg/torture/pr70307.c index e69de29..d47c4b6 100644 --- gcc/testsuite/gcc.dg/torture/pr70307.c +++ gcc/testsuite/gcc.dg/torture/pr70307.c @@ -0,0 +1,62 @@ +/* PR c/70307 */ +/* { dg-do compile } */ + +typedef int v4si __attribute__ ((vector_size (16))); + +v4si foo (v4si); + +v4si +fn1 (int i) +{ + return i <= (v4si){(0, 0)}; +} + +v4si +fn2 (int i) +{ + v4si r; + r = i <= (v4si){(0, 0)}; + return r; +} + +v4si +fn3 (int i) +{ + return foo (i <= (v4si){(0, 0)}); +} + +v4si +fn4 (int i) +{ + struct S { v4si v; }; + struct S s = { .v = i <= (v4si){(0, 0)} }; + return s.v; +} + +v4si +fn5 (int i) +{ + return (v4si){(1, i++)} == (v4si){(0, 0)}; +} + +v4si +fn6 (int i) +{ + v4si r; + r = (v4si){(1, i++)} == (v4si){(0, 0)}; + return r; +} + +v4si +fn7 (int i) +{ + return foo ((v4si){(1, i++)} == (v4si){(0, 0)}); +} + +v4si +fn8 (int i) +{ + struct S { v4si v; }; + struct S s = { .v = (v4si){(1, i++)} == (v4si){(0, 0)} }; + return s.v; +} Marek