On Wed, Jun 12, 2024 at 8:57 AM Hanke Zhang via Gcc <gcc@gcc.gnu.org> 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