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.

Reply via email to