Message ID | 20151126161026.GY21807@redhat.com |
---|---|
State | New |
Headers | show |
On Thu, Nov 26, 2015 at 05:10:26PM +0100, Marek Polacek wrote: > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2015-11-26 Marek Polacek <polacek@redhat.com> > > PR c/68513 > * c-gimplify.c (strip_c_maybe_const_expr_r): New. > (c_gimplify_expr): Call it. > > * gcc.dg/torture/pr68513.c: New test. > > diff --git gcc/c-family/c-gimplify.c gcc/c-family/c-gimplify.c > index fc4a44a..c096575 100644 > --- gcc/c-family/c-gimplify.c > +++ gcc/c-family/c-gimplify.c > @@ -212,6 +212,21 @@ c_build_bind_expr (location_t loc, tree block, tree body) > > /* Gimplification of expression trees. */ > > +/* Callback for c_gimplify_expr. Strip C_MAYBE_CONST_EXPRs in TP so that > + they don't leak into the middle end. */ > + > +static tree > +strip_c_maybe_const_expr_r (tree *tp, int *walk_subtrees, void *) > +{ > + if (TREE_CODE (*tp) == C_MAYBE_CONST_EXPR) > + { > + gcc_assert (C_MAYBE_CONST_EXPR_PRE (*tp) == NULL_TREE); > + *tp = C_MAYBE_CONST_EXPR_EXPR (*tp); > + *walk_subtrees = 0; > + } > + return NULL_TREE; > +} > + > /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in > gimplify_expr. */ > > @@ -296,6 +311,10 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, > return (enum gimplify_status) gimplify_cilk_spawn (expr_p); > } > > + case SAVE_EXPR: > + walk_tree_without_duplicates (expr_p, strip_c_maybe_const_expr_r, NULL); Shouldn't this be done only if (!SAVE_EXPR_RESOLVED_P (*expr_p))? Otherwise I fear bad compile time complexity, consider huge tree containing lots of nested SAVE_EXPRs and every SAVE_EXPR appearing twice or more times somewhere in the tree. Perhaps the walk should also *walk_subtrees = 0; for SAVE_EXPRs and start walking &TREE_OPERAND (*expr_p, 0) instead of expr_p. The nested SAVE_EXPRs would be handled when those are gimplified. Jakub
On Thu, 26 Nov 2015, Marek Polacek wrote: > My worry was of course C_MAYBE_CONST_EXPR_PRE. But it seems we'll never have > any at that point, since it's already been processed and transformed to a > COMPOUND_EXPR. But do I like this patch? No. It's not obvious to me that it will always have been transformed - if a C_MAYBE_CONST_EXPR has escaped to gimplification, why shouldn't it be one with C_MAYBE_CONST_EXPR_PRE? Also, on further consideration: the folding via c_fully_fold is relied upon to get information about whether an expression contains anything that cannot occur in an evaluated part of a constant expression / outside sizeof in a constant expression in C90 mode. So if a SAVE_EXPR is created by language-independent code, c_fully_fold doesn't see inside it and you lose that information. What that says to me is that maybe a better interim solution would be a lang hook for the folders to use to call c_save_expr instead of save_expr. And then longer term: (a) maybe any folding that involves duplicating expressions and so needs to create SAVE_EXPRs would better be done only at the GIMPLE level, and (b) folding for conversions should be delayed as much as possible like other folding (and optimizations of conversions should move from convert.c to match.pd).
On Thu, Nov 26, 2015 at 04:36:34PM +0000, Joseph Myers wrote: > On Thu, 26 Nov 2015, Marek Polacek wrote: > > > My worry was of course C_MAYBE_CONST_EXPR_PRE. But it seems we'll never have > > any at that point, since it's already been processed and transformed to a > > COMPOUND_EXPR. But do I like this patch? No. > > It's not obvious to me that it will always have been transformed - if a > C_MAYBE_CONST_EXPR has escaped to gimplification, why shouldn't it be one > with C_MAYBE_CONST_EXPR_PRE? > > Also, on further consideration: the folding via c_fully_fold is relied > upon to get information about whether an expression contains anything that > cannot occur in an evaluated part of a constant expression / outside > sizeof in a constant expression in C90 mode. So if a SAVE_EXPR is created > by language-independent code, c_fully_fold doesn't see inside it and you > lose that information. What that says to me is that maybe a better > interim solution would be a lang hook for the folders to use to call > c_save_expr instead of save_expr. And then longer term: (a) maybe any > folding that involves duplicating expressions and so needs to create But the condition whether to call c_save_expr or whether to call save_expr instead is not constant in the C FE. If c_fully_fold is expected to be called on the expression, then c_save_expr needs to be used, otherwise save_expr. Can we rely on in_late_binary_op for that? > SAVE_EXPRs would better be done only at the GIMPLE level, and (b) folding > for conversions should be delayed as much as possible like other folding > (and optimizations of conversions should move from convert.c to match.pd). Jakub
On Thu, 26 Nov 2015, Jakub Jelinek wrote: > > Also, on further consideration: the folding via c_fully_fold is relied > > upon to get information about whether an expression contains anything that > > cannot occur in an evaluated part of a constant expression / outside > > sizeof in a constant expression in C90 mode. So if a SAVE_EXPR is created > > by language-independent code, c_fully_fold doesn't see inside it and you > > lose that information. What that says to me is that maybe a better > > interim solution would be a lang hook for the folders to use to call > > c_save_expr instead of save_expr. And then longer term: (a) maybe any > > folding that involves duplicating expressions and so needs to create > > But the condition whether to call c_save_expr or whether to call save_expr > instead is not constant in the C FE. > If c_fully_fold is expected to be called on the expression, then c_save_expr > needs to be used, otherwise save_expr. > Can we rely on in_late_binary_op for that? Yes, I think so.
On Thu, Nov 26, 2015 at 05:05:09PM +0000, Joseph Myers wrote: > On Thu, 26 Nov 2015, Jakub Jelinek wrote: > > > > Also, on further consideration: the folding via c_fully_fold is relied > > > upon to get information about whether an expression contains anything that > > > cannot occur in an evaluated part of a constant expression / outside > > > sizeof in a constant expression in C90 mode. So if a SAVE_EXPR is created > > > by language-independent code, c_fully_fold doesn't see inside it and you > > > lose that information. What that says to me is that maybe a better > > > interim solution would be a lang hook for the folders to use to call > > > c_save_expr instead of save_expr. And then longer term: (a) maybe any > > > folding that involves duplicating expressions and so needs to create > > > > But the condition whether to call c_save_expr or whether to call save_expr > > instead is not constant in the C FE. > > If c_fully_fold is expected to be called on the expression, then c_save_expr > > needs to be used, otherwise save_expr. > > Can we rely on in_late_binary_op for that? > > Yes, I think so. It seems only to be set temporarily when calling convert*, then reset back, while we supposedly want to use save_expr instead of c_save_expr also at the point where we are genericizing, or gimplifying etc. Jakub
On Thu, 26 Nov 2015, Jakub Jelinek wrote: > > > But the condition whether to call c_save_expr or whether to call save_expr > > > instead is not constant in the C FE. > > > If c_fully_fold is expected to be called on the expression, then c_save_expr > > > needs to be used, otherwise save_expr. > > > Can we rely on in_late_binary_op for that? > > > > Yes, I think so. > > It seems only to be set temporarily when calling convert*, then reset > back, while we supposedly want to use save_expr instead of c_save_expr also > at the point where we are genericizing, or gimplifying etc. OK, then we may need a new flag that indicates that we are doing some processing after all the constant expression checks from parsing have been done. (With an eventual preference that anything creating SAVE_EXPRs at all should happen at that late stage - that the front-end representation created during parsing should be closer to the source, including not needing to refer more than once to a given source expression, and genericizing / gimplifying / some such lowering step handling semantics that require SAVE_EXPRs.)
On November 26, 2015 5:36:34 PM GMT+01:00, Joseph Myers <joseph@codesourcery.com> wrote: >On Thu, 26 Nov 2015, Marek Polacek wrote: > >> My worry was of course C_MAYBE_CONST_EXPR_PRE. But it seems we'll >never have >> any at that point, since it's already been processed and transformed >to a >> COMPOUND_EXPR. But do I like this patch? No. > >It's not obvious to me that it will always have been transformed - if a > >C_MAYBE_CONST_EXPR has escaped to gimplification, why shouldn't it be >one >with C_MAYBE_CONST_EXPR_PRE? > >Also, on further consideration: the folding via c_fully_fold is relied >upon to get information about whether an expression contains anything >that >cannot occur in an evaluated part of a constant expression / outside >sizeof in a constant expression in C90 mode. So if a SAVE_EXPR is >created >by language-independent code, c_fully_fold doesn't see inside it and >you >lose that information. What that says to me is that maybe a better >interim solution would be a lang hook for the folders to use to call >c_save_expr instead of save_expr. And then longer term: (a) maybe any >folding that involves duplicating expressions and so needs to create >SAVE_EXPRs would better be done only at the GIMPLE level, and (b) >folding >for conversions should be delayed as much as possible like other >folding >(and optimizations of conversions should move from convert.c to >match.pd). It would be easy to simply never generate any save_exprs from genmatch generated code with the effect of disabling foldings that would need it (for correctness). Richard.
diff --git gcc/c-family/c-gimplify.c gcc/c-family/c-gimplify.c index fc4a44a..c096575 100644 --- gcc/c-family/c-gimplify.c +++ gcc/c-family/c-gimplify.c @@ -212,6 +212,21 @@ c_build_bind_expr (location_t loc, tree block, tree body) /* Gimplification of expression trees. */ +/* Callback for c_gimplify_expr. Strip C_MAYBE_CONST_EXPRs in TP so that + they don't leak into the middle end. */ + +static tree +strip_c_maybe_const_expr_r (tree *tp, int *walk_subtrees, void *) +{ + if (TREE_CODE (*tp) == C_MAYBE_CONST_EXPR) + { + gcc_assert (C_MAYBE_CONST_EXPR_PRE (*tp) == NULL_TREE); + *tp = C_MAYBE_CONST_EXPR_EXPR (*tp); + *walk_subtrees = 0; + } + return NULL_TREE; +} + /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in gimplify_expr. */ @@ -296,6 +311,10 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, return (enum gimplify_status) gimplify_cilk_spawn (expr_p); } + case SAVE_EXPR: + walk_tree_without_duplicates (expr_p, strip_c_maybe_const_expr_r, NULL); + break; + default:; } diff --git gcc/testsuite/gcc.dg/torture/pr68513.c gcc/testsuite/gcc.dg/torture/pr68513.c index e69de29..4e08b29 100644 --- gcc/testsuite/gcc.dg/torture/pr68513.c +++ gcc/testsuite/gcc.dg/torture/pr68513.c @@ -0,0 +1,13 @@ +/* PR c/68513 */ +/* { dg-do compile } */ + +int i; +unsigned u; +volatile unsigned int *e; + +void +fn1 (void) +{ + (short) ((i ? *e : 0) & ~u | i & u); + (short) (((0, 0) ? *e : 0) & ~u | i & u); +}