https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127517
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
--- a/gcc/internal-fn.cc 2026-09-16 22:17:08.000000000 +0200
+++ b/gcc/internal-fn.cc 2026-09-23 19:59:09.255514356 +0200
@@ -1764,10 +1764,26 @@ expand_mul_overflow (location_t loc, tre
do_error = gen_label_rtx ();
do_pending_stack_adjust ();
+
+ scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
+ /* If the operand types don't have mode precision, extend them
+ to mode precision. */
+ if (TYPE_PRECISION (TREE_TYPE (arg0)) < GET_MODE_PRECISION (mode))
+ {
+ tree type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
+ uns0_p);
+ arg0 = fold_convert_loc (loc, type, arg0);
+ }
+ if (TYPE_PRECISION (TREE_TYPE (arg1)) < GET_MODE_PRECISION (mode))
+ {
+ tree type = build_nonstandard_integer_type (GET_MODE_PRECISION (mode),
+ uns1_p);
+ arg1 = fold_convert_loc (loc, type, arg1);
+ }
+
op0 = expand_normal (arg0);
op1 = expand_normal (arg1);
- scalar_int_mode mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg0));
bool uns = unsr_p;
if (lhs)
{
@@ -1829,12 +1845,6 @@ expand_mul_overflow (location_t loc, tre
int pos_neg0 = get_range_pos_neg (arg0, currently_expanding_gimple_stmt);
int pos_neg1 = get_range_pos_neg (arg1, currently_expanding_gimple_stmt);
- /* Unsigned types with smaller than mode precision, even if they have most
- significant bit set, are still zero-extended. */
- if (uns0_p && TYPE_PRECISION (TREE_TYPE (arg0)) < GET_MODE_PRECISION (mode))
- pos_neg0 = 1;
- if (uns1_p && TYPE_PRECISION (TREE_TYPE (arg1)) < GET_MODE_PRECISION (mode))
- pos_neg1 = 1;
/* s1 * u2 -> ur */
if (!uns0_p && uns1_p && unsr_p)
fixes this, will see if it doesn't break something else.