]> git.ipfire.org Git - thirdparty/gcc.git/commit
fold-const: Punt on MULT_EXPR in extract_muldiv MIN/MAX_EXPR case [PR111151]
authorJakub Jelinek <jakub@redhat.com>
Tue, 26 Mar 2024 10:21:38 +0000 (11:21 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 26 Mar 2024 10:21:38 +0000 (11:21 +0100)
commitc4f2c84e8fa369856aee76679590eb613724bfb0
tree204173b5933e8f950953edc8a9ca2c0478beb72d
parent471967ab8b4c49338ba77defbe24b06cc51c0093
fold-const: Punt on MULT_EXPR in extract_muldiv MIN/MAX_EXPR case [PR111151]

As I've tried to explain in the comments, the extract_muldiv_1
MIN/MAX_EXPR optimization is wrong for code == MULT_EXPR.
If the multiplication is done in unsigned type or in signed
type with -fwrapv, it is fairly obvious that max (a, b) * c
in many cases isn't equivalent to max (a * c, b * c) (or min if c is
negative) due to overflows, but even for signed with undefined overflow,
the optimization could turn something without UB in it (where
say a * c invokes UB, but max (or min) picks the other operand where
b * c doesn't).
As for division/modulo, I think it is in most cases safe, except if
the problematic INT_MIN / -1 case could be triggered, but we can
just punt for MAX_EXPR because for MIN_EXPR if one operand is INT_MIN,
we'd pick that operand already.  It is just for completeness, match.pd
already has an optimization which turns x / -1 into -x, so the division
by zero is mostly theoretical.  That is also why in the testcase the
i case isn't actually miscompiled without the patch, while the c and f
cases are.

2024-03-26  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/111151
* fold-const.cc (extract_muldiv_1) <case MAX_EXPR>: Punt for
MULT_EXPR altogether, or for MAX_EXPR if c is -1.

* gcc.c-torture/execute/pr111151.c: New test.
gcc/fold-const.cc
gcc/testsuite/gcc.c-torture/execute/pr111151.c [new file with mode: 0644]