Message ID | 20130617161642.GA2336@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
On Mon, 17 Jun 2013, Jakub Jelinek wrote: > The following patch shows a performance regression caused by the C++ changes > to evaluate side-effects in x += foo (); first and only then do the > addition. Previously if x was say int and foo () returned unsigned long > long, convert_to_integer would narrow the addition to unsigned int, but > as we now pass to convert_to_* a COMPOUND_EXPR with the side-effects on the > op0 and addition on op1 of the COMPOUND_EXPR, convert_to_integer doesn't > perform this shortening and unfortunately we don't have any gimple > optimization yet to do this later on. This patch fixes it by handling > COMPOUND_EXPR in convert_to_* where we care about TREE_CODE of the expr. > > Ok for trunk? Ok for 4.8 as well after a while? I suppose it's OK to fix the regression, though really we should be eliminating these early convert_to_* optimizations (optimizing later on GIMPLE if possible) rather than adding to them.
On 06/17/2013 12:54 PM, Joseph S. Myers wrote: > I suppose it's OK to fix the regression, though really we should be > eliminating these early convert_to_* optimizations (optimizing later on > GIMPLE if possible) rather than adding to them. My thought as well. How hard is it to fix this in gimple fold? Jason
On Mon, Jun 17, 2013 at 01:44:25PM -0400, Jason Merrill wrote: > On 06/17/2013 12:54 PM, Joseph S. Myers wrote: > >I suppose it's OK to fix the regression, though really we should be > >eliminating these early convert_to_* optimizations (optimizing later on > >GIMPLE if possible) rather than adding to them. > > My thought as well. How hard is it to fix this in gimple fold? PRs for it are open for almost 3 years now, I think Kai has some patch, but it hasn't been posted yet, so it is unclear if it would make 4.9. In any case, it isn't probably something that can be backported to release branches, while perhaps this simple convert.c change is. Once we have it in GIMPLE, sure, the change in convert.c can be happily reverted and also those optimizations removed from there too. Jakub
On 06/17/2013 02:09 PM, Jakub Jelinek wrote: > On Mon, Jun 17, 2013 at 01:44:25PM -0400, Jason Merrill wrote: >> On 06/17/2013 12:54 PM, Joseph S. Myers wrote: >>> I suppose it's OK to fix the regression, though really we should be >>> eliminating these early convert_to_* optimizations (optimizing later on >>> GIMPLE if possible) rather than adding to them. >> >> My thought as well. How hard is it to fix this in gimple fold? > > PRs for it are open for almost 3 years now, I think Kai has some patch, but > it hasn't been posted yet, so it is unclear if it would make 4.9. Kai, what's the status of this patch? Jason
On Mon, Jun 17, 2013 at 6:54 PM, Joseph S. Myers <joseph@codesourcery.com> wrote: > On Mon, 17 Jun 2013, Jakub Jelinek wrote: > >> The following patch shows a performance regression caused by the C++ changes >> to evaluate side-effects in x += foo (); first and only then do the >> addition. Previously if x was say int and foo () returned unsigned long >> long, convert_to_integer would narrow the addition to unsigned int, but >> as we now pass to convert_to_* a COMPOUND_EXPR with the side-effects on the >> op0 and addition on op1 of the COMPOUND_EXPR, convert_to_integer doesn't >> perform this shortening and unfortunately we don't have any gimple >> optimization yet to do this later on. This patch fixes it by handling >> COMPOUND_EXPR in convert_to_* where we care about TREE_CODE of the expr. >> >> Ok for trunk? Ok for 4.8 as well after a while? > > I suppose it's OK to fix the regression, though really we should be > eliminating these early convert_to_* optimizations (optimizing later on > GIMPLE if possible) rather than adding to them. I agree. The correct place for this is in tree-ssa-forwprop.c (for now). Richard.
--- gcc/convert.c.jj 2013-05-13 09:44:53.000000000 +0200 +++ gcc/convert.c 2013-06-16 12:16:13.754108523 +0200 @@ -95,6 +95,15 @@ convert_to_real (tree type, tree expr) enum built_in_function fcode = builtin_mathfn_code (expr); tree itype = TREE_TYPE (expr); + if (TREE_CODE (expr) == COMPOUND_EXPR) + { + tree t = convert_to_real (type, TREE_OPERAND (expr, 1)); + if (t == TREE_OPERAND (expr, 1)) + return expr; + return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), + TREE_OPERAND (expr, 0), t); + } + /* Disable until we figure out how to decide whether the functions are present in runtime. */ /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ @@ -366,6 +375,15 @@ convert_to_integer (tree type, tree expr return error_mark_node; } + if (ex_form == COMPOUND_EXPR) + { + tree t = convert_to_integer (type, TREE_OPERAND (expr, 1)); + if (t == TREE_OPERAND (expr, 1)) + return expr; + return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), + TREE_OPERAND (expr, 0), t); + } + /* Convert e.g. (long)round(d) -> lround(d). */ /* If we're converting to char, we may encounter differing behavior between converting from double->char vs double->long->char. @@ -854,6 +872,14 @@ convert_to_complex (tree type, tree expr if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype)) return expr; + else if (TREE_CODE (expr) == COMPOUND_EXPR) + { + tree t = convert_to_complex (type, TREE_OPERAND (expr, 1)); + if (t == TREE_OPERAND (expr, 1)) + return expr; + return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, + TREE_TYPE (t), TREE_OPERAND (expr, 0), t); + } else if (TREE_CODE (expr) == COMPLEX_EXPR) return fold_build2 (COMPLEX_EXPR, type, convert (subtype, TREE_OPERAND (expr, 0)), --- gcc/testsuite/c-c++-common/pr56493.c.jj 2013-06-17 10:24:36.891659600 +0200 +++ gcc/testsuite/c-c++-common/pr56493.c 2013-06-17 10:24:33.164720149 +0200 @@ -0,0 +1,16 @@ +/* PR c++/56493 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +unsigned long long bar (void); +int x; + +void +foo (void) +{ + x += bar (); +} + +/* Verify we narrow the addition from unsigned long long to unsigned int type. */ +/* { dg-final { scan-tree-dump " (\[a-zA-Z._0-9]*) = \\(unsigned int\\) \[^;\n\r]*;.* (\[a-zA-Z._0-9]*) = \\(unsigned int\\) \[^;\n\r]*;.* = \\1 \\+ \\2;" "gimple" { target { ilp32 || lp64 } } } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */