https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96281
Bug ID: 96281 Summary: TBAA does not work as expected for a simple test case Product: gcc Version: 11.0 Status: UNCONFIRMED Keywords: alias Severity: normal Priority: P3 Component: other Assignee: unassigned at gcc dot gnu.org Reporter: felix.yang at huawei dot com Target Milestone: --- Target: aarch64 Test case: foo.c typedef struct state_t { int threadid; } state_t; int history_h[8][12][64]; void history_good (state_t *s) { int i, j; if (s->threadid >= 0 && s->threadid < 8) { for (i = 0; i < 12; i++) { for (j = 0; j < 64; j++) { history_h[s->threadid][i][j] = (history_h[s->threadid][i][j] + 1) >> 1; } } } } $ gcc -S -O2 -ftree-loop-vectorize -funroll-loops foo.c -fopt-info foo.c:14:13: optimized: loop unrolled 6 times When the input parameter s is specified to be unaliased with __restrict__ type qualifier like: void history_good (state_t * __restrict__ s) The inner loop could be auto-vectorized: $ gcc -S -O2 -ftree-loop-vectorize -funroll-loops foo.c -fopt-info foo.c:14:13: optimized: loop vectorized using 16 byte vectors foo.c:8:6: optimized: loop with 15 iterations completely unrolled (header execution count 16535624) Looks like TBAA is not working here for this case. Then I noticed the following logic in tree-ssa-alias.c: 1939 /* When we are trying to disambiguate an access with a pointer dereference 1940 as base versus one with a decl as base we can use both the size 1941 of the decl and its dynamic type for extra disambiguation. 1942 ??? We do not know anything about the dynamic type of the decl 1943 other than that its alias-set contains base2_alias_set as a subset 1944 which does not help us here. */ 1945 /* As we know nothing useful about the dynamic type of the decl just 1946 use the usual conflict check rather than a subset test. 1947 ??? We could introduce -fvery-strict-aliasing when the language 1948 does not allow decls to have a dynamic type that differs from their 1949 static type. Then we can check 1950 !alias_set_subset_of (base1_alias_set, base2_alias_set) instead. */ 1951 if (base1_alias_set != base2_alias_set 1952 && !alias_sets_conflict_p (base1_alias_set, base2_alias_set)) 1953 return false; This was introduced by: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42834 >From the comments, this depends on the language of the source code. So at least for C & C++, could we check !alias_set_subset_of (base1_alias_set, base2_alias_set) instead here? Any other languages supported by GCC that makes a difference?