https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119417
--- Comment #9 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The releases/gcc-14 branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:6c7c25c282642565b23da21cab7e313e78744ab5 commit r14-11472-g6c7c25c282642565b23da21cab7e313e78744ab5 Author: Jakub Jelinek <ja...@redhat.com> Date: Wed Mar 26 14:03:50 2025 +0100 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 <ja...@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. (cherry picked from commit 02132faf4e2fb604758aa86f0b097e6871be595a)