On Mon, 5 Dec 2011, Jakub Jelinek wrote: > Hi! > > When a multiply stmt has zero uses, convert_mult_to_fma immediately > returns true, meaning the multiplication can be deleted. Normally it should > be DCE job to remove dead stmts, not widening_mul pass IMHO, and in this > case it shouldn't be removed because it can throw and wasn't DCEd because of > it. For -fnon-call-exceptions if there is at least one use, we wouldn't be > optimizing multiply and add/sub into FMA, because the multiplication > (stmt_can_throw_p) would be in different bb from the addition/subtraction, > so there is no need to purge dead eh edges etc. in the caller. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. > 2011-12-05 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/51396 > * tree-ssa-math-opts.c (convert_mult_to_fma): Don't optimize > if MUL_RESULT has zero uses. > > * g++.dg/opt/pr51396.C: New test. > > --- gcc/tree-ssa-math-opts.c.jj 2011-10-18 23:52:03.000000000 +0200 > +++ gcc/tree-ssa-math-opts.c 2011-12-05 19:00:42.467551532 +0100 > @@ -2429,6 +2429,12 @@ convert_mult_to_fma (gimple mul_stmt, tr > if (optab_handler (fma_optab, TYPE_MODE (type)) == CODE_FOR_nothing) > return false; > > + /* If the multiplication has zero uses, it is kept around probably because > + of -fnon-call-exceptions. Don't optimize it away in that case, > + it is DCE job. */ > + if (has_zero_uses (mul_result)) > + return false; > + > /* Make sure that the multiplication statement becomes dead after > the transformation, thus that all uses are transformed to FMAs. > This means we assume that an FMA operation has the same cost > --- gcc/testsuite/g++.dg/opt/pr51396.C.jj 2011-12-05 19:03:36.793523559 > +0100 > +++ gcc/testsuite/g++.dg/opt/pr51396.C 2011-12-05 19:03:16.000000000 > +0100 > @@ -0,0 +1,24 @@ > +// PR tree-optimization/51396 > +// { dg-do compile } > +// { dg-options "-O2 -fnon-call-exceptions -mfma" } > +// { dg-options "-O2 -fnon-call-exceptions -mfma" { target i?86-*-* > x86_64-*-* } } > + > +double baz (double) throw (); > + > +struct C > +{ > + C (double d = 0.0) : c (d) {} > + double c; > +}; > + > +static inline void > +foo (double x, const C &y) > +{ > + x ? (y.c * baz (x)) : (C (), y); > +} > + > +void > +bar (double x, C y) > +{ > + foo (x, y); > +} > > Jakub > > -- Richard Guenther <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer