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

Thorsten Otto <ad...@tho-otto.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ad...@tho-otto.de

--- Comment #7 from Thorsten Otto <ad...@tho-otto.de> ---
I ran into a similar problem. The symptom was that code in
tree-switch-conversion was miscompiled:

    if (k == count)
        {
          gcc_checking_assert (count < m_max_case_bit_tests);
          test[k].mask = wi::zero (prec);
          test[k].target_bb = n->m_case_bb;
          test[k].label = n->m_case_label_expr;
          test[k].bits = 0;
          test[k].prob = profile_probability::never ();
          count++;
        }

--- good.s      2024-06-02 13:20:13.453987931 +0200
+++ bad.s       2024-06-02 13:50:03.452881214 +0200
@@ -26976,11 +26976,10 @@
        move.l %d1,-330(%a0)    | prephitmp_336, MEM <struct case_bit_test[3]>
[(struct wide_int_storage *)&test][count_1036].mask.D.16112.len
 | gcc/tree-switch-conversion.cc:1639:          test[k].target_bb =
n->m_case_bb;
        move.l 4(%a3),%d1       | MEM <vector(1) unsigned int> [(void *)n_1051
+ 4B], vect__12.3140
-       lea (-322,%fp),%a4      |,,
-       lea (%a4,%d0.l),%a1     |, vectp.3143
+       lea (%fp,%d0.l),%a1     | tmp12, tmp638, vectp.3143
 | gcc/tree-switch-conversion.cc:1639:          test[k].target_bb =
n->m_case_bb;
        move.l 8(%a3),(%a1)     | MEM <vector(1) unsigned int> [(void *)n_1051
+ 8B], MEM <vector(1) unsigned int> [(void *)vectp.3143_425]
-       move.l %d1,4(%a1)       | vect__12.3140, MEM <vector(1) unsigned int>
[(void *)vectp.3143_425 + 4B]
+       move.l %d1,-318(%a1)    | vect__12.3140, MEM <vector(1) unsigned int>
[(void *)vectp.3143_425 + 4B]
 | gcc/tree-switch-conversion.cc:1641:          test[k].bits = 0;
        clr.l -314(%a0) | test[count_1036].bits
 | gcc/tree-switch-conversion.cc:1642:          test[k].prob =
profile_probability::never ();


Apparently the offset to the local test array was optimized away for the first
store, causing the outer loop to not find the previous m_case_bb pointer, and
then either crash or fail with an assertion because the array overflowed.

Seems like this is not the first regression caused by this "optimization".
Maybe it should be disabled for targets other than riscv, atleast until more
tests have been written.

A crash with such a buggy compiler can be produced with eg.

int date_is_valid(int mon)
{
    switch (mon) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            break;
        default:
            return 0x2400;
    }

    return 0;
}

Reply via email to