https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93051
Bug ID: 93051 Summary: Wrong optimizations for pointers: `if (p == q) use p` -> `if (p == q) use q` Product: gcc Version: 10.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: ch3root at openwall dot com Target Milestone: --- The optimizer sometimes changes `if (p == q) use p` to `if (p == q) use q` if it can track the provenance of `q` but not of `p`. This is wrong when the actual provenance of `p` differs from that of `q`. Examples demonstrate the problem in different cases: - with integers and with live pointers (to show that the problem is not in casts to integers); - with past-the-end pointers and without them (to show that even changing the standard to make their comparisons UB will not help); - with two allocations and with only one (to show that it's not related to how memory is allocated by the compiler/libc). Plus, all examples behaves quite well: - respect provenance of pointers including via casts to integers (so this bug is not about (im)possibility to clear provenance by casts to integers or something); - use only one comparison (so the question of its stability is not touched). There is some previous analysis of propagation of conditional equivalences in other bugs, e.g., pr65752#c52, pr61502#c25. Somewhat more general clang bug -- https://bugs.llvm.org/show_bug.cgi?id=44313. Previous lengthy discussion is in https://bugs.llvm.org/show_bug.cgi?id=34548. Example with a past-the-end pointer (the wrong optimization seems to be applied in vrp1): ---------------------------------------------------------------------- #include <stdio.h> __attribute__((noipa,optnone)) // imagine it in a separate TU static void *opaque(void *p) { return p; } int main() { int x[5]; int y[1]; int *p = x; int *q = y + 1; int *r = opaque(p); // hide provenance of p if (r == q) { *p = 1; *r = 2; printf("result: %d\n", *p); } opaque(q); } ---------------------------------------------------------------------- $ gcc -std=c11 -pedantic -Wall -Wextra -Wno-attributes test.c && ./a.out result: 2 $ gcc -std=c11 -pedantic -Wall -Wextra -Wno-attributes -O3 test.c && ./a.out test.c: In function ‘main’: test.c:17:9: warning: array subscript 1 is outside array bounds of ‘int[1]’ [-Warray-bounds] 17 | *r = 2; | ^~ test.c:9:9: note: while referencing ‘y’ 9 | int y[1]; | ^ result: 1 ---------------------------------------------------------------------- gcc x86-64 version: gcc (GCC) 10.0.0 20191223 (experimental) ---------------------------------------------------------------------- The warning nicely illustrates the problem:-) Based on the example from Harald van Dijk in pr61502#c4.