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

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

https://gcc.gnu.org/g:9c049f4eb807b46397e6f33b0a7fd8a06b5e2e54

commit r15-10584-g9c049f4eb807b46397e6f33b0a7fd8a06b5e2e54
Author: Jakub Jelinek <[email protected]>
Date:   Wed Dec 3 16:07:29 2025 +0100

    switchconv: Fix up inbound checks for switch types wider than sizetype
[PR122943]

    In r14-8302 I've changed switchconv to narrow the CONSTRUCTOR indexes and
    the runtime SSA_NAME indexing into the arrays to at most sizetype for
    types wider than that (__int128, large _BitInt, for -m32 long long too).
    The switchconv partitioning ensures that one partition isn't larger than
    that and having CONSTRUCTOR with _BitInt(1024) indexes was causing all
kinds
    of problems.

    Unfortunately, as the following testcase shows, while doing that is
    desirable, the later gen_inbound_check call uses the lhs of m_arr_ref_first
    statement to determine the type and value that should be compared for the
    inbound check (against the highest possible bound cast to the lhs type).
    So the PR113491 r14-8302 change broke those inbound checks, instead of
    being done in unsigned type corresponding to the precision of the switch
    expression they are now sometimes done using sizetype.  That is of course
    wrong.

    So the following patch fixes it by doing the tidx computation in steps,
    one is the utype subtraction, which has m_arr_ref_first as the last
    instruction, and then if needed there is a cast to sizetype if utype is
    wider than that.  When gen_inbound_check is called, it adds the inbound
    check after the m_arr_ref_first instruction and the additional cast is
    then inside of the guarded block.

    So e.g. in bar for -m32 this patch changes:
     unsigned char bar (long long int val)
     {
       unsigned char result;
    -  sizetype _7;
    +  sizetype _6;
    +  long long unsigned int _7;

       <bb 2> :
    -  _7 = (sizetype) val_3(D);
    +  _7 = (long long unsigned int) val_3(D);
       if (_7 <= 2)
         goto <bb 4>; [INV]
       else
         goto <bb 3>; [INV]

       <bb 3> :
     <L7>:
    -  result_5 = 1;
    +  result_4 = 1;
       goto <bb 5>; [100.00%]

       <bb 4> :
     <L8>:
    -  result_6 = CSWTCH.2[_7];
    +  _6 = (sizetype) _7;
    +  result_5 = CSWTCH.2[_6];

       <bb 5> :
    -  # result_1 = PHI <result_6(4), result_5(3)>
    +  # result_1 = PHI <result_5(4), result_4(3)>
     <L9>:
     <L6>:
       return result_1;

     }

    2025-12-03  Jakub Jelinek  <[email protected]>

            PR tree-optimization/122943
            * tree-switch-conversion.cc (switch_conversion::build_arrays):
            Always gimplify subtraction in utype without cast to tidxtype
            and set m_arr_ref_first to the last stmt of that.  Remove unneeded
            update_stmt call.  If tidxtype is not utype, append after that stmt
            cast to tidxtype and set tidx to the lhs of that cast.

            * gcc.c-torture/execute/pr122943.c: New test.

    (cherry picked from commit 45f3501bdaa4544293e2c391506819c8cff5fcca)

Reply via email to