Bug 115484 - [13/14/15 regression] if-to-switch prevents AVX vectorization
Summary: [13/14/15 regression] if-to-switch prevents AVX vectorization
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 15.0
: P3 normal
Target Milestone: 15.0
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks: vectorizer 116126
  Show dependency treegraph
 
Reported: 2024-06-14 04:14 UTC by Andi Kleen
Modified: 2024-10-14 06:04 UTC (History)
3 users (show)

See Also:
Host:
Target: x86_64-*-*
Build:
Known to work: 15.0
Known to fail:
Last reconfirmed: 2024-06-14 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andi Kleen 2024-06-14 04:14:07 UTC
With current trunk, but also older gcc

int f(char *s)
{
        int c = 0;
        int i;
        for (i = 0; i < 64; i++) {
                c |=  (*s == ',' || *s == '|' || *s == '!' /* || *s == '*' */);
                s++;
        }
        return c;
}
 
vectorizes with -O3 -mavx2  -fopt-info-optall-all tvcmp.c

tvcmp.c:6:16: optimized: loop vectorized using 16 byte vectors
tvcmp.c:2:5: note: vectorized 1 loops in function.
tvcmp.c:7:10: optimized: loop with 3 iterations completely unrolled (header execution count 16535624)


but when the fourth comparison is commented in it doesn't:

BB 3 is always executed in loop 1
loop 1's coldest_outermost_loop is 1, hotter_than_inner_loop is NULL
tvcmp.c:6:16: missed: couldn't vectorize loop
tvcmp.c:6:16: missed: not vectorized: unsupported control flow in loop.
tvcmp.c:2:5: note: vectorized 0 loops in function.
tvcmp.c:10:9: note: ***** Analysis failed with vector mode V16QI
tvcmp.c:10:9: note: ***** Skipping vector mode V16QI, which would repeat the analysis for V16QI
Comment 1 Richard Biener 2024-06-14 05:51:03 UTC
The issue seems to be that if-to-switch creates a switch () once you get to four 
conditions and switch statements are not handled by the pre-vectorizer if-conversion (or by vectorization natively).
Comment 2 Sam James 2024-06-15 00:54:13 UTC
GCC 8 vectorises it: https://godbolt.org/z/Y8Pvxsh5c.
Comment 3 Sam James 2024-06-15 01:02:35 UTC Comment hidden (obsolete)
Comment 4 Sam James 2024-06-15 01:03:34 UTC
Not only does 8 vectorise it, but so does GCC 11, GCC 12. So, 9/10/13/14/15 are broken.
Comment 5 Andrew Pinski 2024-06-15 01:06:30 UTC
(In reply to Sam James from comment #2)
> GCC 8 vectorises it: https://godbolt.org/z/Y8Pvxsh5c.

The if-to-switch was not until GCC 11: r11-5605-g03eb09292ef228.
What made GCC 9 fail was the conversion from bool to int though:
/app/example.c:2:5: missed:   not vectorized: relevant stmt not supported: patt_29 = (int) patt_30;

But that worked in GCC 8. Though that was fixed in GCC 11.

If you replace `c|=` with:
```
                c |=  (*s == ',' | *s == '|' | *s == '!' | *s == '*');
```

GCC 11+ is able to vectorize it again. But the original testcase fails now due to if-to-switch .
Comment 6 Andi Kleen 2024-06-21 22:42:35 UTC
As an interesting but irrelevant side comment clang seems to have the same bug.
Comment 7 Richard Biener 2024-10-14 06:04:30 UTC
Fixed for GCC 15 by a new feature in vectorizer if-conversion.