https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61757
--- Comment #23 from Richard Biener <rguenth at gcc dot gnu.org> ---
The first interesting difference is that for
<bb 14>:
_793 = ASSERT_EXPR <_73, _73 != 18>;
switch (_793) <default: <L32>, case 0: <L26>, case 1: <L27>, case 2: <L28>,
case 3: <L29>, case 4 ... 9: <L28>, case 10 ... 11: <L30>, case 12 ... 17:
<L31>>
<L28>:
we record an equality instead of a range:
@@ -17655,13 +17655,7 @@
BB #19
EDGE 14->19 14 [14.3%] (EXECUTABLE)
- PREDICATE: _73 ge_expr 2
-
- switch (_73) <default: <L32>, case 0: <L26>, case 1: <L27>, case 2:
<L28>, case 3: <L29>, case 4 ... 9: <L28>, case 10 ... 11: <L30>, case 12 ...
17: <L31>>
-
- BB #19
- EDGE 14->19 14 [14.3%] (EXECUTABLE)
- PREDICATE: _73 le_expr 9
+ PREDICATE: _73 eq_expr 2
@@ -19815,9 +19806,8 @@
goto <bb 28>;
<L28>:
- _792 = ASSERT_EXPR <_794, _794 >= 2>;
- _793 = ASSERT_EXPR <_792, _792 <= 9>;
- _77 = _793 + 4294967288;
+ _792 = ASSERT_EXPR <_793, _793 == 2>;
+ _77 = _792 + 4294967288;
_78 = _77 > 1;
_79 = (requirement) _78;
validate_mode (m_780, 2, 0, 1, 1, _79);
that's of course bogus, happens via find_switch_asserts where for correctly
sorted ci vector we fail to pick up CASE_HIGH of cast 4...9.
We miscompile the loop
/* Skip labels until the last of the group. */
do {
++idx;
} while (idx < n && cbb == ci[idx].bb);
to
0x0000000000b6a492 <+3074>: mov %eax,%r14d
0x0000000000b6a495 <+3077>: lea 0x1(%r14),%r15d
=> 0x0000000000b6a499 <+3081>: cmp %r15,%rcx
0x0000000000b6a49c <+3084>: mov %r15,%rax
0x0000000000b6a49f <+3087>: ja 0xb6a492
<find_assert_locations_1(basic_block, sbitmap)+3074>
that is, we simply increment idx until it is equal to n and then use
CASE_HIGH of the last case label in the vector which is the default
label (and thus does not have CASE_HIGH nor CASE_LOW).
The following testcase derived from that is miscompiled on trunk at -O2:
extern void abort (void);
struct X { void *p; int res; } a[32];
int foo (unsigned i, unsigned n, void *q)
{
if (i + 1 < n && q == a[i + 1].p)
{
do {
++i;
} while (i < n && q == a[i].p);
--i;
return a[i].res;
}
}
int main ()
{
int x;
a[0].p = &x;
a[1].p = &x;
a[1].res = 1;
a[2].p = (void *)0;
a[2].res = 0;
if (foo (0, 3, &x) != 1)
abort ();
return 0;
}