Jozef Lawrynowicz <joze...@mittosystems.com> writes:
> I experienced the following ICE when working on a downstream patch for msp430:
>
> void
> foo (unsigned int r, unsigned int y)
> {
>   __builtin_umul_overflow ((unsigned int) (-1), y, &r);
> }
>
>> msp430-elf-gcc -S tester.c -O0
>
> tester.c: In function 'foo':
> tester.c:4:1: error: unrecognizable insn:
>     4 | }
>       | ^
> (insn 16 15 17 2 (set (reg:HI 32)
>         (const_int 65535 [0xffff])) "tester.c":3:3 -1
>      (nil))
> during RTL pass: vregs
> dump file: tester.c.234r.vregs
> tester.c:4:1: internal compiler error: in extract_insn, at recog.c:2311
>
> Following discussions on ml/gcc
> (https://gcc.gnu.org/ml/gcc/2019-10/msg00083.html), I narrowed this down to a
> call to expand_mult_highpart_adjust in expand_expr_real_2.
>
> If one of the operands is a constant, its mode had been converted to the wide
> mode of our multiplication to generate some RTL, but not converted back to the
> narrow mode before expanding what will be the high part of the result of the
> multiplication.
>
> If we look at the other two uses of expand_mult_highpart_adjust in the 
> sources,
> (both in expmed.c (expmed_mult_highpart_optab)) we can see that the narrow
> version of the constant is always used:
>       if (tem)
>         /* We used the wrong signedness.  Adjust the result.  */
>         return expand_mult_highpart_adjust (mode, tem, op0, narrow_op1,
>                                             tem, unsignedp);
>
> So the attached patch updates the use in expand_expr_real_2 to also use the
> narrow version of the constant operand.
> This fixes the aforementioned ICE.

TBH, I don't understand why we have:

                  if (TREE_CODE (treeop1) == INTEGER_CST)
                    op1 = convert_modes (mode, word_mode, op1,
                                         TYPE_UNSIGNED (TREE_TYPE (treeop1)));

All the following code treats op1 as having the original mode (word_mode),
and having the same mode as op0.  That's what both the optab and (like you
say) expand_mult_highpart_adjust expect.

So unless I'm missing something, it looks like all the code does is
introduce exactly this bug.

AFAICT from the history, having separate code for INTEGER_CST dates back
to when this was an expand peephole for normal MULT_EXPRs.  In that case
we had to handle two cases: when op1 was a conversion from a narrower type,
and when it was an INTEGER_CST with a suitable range.  The separate
INTEGER_CST case then got carried along in further updates but I think
became redundant when the code was moved to WIDEN_MULT_EXPR.

Removing the above is pre-approved if it works.

Thanks,
Richard

Reply via email to