https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103121
--- Comment #31 from Martin Sebor <msebor at gcc dot gnu.org> --- I believe I understand what both of you are saying and (also) that the cache behaves correctly. It stores offsets based on the pointer definition statements. Here's a test that I think reproduces the conditions you describe, along with a dump of the access pass. The cache contents show the offset has the range [0, 3] (negative offsets are invalid and so they were eliminated, as were offsets in excess of 3). Stepping through the pointer_query code shows that the offset cached for the p_6 pointer is derived from the 'p_6 = &a + _1;' statement. (The duplicate pointer_query cache contents (again) dump is a bug that I should fix.) Let me know if I misunderstood something. $ cat x.c && gcc -O2 -S -fdump-tree-waccess3-details=/dev/stdout x.c char a[3]; void g (int i, const void *s, int n) { int j = i + 1; char *p = a + j; if (j == 7) __builtin_memcpy (p, s, n); __builtin_memset (p, 0, 3); } ;; Function g (g, funcdef_no=0, decl_uid=1984, cgraph_uid=1, symbol_order=1) Registering value_relation (j_5 > i_4(D)) (bb2) at j_5 = i_4(D) + 1; pointer_query counters: index cache size: 19 index entries: 2 access cache size: 4 access entries: 2 hits: 1 misses: 2 failures: 0 max_depth: 1 pointer_query cache contents: 6.0[3]: p_6 = &a + [0, 3] (base0); size: 3 9.0[1]: s_9(D) = s_9(D); size: unknown pointer_query cache contents (again): 6.0: p_6 = &a + [0, 3] (base0); size: 3 9.0: s_9(D) = s_9(D); size: unknown void g (int i, const void * s, int n) { char * p; int j; sizetype _1; long unsigned int _2; <bb 2> [local count: 1073741824]: j_5 = i_4(D) + 1; _1 = (sizetype) j_5; p_6 = &a + _1; if (j_5 == 7) goto <bb 3>; [20.24%] else goto <bb 4>; [79.76%] <bb 3> [local count: 217325344]: _2 = (long unsigned int) n_8(D); __builtin_memcpy (p_6, s_9(D), _2); <bb 4> [local count: 1073741824]: __builtin_memset (p_6, 0, 3); [tail call] return; }