Jim Wilson <j...@sifive.com> writes:
> This addresses PR 91860 which has four testcases triggering internal errors.
> The problem here is that in combine when handling debug insns, we are trying
> to substitute
> (sign_extend:DI (const_int 8160 [0x1fe0]))
> as the value for
> (reg:DI 78 [ _9 ])
> in the debug insn
> (debug_insn 29 28 30 2 (var_location:QI d (subreg:QI (reg:DI 78 [ _9 ]) 0)) 
> "tmp4.c":11:5 -1
>      (nil))
>
> The place where this starts to go wrong is in simplify_truncation, where it
> tries to compare the size of the original mode VOIDmode with the subreg mode
> QI and decides that we need to sign extend the constant to convert it from
> VOIDmode to QImode.  We actually need a truncation not a extension here.  Also
> note that the GET_MODE_UNIT_PRECISION (VOIDmode) isn't useful.  We can fix
> this by changing the mode to MAX_MODE_INT, as the CONST_INT should already be
> valid for the largest supported integer mode.  There are already a number of
> other places in simplify-rtx.c that do the same thing.
>
> This was tested with rv32/newlib and rv64/linux cross builds and make checks.
> There were no regressions.  The new tests all fail for rv64 without the patch,
> and work with the patch.

subst tries to avoid creating invalid (zero_extend:DI (const_int N)):

              else if (CONST_SCALAR_INT_P (new_rtx)
                       && (GET_CODE (x) == ZERO_EXTEND
                           || GET_CODE (x) == FLOAT
                           || GET_CODE (x) == UNSIGNED_FLOAT))

Does adding SIGN_EXTEND to the list fix the bug?

I guess SIGN_EXTEND was excluded here (and in a couple of other places
in combine) on the basis that CONST_INTs are naturally sign-extended,
so the substitution doesn't lose information.  But is a SIGN_EXTEND
of a CONST_INT really valid rtl?  I agree with what you said in the PR
that it shouldn't be, for two reasons:

(1) SIGN_EXTENDs operate on distinct source and destination modes
    (unlike binary operations that operate on one mode).  The natural
    way of getting the source mode is GET_MODE (XEXP (x, 0)), and allowing
    CONST_INTs means that potentially any code processing SIGN_EXTENDs
    would need to check for CONST_INTs before using GET_MODE.

(2) we're still finding cases in which CONST_INTs aren't properly
    canonicalised into sign-extended form.  Allowing SIGN_EXTENDs
    of them turns that from being an internal consistency failure
    to a wrong code bug.

There's also the argument that SIGN_EXTEND and ZERO_EXTEND should
be handled consistently.

Thanks,
Richard

Reply via email to