Hello, I am working with the current distribution of gcc 4.3.3.
The following two transformations are unsafe for (signed) fixed-point numbers. In both cases, a NEG operation is moved to the input of the MULT (say, A). However, if A is -1.0, then NEG A overflows, and the MULT yields the wrong result. Note that if the result of (-1.0 * B) is between -1.0 and +1.0 than the NEG doesn't overflow (1st case); otherwise, it would be a user error (undefined overflow behavior). I didn't find this bug mentioned in the archives. If it has been reported before, please accept my apologies for sending a duplicate report. Best regards, Stefan Freudenberger PS. I don't subscribe to gcc-bugs: please include me in replies. Thank you. $ LC_ALL=C TZ=UTC0 diff -Naur gcc-4.3.3-{ORIG,smf}/gcc/simplify-rtx.c --- gcc-4.3.3-ORIG/gcc/simplify-rtx.c 2008-05-09 17:13:30.000000000 +0000 +++ gcc-4.3.3-smf/gcc/simplify-rtx.c 2009-03-27 09:52:38.712334115 +0000 @@ -542,7 +542,8 @@ /* (neg (mult A B)) becomes (mult (neg A) B). This works even for floating-point values. */ if (GET_CODE (op) == MULT - && !HONOR_SIGN_DEPENDENT_ROUNDING (mode)) + && !HONOR_SIGN_DEPENDENT_ROUNDING (mode) + && !SIGNED_FIXED_POINT_MODE_P (mode)) { temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode); return simplify_gen_binary (MULT, mode, temp, XEXP (op, 1)); @@ -1933,6 +1934,7 @@ /* Canonicalize (minus (neg A) (mult B C)) to (minus (mult (neg B) C) A). */ if (!HONOR_SIGN_DEPENDENT_ROUNDING (mode) + && !SIGNED_FIXED_POINT_MODE_P (mode) && GET_CODE (op1) == MULT && GET_CODE (op0) == NEG) { $