https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91146
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The testcase isn't very good, because it is optimized to nothing without the sanitization. But using __attribute__((used)) void f () override { small_vector<int, 20> v; v.insert (v.begin (), 1); __asm volatile ("" : : "r" (&v) : "memory"); } prevents that. With that, the dumps look comparable until fre3. Initially, I thought the issue is that ASAN_MARK ifn isn't said to affect just the pointed memory (and directly only). In reality it affects something different (the shadow memory corresponding to that memory), but perhaps it would work. Unfortunately: --- gcc/internal-fn.def.jj 2020-01-18 13:47:09.517357706 +0100 +++ gcc/internal-fn.def 2020-03-17 16:04:08.092861394 +0100 @@ -309,7 +309,7 @@ DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_ DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL) DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW, "..R..") -DEF_INTERNAL_FN (ASAN_MARK, ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (ASAN_MARK, ECF_LEAF | ECF_NOTHROW, ".W.") DEF_INTERNAL_FN (ASAN_POISON, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL) DEF_INTERNAL_FN (ASAN_POISON_USE, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL) DEF_INTERNAL_FN (ADD_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) doesn't fix it. So, at the start of f without asan we have: v ={v} {CLOBBER}; MEM[(struct &)&v] ={v} {CLOBBER}; MEM[(struct small_vector_base *)&v] ={v} {CLOBBER}; MEM[(struct small_vector_base *)&v].BeginX = &MEM[(struct small_vector_template_common *)&v].FirstEl; MEM[(struct small_vector_base *)&v].EndX = &MEM[(struct small_vector_template_common *)&v].FirstEl; MEM[(struct small_vector_base *)&v].CapacityX = &MEM <union U> [(void *)&v + 104B]; D.48526 = 1; _17 = MEM[(struct small_vector_template_common *)&v].D.48095.EndX; if (&MEM[(struct small_vector_template_common *)&v].FirstEl == _17) where small_vector_template_common is derived from small_vector_base and thus MEM[(struct small_vector_template_common *)&v].D.48095 and MEM[(struct small_vector_base *)&v] is the same thing. Now, with asan we have: .ASAN_MARK (UNPOISON, &v, 104); v ={v} {CLOBBER}; MEM[(struct &)&v] ={v} {CLOBBER}; MEM[(struct small_vector_base *)&v] ={v} {CLOBBER}; MEM[(struct small_vector_base *)&v].BeginX = &MEM[(struct small_vector_template_common *)&v].FirstEl; MEM[(struct small_vector_base *)&v].EndX = &MEM[(struct small_vector_template_common *)&v].FirstEl; MEM[(struct small_vector_base *)&v].CapacityX = &MEM <union U> [(void *)&v + 104B]; .ASAN_MARK (UNPOISON, &D.48886, 4); D.48886 = 1; _10 = MEM[(struct small_vector_template_common *)&v].D.48455.BeginX; _20 = MEM[(struct small_vector_template_common *)&v].D.48455.EndX; if (_10 == _20) The only difference other than .ASAN_MARK calls is that in the asan case _10 hasn't been propagated into the comparison. Anyway, fre3 seems to be able to value number the _17 load to &MEM[(struct small_vector_template_common *)&v].FirstEl and thus optimize the comparison into true, while with the .ASAN_MARK calls it doesn't.