https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127848

--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <[email protected]>:

https://gcc.gnu.org/g:08c26561e4fe2cb6a26f5217673ed72c22d33e5b

commit r17-5106-g08c26561e4fe2cb6a26f5217673ed72c22d33e5b
Author: Jakub Jelinek <[email protected]>
Date:   Tue Oct 13 10:47:53 2026 +0200

    tailc: Conservatively punt on some return type mismatches in tail call opt
[PR127848]

    The first testcase is miscompiled on x86_64 and various other
    bitint_ext_undef targets, where the padding bits are unspecified.
    So, if callee returns unsigned _BitInt(15), only low 15 bits are
    specified, when caller returns unsigned short on x86_64, the bits 16-63
    are unspecified, but bit 15 needs to be cleared, so we can't tail
    call.

    Now, tailc for casts currently checks TYPE_MODE differences and for
    the destination doesn't have non-mode precision (that one was added
    because of callee returning unsigned char and caller returning bool,
    those have the same mode but need to emit some code in between the
    call to the callee and return from caller).
    For useless_type_conversion_p we keep the distinction between normal
    INTEGER_TYPEs and BITINT_TYPE_P types with the same precision, because
    at function boundaries the target can have different calling convention.
    We don't really know at GIMPLE if the target returns unsigned _BitInt(16)
    and unsigned short the same way, there could be e.g. differences in padding
    bits etc.
    The following patch is a conservative fix, it punts on
    BITINT_TYPE_P != BITINT_TYPE_P conversions (exactly because we don't
    know if it changes ABI or not), and if both are BITINT_TYPE_P with the
    same TYPE_MODE, does some further checks - if TYPE_SIZE is different
    (and mode the same, that could be just BLKmode) it punts on TYPE_SIZE
    differences, for narrowing or same precision casts it punts except
    for bitint_ext_undef targets (on those the padding bits are unspecified
    and if we have more or same amount of unspecified padding bits it is ok),
    for widening casts it punts on the other side for all but bitint_ext_full
    targets (I'm not motivated enough to bother with figuring out all the
    details for bitint_ext_partial), because on those targets the narrower
    bitint has the bits already extended and if the narrower and wider _BitInt
    type have the same signedness, they are fine (now that I think about it,
    perhaps we could allow even narrower unsigned wider signed, can test
    that incrementally).
    In any case, the patch may pessimize code which would work just fine,
    callee returning unsigned _BitInt(16) and caller unsigned short or vice
    versa on many targets, etc.  But, there can be multiple casts, so if we
    want to improve it, we could e.g. have casts where the callee type is
    compatible with the src_var type and dest type is compatible with the
    caller's type (so have these checks for intermediate calls but allow
    one cast from callee to caller return types), and then somehow deal with it
    during expansion (either in generic code try to expand code which converts
    the callee type temporary to caller type and check (and throw away) a
    sequence emitted by that whether it contains only normal moves and no other
    insns, or make sure every target verifies everything in their target hook).
    I don't have time to do that right now though and it might be too risky
    for backports anyway.

    2026-10-13  Jakub Jelinek  <[email protected]>

            PR middle-end/127848
            * tree-tailcall.cc: Include target.h.
            (process_assignment): Punt if one of dest and src_var types
            is BITINT_TYPE_P and the other is not.  If both are BITINT_TYPE_P,
            punt if TYPE_SIZE is different, or for narrowing or same precision
            conversions on != bitint_ext_undef targets, or for widening
            conversions on != bitint_ext_full targets or if signedness differs.

            * gcc.dg/pr127848-1.c: New test.
            * gcc.dg/pr127848-2.c: New test.
            * gcc.dg/pr127848-3.c: New test.
            * gcc.dg/pr127848-4.c: New test.
            * gcc.dg/pr127848-5.c: New test.

    Reviewed-by: Richard Biener <[email protected]>

Reply via email to