Consider the following code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
class chartolower {
private:
char s[50000];
public:
void populates(int index, int val) { s[index] = val; }
size_t strlen(const char *s) const {
long length = 0;
while (*s != '\0') {
s++;
length++;
}
return length;
}
/*Convert string to lower case: slow*/
void lower1() {
long i;
for (i = 0; i < strlen(s); i++)
if (s[i] >= 'A' && s[i] <= 'Z')
s[i] -= ('A' - 'a'); //Case(1) strlen(s) not optimized away
//i = i; //Case(2) strlen(s) optimized away
//if(s[i] != '\0') s[i] = s[i];//Case(3) strlen(s) not optimized away
//s[i] = s[i]; //Case(4) strlen(s) not optimized away
}
};
int main() {
chartolower s;
for (int i = 0; i < 49999; i++)
s.populates(i, 65);//ASCII for A
s.populates(49999, '\0');
clock_t start_t, end_t, total_t;
start_t = clock();
s.lower1();
end_t = clock();
total_t = (end_t - start_t);
printf("Total time taken by CPU Lower 1: %d\n", total_t);
getchar();
}
On my computer, (Visual Studio 2017, Release Mode Build) the output of the 4 cases are:
Case(1) Total time taken by CPU Lower 1: 3477
Case(2) Total time taken by CPU Lower 1: 0
Case(3) Total time taken by CPU Lower 1: 3445
Case(4) Total time taken by CPU Lower 1: 3455
Case(1), I can understand why strlen(s)
of the line for (i = 0; i < strlen(s); i++)
is not optimized away since s[i]
can be changed. Case(2), it is optimized away since s[i]
for all i
remains unchanged. Case(3) it is not clear to me why the compiler is unable to optimize strlen(s)
away. I would have expected the compiler to figure out that strlen(s)
should compute until it encounters a \0
and this is precisely the condition that is checked in Case(3). Case(4) also does not optimize away and I would have thought that it should be optimized away since it is similar to Case(2).
What causes the optimizations in Case(2) but not the other cases?