There were more omissions in how zero_one_operation works with the new way of processing negates in the context of multiplication chains.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. CPU 2006 build in progress as well. Richard. 2016-05-24 Richard Biener <rguent...@suse.de> PR tree-optimization/71230 * tree-ssa-reassoc.c (zero_one_operation): Handle negate special ops. * gcc.dg/torture/pr71230.c: New testcase. * g++.dg/torture/pr71230.C: Likewise. Index: gcc/tree-ssa-reassoc.c =================================================================== *** gcc/tree-ssa-reassoc.c (revision 236630) --- gcc/tree-ssa-reassoc.c (working copy) *************** zero_one_operation (tree *def, enum tree *** 1189,1200 **** { tree name; ! if (opcode == MULT_EXPR ! && stmt_is_power_of_op (stmt, op)) { ! if (decrement_power (stmt) == 1) ! propagate_op_to_single_use (op, stmt, def); ! return; } name = gimple_assign_rhs1 (stmt); --- 1191,1210 ---- { tree name; ! if (opcode == MULT_EXPR) { ! if (stmt_is_power_of_op (stmt, op)) ! { ! if (decrement_power (stmt) == 1) ! propagate_op_to_single_use (op, stmt, def); ! return; ! } ! else if (gimple_assign_rhs_code (stmt) == NEGATE_EXPR ! && gimple_assign_rhs1 (stmt) == op) ! { ! propagate_op_to_single_use (op, stmt, def); ! return; ! } } name = gimple_assign_rhs1 (stmt); *************** zero_one_operation (tree *def, enum tree *** 1213,1219 **** } /* We might have a multiply of two __builtin_pow* calls, and ! the operand might be hiding in the rightmost one. */ if (opcode == MULT_EXPR && gimple_assign_rhs_code (stmt) == opcode && TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME --- 1223,1230 ---- } /* We might have a multiply of two __builtin_pow* calls, and ! the operand might be hiding in the rightmost one. Likewise ! this can happen for a negate. */ if (opcode == MULT_EXPR && gimple_assign_rhs_code (stmt) == opcode && TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME *************** zero_one_operation (tree *def, enum tree *** 1226,1231 **** --- 1237,1249 ---- propagate_op_to_single_use (op, stmt2, def); return; } + else if (is_gimple_assign (stmt2) + && gimple_assign_rhs_code (stmt2) == NEGATE_EXPR + && gimple_assign_rhs1 (stmt2) == op) + { + propagate_op_to_single_use (op, stmt2, def); + return; + } } /* Continue walking the chain. */ Index: gcc/testsuite/gcc.dg/torture/pr71230.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr71230.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr71230.c (working copy) *************** *** 0 **** --- 1,25 ---- + /* { dg-do compile } */ + /* { dg-additional-options "-ffast-math" } */ + + void metric_carttosphere(int *cctk_lsh, double txz, double tyz, double txx, + double tzz, double sint, double cosp, double cost, + double tyy, double sinp, double txy, double *grp, + double *grq, double *r) + { + int i; + for(i=0; i<cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]; i++) + { + grq[i] = (cost*tyy*((sinp)*(sinp))*sint+ + 2*cosp*cost*txy*sinp*sint- + cost*tzz*sint+ + ((cosp)*(cosp))*cost*txx*sint+ + 2*((cost)*(cost))*tyz*sinp- + tyz*sinp+ + 2*cosp*((cost)*(cost))*txz- + cosp*txz)*r[i]; + grp[i] = ((-txy*((sinp)*(sinp))+ + (cosp*tyy-cosp*txx)*sinp+ + ((cosp)*(cosp))*txy)*sint- + cost*txz*sinp+cosp*cost*tyz); + } + } Index: gcc/testsuite/g++.dg/torture/pr71230.C =================================================================== --- gcc/testsuite/g++.dg/torture/pr71230.C (revision 0) +++ gcc/testsuite/g++.dg/torture/pr71230.C (working copy) @@ -0,0 +1,31 @@ +// { dg-do compile } +// { dg-additional-options "-ffast-math" } + +template <int rank, int dim> class Tensor; +template <int dim> class Point { +public: + Point (const double x, const double y, const double z); + double operator () (const unsigned int index) const; +}; +template <int celldim, int dim> class TriaObjectAccessor { + Point<dim> & vertex (const unsigned int i) const; + Point<dim> barycenter (double, double, double, double, double) const; +}; +template <> Point<3> TriaObjectAccessor<3, 3>::barycenter (double s6, double s7, double s1, double s2, double s3) const +{ + const double x[8] = { + vertex(0)(0), vertex(1)(0), vertex(2)(0), vertex(3)(0), vertex(4)(0), vertex(5)(0), vertex(6)(0), vertex(7)(0) }; + const double y[8] = { + vertex(0)(1), vertex(1)(1), vertex(2)(1), vertex(3)(1), vertex(4)(1), vertex(5)(1), vertex(6)(1), vertex(7)(1) }; + const double z[8] = { + vertex(0)(2), vertex(1)(2), vertex(2)(2), vertex(3)(2), vertex(4)(2), vertex(5)(2), vertex(6)(2), vertex(7)(2) }; + double s4, s5, s8; + const double unknown0 = s1*s2; + const double unknown1 = s1*s2; + s8 = -z[2]*x[1]*y[2]*z[5]+z[2]*y[1]*x[2]*z[5]-z[2]*z[1]*x[2]*y[5]+z[2]*z [1]*x[5]*y[2]+2.0*y[5]*x[7]*z[4]*z[4]-y[1]*x[2]*z[0]*z[0]+x[0]*y[3]*z[7]*z[7] -2.0*z[5]*z[5]*x[4]*y[1]+2.0*z[5]*z[5]*x[1]*y[4]+z[5]*z[5]*x[0]*y[4]-2.0*z[2]*z [2]*x[1]*y[3]+2.0*z[2]*z[2]*x[3]*y[1]-x[0]*y[4]*z[7]*z[7]-y[0]*x[3]*z[7]*z[7]+x [1]*y[0]*z[5]*z[5]; + s5 = s8+z[2]*x[6]*y[2]*z[5]-z[2]*x[5]*y[2]*z[6]-z[2]*x[2]*y[3]*z[7]-x[2]* y[3]*z[7]*z[7]+2.0*z[2]*x[2]*y[3]*z[1]-z[2]*y[2]*x[3]*z[0]+z[2]*y[2]*x[0]*z[3]- z[2]*x[2]*y[0]*z[3]-z[7]*y[2]*x[7]*z[3]+z[7]*z[2]*x[7]*y[3]+z[7]*x[2]*y[7]*z[3] +z[6]*y[1]*x[2]*z[5]-z[6]*x[1]*y[2]*z[5]+z[5]*x[1]*y[5]*z[2]+s6+s7; + s4 = 1/s5; + s2 = s3*s4; + const double unknown2 = s1*s2; + return Point<3> (unknown0, unknown1, unknown2); +}