diff options
author | Jakub Jelinek <jakub@redhat.com> | 2011-07-04 20:53:56 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2011-07-04 20:53:56 +0200 |
commit | 707f991907e5c97c56a05654fee49f4940158994 (patch) | |
tree | b9c8211932e2c4b13367e217f110ffc882b8f5cf /gcc/simplify-rtx.c | |
parent | 15923c25df505b21061fda148dcb2b036af4735a (diff) | |
download | gcc-707f991907e5c97c56a05654fee49f4940158994.zip gcc-707f991907e5c97c56a05654fee49f4940158994.tar.gz gcc-707f991907e5c97c56a05654fee49f4940158994.tar.bz2 |
re PR rtl-optimization/49472 (Compiler segfault on valid code)
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.
From-SVN: r175821
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 3c4df97..bcd55b27 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -686,13 +686,13 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) 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_code code, enum machine_mode mode, 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)); } |