]> git.ipfire.org Git - thirdparty/gcc.git/commit
widening_mul: Fix up further r14-8680 widening mul issues [PR119417]
authorJakub Jelinek <jakub@redhat.com>
Wed, 26 Mar 2025 13:03:50 +0000 (14:03 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 26 Mar 2025 13:03:50 +0000 (14:03 +0100)
commit02132faf4e2fb604758aa86f0b097e6871be595a
tree9085ecfd13ecf6c5a4d63cddd37b77a89d8bdaf0
parentfb71d7c8e7ce4b061e40cd29cd77a4cfd7a256af
widening_mul: Fix up further r14-8680 widening mul issues [PR119417]

The following testcase is miscompiled since r14-8680 PR113560 changes.
I've already tried to fix some of the issues caused by that change in
r14-8823 PR113759, but apparently didn't get it right.

The problem is that the r14-8680 changes sometimes set *type_out to
a narrower type than the *new_rhs_out actually has (because it will
handle stuff like _1 = rhs1 & 0xffff; and imply from that HImode type_out.

Now, if in convert_mult_to_widen or convert_plusminus_to_widen we actually
get optab for the modes we've asked for (i.e. with from_mode and to_mode),
everything works fine, if the operands don't have the expected types,
they are converted to those (for INTEGER_CSTs with fold_convert,
otherwise with build_and_insert_cast).
On the following testcase on aarch64 that is not the case, we ask
for from_mode HImode and to_mode DImode, but get actual_mode SImode.
The mult_rhs1 operand already has SImode and we change type1 to unsigned int
and so no cast is actually done, except that the & 0xffff is lost that way.

The following patch ensures that if we change typeN because of wider
actual_mode (or because of a sign change), we first cast to the old
typeN (if the r14-8680 code was encountered, otherwise it would have the
same precision) and only then change it, and then perhaps cast again.

On the testcase on aarch64-linux the patch results in the expected
-       add     x19, x19, w0, uxtw 1
+       add     x19, x19, w0, uxth 1
difference.

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

PR tree-optimization/119417
* tree-ssa-math-opts.cc (convert_mult_to_widen): Before changing
typeN because actual_precision/from_unsignedN differs cast rhsN
to typeN if it has a different type.
(convert_plusminus_to_widen): Before changing
typeN because actual_precision/from_unsignedN differs cast mult_rhsN
to typeN if it has a different type.

* gcc.dg/torture/pr119417.c: New test.
gcc/testsuite/gcc.dg/torture/pr119417.c [new file with mode: 0644]
gcc/tree-ssa-math-opts.cc