https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81786
Bug ID: 81786 Summary: local restricted pointer can be relied on in alias analysis Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- I've been looking for opportunities to improve code generation by relying on explicit guarantees about aliasing properties that commonly hold but that GCC cannot otherwise rely on due to the lack of contextual information. For instance, it's common for a function that takes a non-const pointer argument (say Q) to modify the object it points to (say X), then call some other function (say FOO), and then read X's value again via *Q. Unless GCC knows the semantics of FOO it must assume that every call to it changes the value of X, even though it's quite rare in practice for that to happen. It would be nice to be able to express this guarantee to GCC to let it generate more efficient code. As it turns out, according to the C aliasing rules, locally declaring a restrict-qualified pointer P as a copy of an unknown pointer Q (such as a function argument) can be used to express the guarantee that the object X the pointers point to isn't modified during P's lifetime. (This is 6.7.3.1, p4.) So with this simple notation, GCC could rely on this guarantee to optimize the program below as indicated in the comments. Note that neither functions need to make use of the restrict qualifier in its interface. This is helpful because relatively few functions do. $ cat x.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout x.c void foo (void); void bar (int *q) { int* restrict p = q; *p = 123; foo (); // must not modify *P if (*p != 123) // cannot be true __builtin_abort (); // can be eliminated } int x; void baz (void) { x = 789; bar (&x); } ;; Function bar (bar, funcdef_no=0, decl_uid=1817, cgraph_uid=0, symbol_order=0) bar (int * q) { int _1; <bb 2> [100.00%] [count: INV]: *q_2(D) = 123; foo (); _1 = *q_2(D); if (_1 != 123) goto <bb 3>; [0.04%] [count: 0] else goto <bb 4>; [99.96%] [count: INV] <bb 3> [0.04%] [count: 0]: __builtin_abort (); <bb 4> [99.96%] [count: INV]: return; } ;; Function baz (baz, funcdef_no=1, decl_uid=1822, cgraph_uid=1, symbol_order=2) baz () { int _2; <bb 2> [100.00%] [count: INV]: x = 123; foo (); _2 = x; if (_2 != 123) goto <bb 3>; [0.04%] [count: 0] else goto <bb 4>; [99.96%] [count: INV] <bb 3> [0.04%] [count: 0]: __builtin_abort (); <bb 4> [99.96%] [count: INV]: return; }