Submitted by Jakub Jelinek on July 4, 2011, 5:40 p.m.

Message ID | 20110704174043.GU16443@tyan-ft48-01.lab.bos.redhat.com |
---|---|

State | New |

Headers | show |

> 2011-07-04 Jakub Jelinek <jakub@redhat.com> > > PR rtl-optimization/49472 > * simplify-rtx.c (simplify_unary_operation_1) <case NEG>: When > negating MULT, negate the second operand instead of first. > (simplify_binary_operation_1) <case MULT>: If one operand is > a NEG and the other is MULT, don't attempt to optimize by > negation of the MULT operand if it only moves the NEG operation > around. > > * gfortran.dg/pr49472.f90: New test. OK for mainline and 4.6 branch.

--- gcc/simplify-rtx.c.jj 2011-06-21 16:46:01.000000000 +0200 +++ gcc/simplify-rtx.c 2011-07-04 12:14:51.000000000 +0200 @@ -686,13 +686,13 @@ simplify_unary_operation_1 (enum rtx_cod return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1)); } - /* (neg (mult A B)) becomes (mult (neg A) B). + /* (neg (mult A B)) becomes (mult A (neg B)). This works even for floating-point values. */ if (GET_CODE (op) == MULT && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) { - temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); - return simplify_gen_binary (MULT, mode, temp, XEXP (op, 1)); + temp = simplify_gen_unary (NEG, mode, XEXP (op, 1), mode); + return simplify_gen_binary (MULT, mode, XEXP (op, 0), temp); } /* NEG commutes with ASHIFT since it is multiplication. Only do @@ -2271,12 +2271,34 @@ simplify_binary_operation_1 (enum rtx_co if (GET_CODE (op0) == NEG) { rtx temp = simplify_unary_operation (NEG, mode, op1, mode); + /* If op1 is a MULT as well and simplify_unary_operation + just moved the NEG to the second operand, simplify_gen_binary + below could through simplify_associative_operation move + the NEG around again and recurse endlessly. */ + if (temp + && GET_CODE (op1) == MULT + && GET_CODE (temp) == MULT + && XEXP (op1, 0) == XEXP (temp, 0) + && GET_CODE (XEXP (temp, 1)) == NEG + && XEXP (op1, 1) == XEXP (XEXP (temp, 1), 0)) + temp = NULL_RTX; if (temp) return simplify_gen_binary (MULT, mode, XEXP (op0, 0), temp); } if (GET_CODE (op1) == NEG) { rtx temp = simplify_unary_operation (NEG, mode, op0, mode); + /* If op0 is a MULT as well and simplify_unary_operation + just moved the NEG to the second operand, simplify_gen_binary + below could through simplify_associative_operation move + the NEG around again and recurse endlessly. */ + if (temp + && GET_CODE (op0) == MULT + && GET_CODE (temp) == MULT + && XEXP (op0, 0) == XEXP (temp, 0) + && GET_CODE (XEXP (temp, 1)) == NEG + && XEXP (op0, 1) == XEXP (XEXP (temp, 1), 0)) + temp = NULL_RTX; if (temp) return simplify_gen_binary (MULT, mode, temp, XEXP (op1, 0)); } --- gcc/testsuite/gfortran.dg/pr49472.f90.jj 2011-07-04 12:23:12.000000000 +0200 +++ gcc/testsuite/gfortran.dg/pr49472.f90 2011-07-04 12:22:53.000000000 +0200 @@ -0,0 +1,15 @@ +! PR rtl-optimization/49472 +! { dg-do compile } +! { dg-options "-O -fcompare-debug -ffast-math" } +subroutine pr49472 + integer, parameter :: n = 3 + real(8) :: a, b, c, d, e (n+1) + integer :: i + do i=2, (n+1) + b = 1. / ((i - 1.5d0) * 1.) + c = b * a + d = -b * c / (1. + b * b) ** 1.5d0 + e(i) = d + end do + call dummy (e) +end subroutine