I implemented the following code which converts 32 bytes of input to uppercase:
Version 1:
void to_upper(char* input) {
for (int i = 0; i < 32; ++i) {
input[i] = (input[i] >= 'a' && input[i] <= 'z') ? input[i] - 32 : input[i];
}
}
Version 2:
void to_upper(char* input) {
for (int i = 0; i < 32; ++i) {
if (input[i] >= 'a' && input[i] <= 'z') {
input[i] = input[i] - 32; // same for: input[i] -= 32;
}
}
}
The first version gets autovectorized, the second doesn't. The behaviour is consistent across clang and gcc. Moreover, I implemented both versions in Rust, too, and the Rust compiler does the same, Version 1 autovectorized, Version 2 isn't.
What is limiting the compiler from vectorizing the second version?