On Wed, Jun 12, 2024 at 8:57 AM Hanke Zhang via Gcc <[email protected]> wrote:
>
> Hi,
>
> I'm trying to study "Match and Simplify" recently, and I had this sample code:
>
> int main() {
> int n = 1000;
> int *a = malloc (sizeof(int) * n);
> int *b = malloc (sizeof(int) * n);
> int *c = malloc (sizeof(int) * n);
> for (int i = 0; i < n; i++) {
> if (a[i] & b[i]) {
> a[i] ^= c[i];
> }
> }
> }
>
> But this code cannot be vectorized very well. I hope it can become like this:
>
> int main() {
> int n = 1000;
> int *a = malloc (sizeof(int) * n);
> int *b = malloc (sizeof(int) * n);
> int *c = malloc (sizeof(int) * n);
> for (int i = 0; i < n; i++) {
> int cond = ((a[i] & b[i]) == 1);
> unsigned int mask = cond ? -1 : 0;
> a[i] ^= (c[i] & mask);
> }
> }
>
>
> This can finally result in concise and efficient vectorized
> instructions. But I want to know if this can be achieved through
> "Match and Simplify"? Because when I tried to write the pattern, I
> found that the condtional statement here seemed not to be matched
> well, as there is not an else block.
>
> Or is this not possible with "Match and Simplify"? Is it possible to
> implement it in if-conversion?
It's not possible to perform this transform in match-and-simplify,
if-conversion does this but it considers 'a' to be possibly not
writable and thus the conditional store has to be preserved. It
should use a .MASK_STORE here and I verified it does with
-mavx2. Note your testcase is optimized away as it's full
of dead code.
int foo (int n, int *a, int *b, int *c) {
for (int i = 0; i < n; i++) {
if (a[i] & b[i]) {
a[i] ^= c[i];
}
}
}
is what I tried. I suppose other compilers do not consider
read-only memory mappings? Note there's also store data races
to be considered (but -Ofast might help with that).
In my testcase the c[i] access could also trap, requiring .MASK_LOAD
(I'm quite sure we can't analyze allocated array bounds when the
allocation stmt is seen as in your case).
Richard.
> Thanks
> Hanke Zhang