Char * comparison with the value set in the previous instruction is not optimized?

While working with some test code, I noticed that in the following code:

extern char* pc; int muysimple() { *pc = 0; if (*pc != 0) { return 1111; } return 4444; } 

the comparison is not optimized by any compiler that I can select on godbolt .

If I change the value of extern char* to extern int* , the comparison will be optimized.

Why do gcc and clang keep the comparison for char , although there is nothing in this code that could legitimately change the value so that the comparison is ever evaluated as true?

Is there anything in the language specification that prohibits this optimization for writing / reading via char* (but allows optimizing for int* !) Or are optimizers more conservative around char?


As mentioned in comets: I don’t see - the right decision - how smoothing rules can come into play here. There is only one variable visible for this code, and multithreading or calling anywhere.

Of course, the (s) aliasing char rules may well be practical reasons why compilers don't optimize this, but the question is whether compilers are allowed optimize this for char* - as well as int* - or they are not allowed to optimize this.

+6
source share
2 answers

although there is nothing in this code that could legitimately change the value so that the comparison is ever evaluated as true?

pc = (char *) &pc; is a valid destination, and since char lvalues ​​can be used to access any type of POD, the destination *pc can change pc .

+6
source

Perhaps char* allowed an alias that anything included volatile memory.

With the -fpermissive flag -fpermissive gcc just displays a warning about char* pointing to volatile memory, but compiles .

Since in your example the pointer is extern , it may use a different translation compiled with this flag, so the pointer points to volatile memory. Therefore, optimization cannot be performed.

I did not find an official link to whether char* aliasing volatile nonvolatile memory is considered legitimate or UB.

EDIT: It appears that the same warning is given for the int* to volatile int* assignment, in which case the compiler does the optimization. Therefore, I assume that warning / enabling flags are not related. The only question is whether char* generally allowed for the volatile alias in general.

Here's an example of smart clearing a volatile struct using C ++ with no warnings only.

EDIT2: It seems that adding the -fno-strict-aliasing flag -fno-strict-aliasing that any type of pointer is not optimized in the source code. Therefore, I think the reason compilers do not optimize when they fear aliases. Or because:

  • Flashing volatile memory allowed (?)
  • Fear of data racing with other pointers to the same non-volatile memory. @alain mentions in his answer that the data races are UB, but even if this is true, I think that the compiler developers decided to be careful here, not optimize.
+1
source

Source: https://habr.com/ru/post/1014035/


All Articles