Patchwork Move Asan instrumentation to sanopt pass

login
register
mail settings
Submitter Yury Gribov
Date July 18, 2014, 1:36 p.m.
Message ID <53C922DE.6020000@samsung.com>
Download mbox | patch
Permalink /patch/371541/
State New
Headers show

Comments

Yury Gribov - July 18, 2014, 1:36 p.m.
Hi all,

Attached patch delays generation of Asan memory checking code
until sanopt pass. This is a first step towards global static analysis
of Asan instrumentation which would allow to
* remove redundant instrumentations
* aggregate adjacent Asan checks
* move invariant checks from loops

The patch also changes the logic behind 
asan-instrumentation-with-call-threshold
parameter to more closely match LLVM.

The patch splits build_check_stmt routine to two parts. The first one
(called from asan0/asan passes) inserts calls to internal functions
ASAN_LOAD and ASAN_STORE. The second expands those to inline checks
(in asan_expand_check_ifn).

Here are some obvious disadvantages:
* passing additional info via hidden parameter of
ASAN_{LOAD,STORE} is ugly but I'm not sure how to do this better
* delayed expansion runs after all optimization passes
so inlined Asan checks will not get a chance to be
CSE-ed, etc.; this may probably be solved by moving sanopt earlier
in the pipeline. BTW I haven't experienced notable slowdowns in my 
experiments.
* passing program pointers to ASAN_{LOAD,STORE} may damage alias analysis
because all pointers will now escape; I probably could
provide fnspec with (EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE) or
even EAF_UNUSED for these functions but this does not seem
to be supported in current middle-end.

The patch was bootstrapped, regtested and asan-bootstrapped on x64.

Is this ok for trunk?

-Yury
Jakub Jelinek - July 18, 2014, 2:46 p.m.
On Fri, Jul 18, 2014 at 05:36:30PM +0400, Yury Gribov wrote:
> The patch was bootstrapped, regtested and asan-bootstrapped on x64.

Thanks for working on this.

For formatting, can you please just replace 8 spaces with tabs
in the ^+ lines in the patch?
sed '/^+/s/        /\t/g' or so.
Can you avoid using // comments in code that uses /* */ comments?

If all the ifns have a bitmask argument, one question is if we really
want ASAN_LOAD vs. ASAN_STORE, instead of a single ASAN_CHECK that
would actually have ASAN_CHECK_IS_STORE as one of the flags.

>  pass_sanopt::execute (function *fun)
>  {
>    basic_block bb;
> +  gimple_stmt_iterator gsi;
>  
> +  int asan_num_accesses = 0;

IMHO you should guard this with if (flag_sanitize & SANITIZE_ADDRESS),
to avoid the cost for -fsanitize=undefined, thread etc.

> +  FOR_EACH_BB_FN (bb, fun)
> +    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> +      {
> + 	gimple stmt = gsi_stmt (gsi);
> +	if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
> +	  {
> +	    enum internal_fn ifn = gimple_call_internal_fn (stmt);
> +	    switch (ifn)
> +	      {
> +	      case IFN_ASAN_LOAD:
> +	      case IFN_ASAN_STORE:
> +		{
> +		  ++asan_num_accesses;
> +		  break;
> +		}
> +	      default:
> +		break;
> +	      }
> +	    }
> +        }
> +
> +  bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX
> +    && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD;
> +    

> --- a/gcc/gimple-iterator.h
> +++ b/gcc/gimple-iterator.h
> @@ -116,6 +116,7 @@ gsi_start_bb (basic_block bb)
>    gimple_seq *seq;
>  
>    seq = bb_seq_addr (bb);
> +  gcc_assert (seq);
>    i.ptr = gimple_seq_first (*seq);
>    i.seq = seq;
>    i.bb = bb;

Uh.  Can you please explain this?  That sounds weird.

	Jakub
Richard Guenther - July 22, 2014, 1:57 p.m.
On Fri, Jul 18, 2014 at 3:36 PM, Yury Gribov <y.gribov@samsung.com> wrote:
> Hi all,
>
> Attached patch delays generation of Asan memory checking code
> until sanopt pass. This is a first step towards global static analysis
> of Asan instrumentation which would allow to
> * remove redundant instrumentations
> * aggregate adjacent Asan checks
> * move invariant checks from loops
>
> The patch also changes the logic behind
> asan-instrumentation-with-call-threshold
> parameter to more closely match LLVM.
>
> The patch splits build_check_stmt routine to two parts. The first one
> (called from asan0/asan passes) inserts calls to internal functions
> ASAN_LOAD and ASAN_STORE. The second expands those to inline checks
> (in asan_expand_check_ifn).
>
> Here are some obvious disadvantages:
> * passing additional info via hidden parameter of
> ASAN_{LOAD,STORE} is ugly but I'm not sure how to do this better
> * delayed expansion runs after all optimization passes
> so inlined Asan checks will not get a chance to be
> CSE-ed, etc.; this may probably be solved by moving sanopt earlier
> in the pipeline. BTW I haven't experienced notable slowdowns in my
> experiments.
> * passing program pointers to ASAN_{LOAD,STORE} may damage alias analysis
> because all pointers will now escape;

Ugh.

> I probably could
> provide fnspec with (EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE) or
> even EAF_UNUSED for these functions but this does not seem
> to be supported in current middle-end.

Simply add the "fn spec" attribute to the functions?

Richard.

> The patch was bootstrapped, regtested and asan-bootstrapped on x64.
>
> Is this ok for trunk?
>
> -Yury
Yury Gribov - July 22, 2014, 2:15 p.m.
On 07/22/2014 05:57 PM, Richard Biener wrote:
>> I probably could
>> provide fnspec with (EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE) or
>> even EAF_UNUSED for these functions but this does not seem
>> to be supported in current middle-end.
>
> Simply add the "fn spec" attribute to the functions?

Problem is that internal functions don't seem to support this
(gimple_statement_call::fntype and gimple_statement_call::internal_fn
occupy the same field). I wasn't sure about the reasons for this
so decided change them in original patch. Do you think we should we allow
fntype for internal functions?

-Y
Richard Guenther - July 22, 2014, 2:20 p.m.
On Tue, Jul 22, 2014 at 4:15 PM, Yury Gribov <y.gribov@samsung.com> wrote:
> On 07/22/2014 05:57 PM, Richard Biener wrote:
>>>
>>> I probably could
>>> provide fnspec with (EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE) or
>>> even EAF_UNUSED for these functions but this does not seem
>>> to be supported in current middle-end.
>>
>>
>> Simply add the "fn spec" attribute to the functions?
>
>
> Problem is that internal functions don't seem to support this
> (gimple_statement_call::fntype and gimple_statement_call::internal_fn
> occupy the same field). I wasn't sure about the reasons for this
> so decided change them in original patch. Do you think we should we allow
> fntype for internal functions?

Ah.... internal fns.  Those cannot have attributes indeed (technical
limitation).
Martin was working on putting those flags elsewhere (cgraph, though internal
functions don't have cgraph nodes either ...).  Maybe it was a bad idea to use
internal functions for ASAN.

Richard.

> -Y
Jakub Jelinek - July 23, 2014, 8:09 p.m.
On Tue, Jul 22, 2014 at 04:20:04PM +0200, Richard Biener wrote:
> On Tue, Jul 22, 2014 at 4:15 PM, Yury Gribov <y.gribov@samsung.com> wrote:
> > On 07/22/2014 05:57 PM, Richard Biener wrote:
> >>>
> >>> I probably could
> >>> provide fnspec with (EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE) or
> >>> even EAF_UNUSED for these functions but this does not seem
> >>> to be supported in current middle-end.
> >>
> >>
> >> Simply add the "fn spec" attribute to the functions?
> >
> >
> > Problem is that internal functions don't seem to support this
> > (gimple_statement_call::fntype and gimple_statement_call::internal_fn
> > occupy the same field). I wasn't sure about the reasons for this
> > so decided change them in original patch. Do you think we should we allow
> > fntype for internal functions?
> 
> Ah.... internal fns.  Those cannot have attributes indeed (technical
> limitation).
> Martin was working on putting those flags elsewhere (cgraph, though internal
> functions don't have cgraph nodes either ...).  Maybe it was a bad idea to use
> internal functions for ASAN.

But if it is a builtin function, then users can use it directly, which is
not really desirable.
For internal-fn, we already support ECF* constants, guess either we could
add support for EAF* too, through internal-fn.def, or we need support for
normal builtins that are inaccessible to users (but using . or space
in names is too ugly IMHO for that).

	Jakub
Yury Gribov - July 24, 2014, 6:21 a.m.
On 07/24/2014 12:09 AM, Jakub Jelinek wrote:
>> Ah.... internal fns.  Those cannot have attributes indeed (technical
>> limitation).
>> Martin was working on putting those flags elsewhere (cgraph, though internal
>> functions don't have cgraph nodes either ...).  Maybe it was a bad idea to use
>> internal functions for ASAN.
>
> For internal-fn, we already support ECF* constants, guess either we could
> add support for EAF* too, through internal-fn.def,

Just hack in EAFs or support full-featured declarations in internals?
The latter looks more appropriate but would increase size of
internal function calls by one word (namely 
gimple_statement_call::internal_fn).

> or we need support for
> normal builtins that are inaccessible to users (but using . or space
> in names is too ugly IMHO for that).

We could be just another flag in DEF_BUILTIN.
Although my understanding was that we already have
user-inaccessible builtins and these are internal functions.

-Y
Jakub Jelinek - July 24, 2014, 7:48 a.m.
On Thu, Jul 24, 2014 at 10:21:14AM +0400, Yury Gribov wrote:
> On 07/24/2014 12:09 AM, Jakub Jelinek wrote:
> >>Ah.... internal fns.  Those cannot have attributes indeed (technical
> >>limitation).
> >>Martin was working on putting those flags elsewhere (cgraph, though internal
> >>functions don't have cgraph nodes either ...).  Maybe it was a bad idea to use
> >>internal functions for ASAN.
> >
> >For internal-fn, we already support ECF* constants, guess either we could
> >add support for EAF* too, through internal-fn.def,
> 
> Just hack in EAFs or support full-featured declarations in internals?
> The latter looks more appropriate but would increase size of
> internal function calls by one word (namely
> gimple_statement_call::internal_fn).

Internal functions have internal-fn-id instead of a declaration, the whole
point of them is that they don't have function types etc. and it solely
about the types used for arguments and return value in the IL.
So, either support for just EAF*, or perhaps support for DECL_ATTRIBUTES
for internal-fns, say by having some tree array where you'd store what you
stick into DECL_ATTRIBUTES normally.

	Jakub

Patch

commit ec53fb00ab4a762c3c4cefa886f6cd9ee549de8d
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Thu Jul 17 09:45:26 2014 +0400

    Move inlining of Asan memory checks to sanopt pass.
    Change asan-instrumentation-with-call-threshold to more closely match LLVM.
    
    gcc/
    
    2014-07-17  Yury Gribov  <y.gribov@samsung.com>
    
    	* asan.c (asan_check_flags): New enum.
    	(build_check_stmt_with_calls): Removed function.
    	(build_check_stmt): Split inlining logic to
    	asan_expand_check_ifn.
    	(instrument_derefs): Rename parameter.
    	(instrument_mem_region_access): Rename parameter.
    	(instrument_strlen_call): Likewise.
    	(asan_expand_check_ifn): New function.
    	(asan_instrument): Remove old code.
    	(pass_sanopt::execute): Change handling of
    	asan-instrumentation-with-call-threshold.
    	* doc/invoke.texi (asan-instrumentation-with-call-threshold):
    	Update description.
    	* gimple_iterator.h (gsi_start_bb): Fix uninitialized
    	warnings.
    	* internal-fn.c (expand_ASAN_LOAD): New function.
    	(expand_ASAN_STORE): Likewise.
    	* internal-fn.def (ASAN_LOAD): New internal function.
    	(ASAN_STORE): Likewise.
    	* params.def (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD):
    	Update description.
    	(PARAM_ASAN_USE_AFTER_RETURN): Likewise.
    
    gcc/testsuite/
    
    2014-07-17  Yury Gribov  <y.gribov@samsung.com>
    
    	* c-c++-common/asan/inc.c: Update test.
    	* c-c++-common/asan/instrument-with-calls-2.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-1.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-2.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-3.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-4.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-5.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-6.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-7.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-8.c: Likewise.
    	* c-c++-common/asan/no-redundant-instrumentation-9.c: Likewise.

diff --git a/gcc/asan.c b/gcc/asan.c
index 0d78634..7fe079d 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -243,18 +243,15 @@  static GTY(()) tree shadow_ptr_types[2];
 /* Decl for __asan_option_detect_stack_use_after_return.  */
 static GTY(()) tree asan_detect_stack_use_after_return;
 
-/* Number of instrumentations in current function so far.  */
-
-static int asan_num_accesses;
-
-/* Check whether we should replace inline instrumentation with calls.  */
-
-static inline bool
-use_calls_p ()
+/* Various flags for Asan builtins.  */
+enum asan_check_flags
 {
-  return ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX
-    && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD;
-}
+  ASAN_CHECK_NON_ZERO_LEN = 1 << 0,
+  ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
+  ASAN_CHECK_START_INSTRUMENTED = 1 << 2,
+  ASAN_CHECK_END_INSTRUMENTED = 1 << 3,
+  ASAN_CHECK_LAST
+};
 
 /* Hashtable support for memory references used by gimple
    statements.  */
@@ -1553,55 +1550,6 @@  maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter,
   return gimple_assign_lhs (g);
 }
 
-/* Instrument the memory access instruction using callbacks.
-   Parameters are similar to BUILD_CHECK_STMT.  */
-
-static void
-build_check_stmt_with_calls (location_t loc, tree base, tree len,
-			     HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter,
-			     bool before_p, bool is_store, bool is_scalar_access)
-{
-  gimple_stmt_iterator gsi = *iter;
-  tree base_ssa = maybe_create_ssa_name (loc, base, &gsi, before_p);
-
-  gimple g
-    = gimple_build_assign_with_ops (NOP_EXPR,
-				    make_ssa_name (pointer_sized_int_node, NULL),
-				    base_ssa, NULL_TREE);
-  gimple_set_location (g, loc);
-  if (before_p)
-    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
-  else
-    gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-  tree base_addr = gimple_assign_lhs (g);
-
-  int nargs;
-  tree fun
-    = check_func (is_store, is_scalar_access ? size_in_bytes : -1, &nargs);
-  if (nargs == 1)
-    g = gimple_build_call (fun, 1, base_addr);
-  else
-    {
-      gcc_assert (nargs == 2);
-      g = gimple_build_assign_with_ops (NOP_EXPR,
-					make_ssa_name (pointer_sized_int_node,
-						       NULL),
-					len, NULL_TREE);
-      gimple_set_location (g, loc);
-      gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-      tree sz_arg = gimple_assign_lhs (g);
-      g = gimple_build_call (fun, nargs, base_addr, sz_arg);
-    }
-  gimple_set_location (g, loc);
-  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
-  if (!before_p)
-    {
-      gsi_next (&gsi);
-      *iter = gsi;
-    }
-}
-
 /* Instrument the memory access instruction BASE.  Insert new
    statements before or after ITER.
 
@@ -1622,27 +1570,30 @@  build_check_stmt_with_calls (location_t loc, tree base, tree len,
    otherwise, it points to the statement logically following it.  */
 
 static void
-build_check_stmt (location_t location, tree base, tree len,
+build_check_stmt (location_t loc, tree base, tree len,
 		  HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter,
-		  bool non_zero_len_p, bool before_p, bool is_store,
+		  bool is_non_zero_len, bool before_p, bool is_store,
 		  bool is_scalar_access, unsigned int align = 0,
 		  bool start_instrumented = false,
 		  bool end_instrumented = false)
 {
   gimple_stmt_iterator gsi = *iter;
   gimple g;
-  tree uintptr_type
-    = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1);
 
-  gcc_assert (!(size_in_bytes > 0 && !non_zero_len_p));
+  gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len));
 
   if (start_instrumented && end_instrumented)
     {
       if (!before_p)
-        gsi_next (iter);
+	gsi_next (iter);
       return;
     }
 
+  gsi = *iter;
+
+  base = unshare_expr (base);
+  base = maybe_create_ssa_name (loc, base, &gsi, before_p);
+
   if (len)
     len = unshare_expr (len);
   else
@@ -1654,9 +1605,8 @@  build_check_stmt (location_t location, tree base, tree len,
   if (size_in_bytes > 1)
     {
       if ((size_in_bytes & (size_in_bytes - 1)) != 0
-	  || !is_scalar_access
 	  || size_in_bytes > 16)
-	size_in_bytes = -1;
+	is_scalar_access = false;
       else if (align && align < size_in_bytes * BITS_PER_UNIT)
 	{
 	  /* On non-strict alignment targets, if
@@ -1667,189 +1617,33 @@  build_check_stmt (location_t location, tree base, tree len,
 	  if (size_in_bytes != 16
 	      || STRICT_ALIGNMENT
 	      || align < 8 * BITS_PER_UNIT)
-	    size_in_bytes = -1;
-	}
-    }
-
-  HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
-
-  tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
-  tree shadow_type = TREE_TYPE (shadow_ptr_type);
-
-  base = unshare_expr (base);
-
-  if (use_calls_p ())
-    {
-      gsi = *iter;
-      build_check_stmt_with_calls (location, base, len, size_in_bytes, iter,
-				   before_p, is_store, is_scalar_access);
-      return;
-    }
-
-  ++asan_num_accesses;
-
-  if (!non_zero_len_p)
-    {
-      gcc_assert (before_p);
-
-      /* So, the length of the memory area to asan-protect is
-	 non-constant.  Let's guard the generated instrumentation code
-	 like:
-
-	 if (len != 0)
-	   {
-	     //asan instrumentation code goes here.
-	   }
-	 // falltrough instructions, starting with *ITER.  */
-
-      g = gimple_build_cond (NE_EXPR,
-			     len,
-			     build_int_cst (TREE_TYPE (len), 0),
-			     NULL_TREE, NULL_TREE);
-      gimple_set_location (g, location);
-
-      basic_block then_bb, fallthrough_bb;
-      insert_if_then_before_iter (g, iter, /*then_more_likely_p=*/true,
-				  &then_bb, &fallthrough_bb);
-      /* Note that fallthrough_bb starts with the statement that was
-	 pointed to by ITER.  */
-
-      /* The 'then block' of the 'if (len != 0) condition is where
-	 we'll generate the asan instrumentation code now.  */
-      gsi = gsi_last_bb (then_bb);
-      build_check_stmt (location, base, len, size_in_bytes, &gsi,
-			/*non_zero_len_p*/true, /*before_p*/true, is_store,
-			is_scalar_access, align,
-			start_instrumented, end_instrumented);
-      return;
-    }
-
-  /* Get an iterator on the point where we can add the condition
-     statement for the instrumentation.  */
-  basic_block then_bb, else_bb;
-  gsi = create_cond_insert_point (&gsi, before_p,
-				  /*then_more_likely_p=*/false,
-				  /*create_then_fallthru_edge=*/false,
-				  &then_bb,
-				  &else_bb);
-
-  tree base_ssa = maybe_create_ssa_name (location, base, &gsi,
-					 /*before_p*/false);
-
-  g = gimple_build_assign_with_ops (NOP_EXPR,
-				    make_ssa_name (uintptr_type, NULL),
-				    base_ssa, NULL_TREE);
-  gimple_set_location (g, location);
-  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-  tree base_addr = gimple_assign_lhs (g);
-
-  tree t = NULL_TREE;
-  if (real_size_in_bytes >= 8)
-    {
-      tree shadow = build_shadow_mem_access (&gsi, location, base_addr,
-					     shadow_ptr_type);
-      t = shadow;
-    }
-  else
-    {
-      /* Slow path for 1, 2 and 4 byte accesses.  */
-
-      if (!start_instrumented)
-	{
-	  /* Test (shadow != 0)
-		  & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow).  */
-	  tree shadow = build_shadow_mem_access (&gsi, location, base_addr,
-						 shadow_ptr_type);
-	  gimple shadow_test = build_assign (NE_EXPR, shadow, 0);
-	  gimple_seq seq = NULL;
-	  gimple_seq_add_stmt (&seq, shadow_test);
-	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7));
-	  gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
-						      gimple_seq_last (seq)));
-	  if (real_size_in_bytes > 1)
-	    gimple_seq_add_stmt (&seq,
-				 build_assign (PLUS_EXPR, gimple_seq_last (seq),
-					       real_size_in_bytes - 1));
-	  gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
-						   gimple_seq_last (seq),
-						   shadow));
-	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
-						   gimple_seq_last (seq)));
-	  t = gimple_assign_lhs (gimple_seq_last (seq));
-	  gimple_seq_set_location (seq, location);
-	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
-	}
-
-      /* For non-constant, misaligned or otherwise weird access sizes,
-	 check first and last byte.  */
-      if (size_in_bytes == -1 && !end_instrumented)
-	{
-	  g = gimple_build_assign_with_ops (MINUS_EXPR,
-					    make_ssa_name (uintptr_type, NULL),
-					    len,
-					    build_int_cst (uintptr_type, 1));
-	  gimple_set_location (g, location);
-	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-	  tree last = gimple_assign_lhs (g);
-	  g = gimple_build_assign_with_ops (PLUS_EXPR,
-					    make_ssa_name (uintptr_type, NULL),
-					    base_addr,
-					    last);
-	  gimple_set_location (g, location);
-	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-	  tree base_end_addr = gimple_assign_lhs (g);
-
-	  tree shadow = build_shadow_mem_access (&gsi, location, base_end_addr,
-						 shadow_ptr_type);
-	  gimple shadow_test = build_assign (NE_EXPR, shadow, 0);
-	  gimple_seq seq = NULL;
-	  gimple_seq_add_stmt (&seq, shadow_test);
-	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
-						   base_end_addr, 7));
-	  gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
-						      gimple_seq_last (seq)));
-	  gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
-						   gimple_seq_last (seq),
-						   shadow));
-	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
-						   gimple_seq_last (seq)));
-	  if (!start_instrumented)
-	    gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
-						     gimple_seq_last (seq)));
-	  t = gimple_assign_lhs (gimple_seq_last (seq));
-	  gimple_seq_set_location (seq, location);
-	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+	    is_scalar_access = false;
 	}
     }
 
-  g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0),
-			 NULL_TREE, NULL_TREE);
-  gimple_set_location (g, location);
-  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
-  /* Generate call to the run-time library (e.g. __asan_report_load8).  */
-  gsi = gsi_start_bb (then_bb);
-  int nargs;
-  tree fun = report_error_func (is_store, is_scalar_access ? size_in_bytes : -1,
-				&nargs);
-  if (nargs == 1)
-      g = gimple_build_call (fun, 1, base_addr);
+  HOST_WIDE_INT flags = 0;
+  if (is_non_zero_len)
+    flags |= ASAN_CHECK_NON_ZERO_LEN;
+  if (is_scalar_access)
+    flags |= ASAN_CHECK_SCALAR_ACCESS;
+  if (start_instrumented)
+    flags |= ASAN_CHECK_START_INSTRUMENTED;
+  if (end_instrumented)
+    flags |= ASAN_CHECK_END_INSTRUMENTED;
+
+  g = gimple_build_call_internal (is_store ? IFN_ASAN_STORE : IFN_ASAN_LOAD,
+				  3,
+				  build_int_cst (integer_type_node, flags),
+				  base, len);
+  gimple_set_location (g, loc);
+  if (before_p)
+    gsi_insert_before (&gsi, g, GSI_SAME_STMT);
   else
     {
-      gcc_assert (nargs == 2);
-      g = gimple_build_assign_with_ops (NOP_EXPR,
-					make_ssa_name (pointer_sized_int_node,
-						       NULL),
-					len, NULL_TREE);
-      gimple_set_location (g, location);
       gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-      tree sz_arg = gimple_assign_lhs (g);
-      g = gimple_build_call (fun, nargs, base_addr, sz_arg);
+      gsi_next (&gsi);
+      *iter = gsi;
     }
-  gimple_set_location (g, location);
-  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
-  *iter = gsi_start_bb (else_bb);
 }
 
 /* If T represents a memory access, add instrumentation code before ITER.
@@ -1942,7 +1736,7 @@  instrument_derefs (gimple_stmt_iterator *iter, tree t,
     {
       unsigned int align = get_object_alignment (t);
       build_check_stmt (location, base, NULL_TREE, size_in_bytes, iter,
-			/*non_zero_len_p*/size_in_bytes > 0, /*before_p=*/true,
+			/*is_non_zero_len*/size_in_bytes > 0, /*before_p=*/true,
 			is_store, /*is_scalar_access*/true, align);
       update_mem_ref_hash_table (base, size_in_bytes);
       update_mem_ref_hash_table (t, size_in_bytes);
@@ -1980,7 +1774,7 @@  instrument_mem_region_access (tree base, tree len,
   HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
 
   build_check_stmt (location, base, len, size_in_bytes, iter,
-		    /*non_zero_len_p*/size_in_bytes > 0, /*before_p*/true,
+		    /*is_non_zero_len*/size_in_bytes > 0, /*before_p*/true,
 		    is_store, /*is_scalar_access*/false, /*align*/0,
 		    start_instrumented, end_instrumented);
 
@@ -2028,6 +1822,7 @@  instrument_strlen_call (gimple_stmt_iterator *iter)
   tree str_arg = gimple_call_arg (call, 0);
   bool start_instrumented = has_mem_ref_been_instrumented (str_arg, 1);
 
+  // TODO: remove this?
   tree cptr_type = build_pointer_type (char_type_node);
   gimple str_arg_ssa =
     gimple_build_assign_with_ops (NOP_EXPR,
@@ -2037,7 +1832,7 @@  instrument_strlen_call (gimple_stmt_iterator *iter)
   gsi_insert_before (iter, str_arg_ssa, GSI_SAME_STMT);
 
   build_check_stmt (loc, gimple_assign_lhs (str_arg_ssa), NULL_TREE, 1, iter,
-		    /*non_zero_len_p*/true, /*before_p=*/true,
+		    /*is_non_zero_len*/true, /*before_p=*/true,
 		    /*is_store=*/false, /*is_scalar_access*/true, /*align*/0,
 		    start_instrumented, start_instrumented);
 
@@ -2050,7 +1845,7 @@  instrument_strlen_call (gimple_stmt_iterator *iter)
   gsi_insert_after (iter, g, GSI_NEW_STMT);
 
   build_check_stmt (loc, gimple_assign_lhs (g), NULL_TREE, 1, iter,
-		    /*non_zero_len_p*/true, /*before_p=*/false,
+		    /*is_non_zero_len*/true, /*before_p=*/false,
 		    /*is_store=*/false, /*is_scalar_access*/true, /*align*/0);
 
   return true;
@@ -2617,6 +2412,214 @@  asan_finish_file (void)
   flag_sanitize |= SANITIZE_ADDRESS;
 }
 
+/* Expand the ASAN_{LOAD,STORE} builtins.  */
+
+static void
+asan_expand_check_ifn (gimple_stmt_iterator *iter, bool is_store,
+		       bool use_calls)
+{
+  gimple g = gsi_stmt (*iter);
+  location_t loc = gimple_location (g);
+
+  HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
+  gcc_assert (flags < ASAN_CHECK_LAST);
+  bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
+
+  tree base = gimple_call_arg (g, 1);
+  tree len = gimple_call_arg (g, 2);
+
+  HOST_WIDE_INT size_in_bytes
+    = is_scalar_access && tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
+
+  if (use_calls)
+    {
+      /* Instrument using callbacks.  */
+      gimple g
+        = gimple_build_assign_with_ops (NOP_EXPR,
+				        make_ssa_name (pointer_sized_int_node,
+                                        NULL),
+				        base, NULL_TREE);
+      gimple_set_location (g, loc);
+      gsi_insert_before (iter, g, GSI_SAME_STMT);
+      tree base_addr = gimple_assign_lhs (g);
+
+      int nargs;
+      tree fun = check_func (is_store, size_in_bytes, &nargs);
+      if (nargs == 1)
+        g = gimple_build_call (fun, 1, base_addr);
+      else
+        {
+          gcc_assert (nargs == 2);
+          g = gimple_build_assign_with_ops (NOP_EXPR,
+					    make_ssa_name (pointer_sized_int_node,
+						           NULL),
+					    len, NULL_TREE);
+          gimple_set_location (g, loc);
+          gsi_insert_before (iter, g, GSI_SAME_STMT);
+          tree sz_arg = gimple_assign_lhs (g);
+          g = gimple_build_call (fun, nargs, base_addr, sz_arg);
+        }
+      gimple_set_location (g, loc);
+      gsi_replace (iter, g, false);
+      return;
+    }
+
+  bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
+  bool start_instrumented = (flags & ASAN_CHECK_START_INSTRUMENTED) != 0;
+  bool end_instrumented = (flags & ASAN_CHECK_END_INSTRUMENTED) != 0;
+
+  HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
+
+  tree uintptr_type
+    = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1);
+
+  tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
+  tree shadow_type = TREE_TYPE (shadow_ptr_type);
+
+  gimple_stmt_iterator gsi = *iter;
+
+  if (!is_non_zero_len)
+    {
+      /* So, the length of the memory area to asan-protect is
+	 non-constant.  Let's guard the generated instrumentation code
+	 like:
+
+	 if (len != 0)
+	   {
+	     //asan instrumentation code goes here.
+	   }
+	 // falltrough instructions, starting with *ITER.  */
+
+      g = gimple_build_cond (NE_EXPR,
+			    len,
+			    build_int_cst (TREE_TYPE (len), 0),
+			    NULL_TREE, NULL_TREE);
+      gimple_set_location (g, loc);
+
+      basic_block then_bb, fallthrough_bb;
+      insert_if_then_before_iter (g, iter, /*then_more_likely_p=*/true,
+				 &then_bb, &fallthrough_bb);
+      /* Note that fallthrough_bb starts with the statement that was
+	pointed to by ITER.  */
+
+      /* The 'then block' of the 'if (len != 0) condition is where
+	we'll generate the asan instrumentation code now.  */
+      gsi = gsi_last_bb (then_bb);
+    }
+
+  /* Get an iterator on the point where we can add the condition
+     statement for the instrumentation.  */
+  basic_block then_bb, else_bb;
+  gsi = create_cond_insert_point (&gsi, /*before_p*/false,
+				  /*then_more_likely_p=*/false,
+				  /*create_then_fallthru_edge=*/false,
+				  &then_bb,
+				  &else_bb);
+
+  g = gimple_build_assign_with_ops (NOP_EXPR,
+				    make_ssa_name (pointer_sized_int_node,
+						   NULL),
+				    base, NULL_TREE);
+  gimple_set_location (g, loc);
+  gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+  tree base_addr = gimple_assign_lhs (g);
+
+  tree t = NULL_TREE;
+  if (real_size_in_bytes >= 8)
+    {
+      tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
+					     shadow_ptr_type);
+      t = shadow;
+    }
+  else
+    {
+      /* Slow path for 1, 2 and 4 byte accesses.  */
+
+      if (!start_instrumented)
+	{
+	  /* Test (shadow != 0)
+	     & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow).  */
+	  tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
+						 shadow_ptr_type);
+	  gimple shadow_test = build_assign (NE_EXPR, shadow, 0);
+	  gimple_seq seq = NULL;
+	  gimple_seq_add_stmt (&seq, shadow_test);
+	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7));
+	  gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
+						      gimple_seq_last (seq)));
+	  if (real_size_in_bytes > 1)
+	    gimple_seq_add_stmt (&seq,
+				 build_assign (PLUS_EXPR, gimple_seq_last (seq),
+					       real_size_in_bytes - 1));
+	  gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
+						   gimple_seq_last (seq),
+						   shadow));
+	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
+						   gimple_seq_last (seq)));
+	  t = gimple_assign_lhs (gimple_seq_last (seq));
+	  gimple_seq_set_location (seq, loc);
+	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+	}
+
+      /* For non-constant, misaligned or otherwise weird access sizes,
+	 check first and last byte.  */
+      if (size_in_bytes == -1 && !end_instrumented)
+	{
+	  g = gimple_build_assign_with_ops (MINUS_EXPR,
+					    make_ssa_name (uintptr_type, NULL),
+					    len,
+					    build_int_cst (uintptr_type, 1));
+	  gimple_set_location (g, loc);
+	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+	  tree last = gimple_assign_lhs (g);
+	  g = gimple_build_assign_with_ops (PLUS_EXPR,
+					    make_ssa_name (uintptr_type, NULL),
+					    base_addr,
+					    last);
+	  gimple_set_location (g, loc);
+	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+	  tree base_end_addr = gimple_assign_lhs (g);
+
+	  tree shadow = build_shadow_mem_access (&gsi, loc, base_end_addr,
+						 shadow_ptr_type);
+	  gimple shadow_test = build_assign (NE_EXPR, shadow, 0);
+	  gimple_seq seq = NULL;
+	  gimple_seq_add_stmt (&seq, shadow_test);
+	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
+						   base_end_addr, 7));
+	  gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
+						      gimple_seq_last (seq)));
+	  gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
+						   gimple_seq_last (seq),
+						   shadow));
+	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
+						   gimple_seq_last (seq)));
+	  if (!start_instrumented)
+	    gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
+						     gimple_seq_last (seq)));
+	  t = gimple_assign_lhs (gimple_seq_last (seq));
+	  gimple_seq_set_location (seq, loc);
+	  gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
+	}
+    }
+
+  g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0),
+			 NULL_TREE, NULL_TREE);
+  gimple_set_location (g, loc);
+  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+
+  /* Generate call to the run-time library (e.g. __asan_report_load8).  */
+  gsi = gsi_start_bb (then_bb);
+  int nargs;
+  tree fun = report_error_func (is_store, size_in_bytes, &nargs);
+  g = gimple_build_call (fun, nargs, base_addr, len);
+  gimple_set_location (g, loc);
+  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
+
+  gsi_remove (iter, true);
+  *iter = gsi_start_bb (else_bb);
+}
+
 /* Instrument the current function.  */
 
 static unsigned int
@@ -2624,7 +2627,6 @@  asan_instrument (void)
 {
   if (shadow_ptr_types[0] == NULL_TREE)
     asan_init_shadow_ptr_types ();
-  asan_num_accesses = 0;
   transform_statements ();
   return 0;
 }
@@ -2744,10 +2746,35 @@  unsigned int
 pass_sanopt::execute (function *fun)
 {
   basic_block bb;
+  gimple_stmt_iterator gsi;
 
+  int asan_num_accesses = 0;
+  FOR_EACH_BB_FN (bb, fun)
+    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+      {
+ 	gimple stmt = gsi_stmt (gsi);
+	if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
+	  {
+	    enum internal_fn ifn = gimple_call_internal_fn (stmt);
+	    switch (ifn)
+	      {
+	      case IFN_ASAN_LOAD:
+	      case IFN_ASAN_STORE:
+		{
+		  ++asan_num_accesses;
+		  break;
+		}
+	      default:
+		break;
+	      }
+	    }
+        }
+
+  bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX
+    && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD;
+    
   FOR_EACH_BB_FN (bb, fun)
     {
-      gimple_stmt_iterator gsi;
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple stmt = gsi_stmt (gsi);
@@ -2756,17 +2783,27 @@  pass_sanopt::execute (function *fun)
 	    continue;
 
 	  if (gimple_call_internal_p (stmt))
-	    switch (gimple_call_internal_fn (stmt))
-	      {
-	      case IFN_UBSAN_NULL:
-		ubsan_expand_null_ifn (gsi);
-		break;
-	      case IFN_UBSAN_BOUNDS:
-		ubsan_expand_bounds_ifn (&gsi);
-		break;
-	      default:
-		break;
-	      }
+	    {
+	      enum internal_fn ifn = gimple_call_internal_fn (stmt);
+	      switch (ifn)
+		{
+		case IFN_UBSAN_NULL:
+		  ubsan_expand_null_ifn (gsi);
+		  break;
+		case IFN_UBSAN_BOUNDS:
+		  ubsan_expand_bounds_ifn (&gsi);
+		  break;
+		case IFN_ASAN_LOAD:
+		case IFN_ASAN_STORE:
+		  {
+		    bool is_store = ifn == IFN_ASAN_STORE;
+		    asan_expand_check_ifn (&gsi, is_store, use_calls);
+		    break;
+		  }
+		default:
+		  break;
+		}
+	    }
 
 	  if (dump_file && (dump_flags & TDF_DETAILS))
 	    {
@@ -2775,7 +2812,7 @@  pass_sanopt::execute (function *fun)
 	      fprintf (dump_file, "\n");
 	    }
 
-	  /* ubsan_expand_bounds_ifn might move us to the end of the BB.  */
+	  /* Expansions might move us to the end of the BB.  */
 	  if (gsi_end_p (gsi))
 	    break;
 	}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b5e8d98..8a755df 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -10312,9 +10312,9 @@  To disable use-after-return detection use
 @option{--param asan-use-after-return=0}.
 
 @item asan-instrumentation-with-call-threshold
-Once number of memory accesses  in function becomes greater
-or equal than this number, use callbacks instead of
-generating inline code.  E.g. to disable inline code use
+If number of memory accesses in function being instrumented
+is greater or equal to this number, use callbacks instead of inline checks.
+E.g. to disable inline code use
 @option{--param asan-instrumentation-with-call-threshold=0}.
 
 @end table
diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h
index 909d58b..0761bba 100644
--- a/gcc/gimple-iterator.h
+++ b/gcc/gimple-iterator.h
@@ -116,6 +116,7 @@  gsi_start_bb (basic_block bb)
   gimple_seq *seq;
 
   seq = bb_seq_addr (bb);
+  gcc_assert (seq);
   i.ptr = gimple_seq_first (*seq);
   i.seq = seq;
   i.bb = bb;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 78f59d6..f7935b2 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -167,6 +167,20 @@  expand_UBSAN_BOUNDS (gimple stmt ATTRIBUTE_UNUSED)
   gcc_unreachable ();
 }
 
+/* These should get expanded in the sanopt pass.  */
+
+static void
+expand_ASAN_LOAD (gimple stmt ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
+static void
+expand_ASAN_STORE (gimple stmt ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
 /* Add sub/add overflow checking to the statement STMT.
    CODE says whether the operation is +, or -.  */
 
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index f0766bc..cfa7450 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -54,3 +54,5 @@  DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN)
 DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (ASAN_LOAD, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (ASAN_STORE, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW)
diff --git a/gcc/params.def b/gcc/params.def
index aa1e88d..f1c44e0 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -1072,14 +1072,14 @@  DEFPARAM (PARAM_ASAN_MEMINTRIN,
 
 DEFPARAM (PARAM_ASAN_USE_AFTER_RETURN,
          "asan-use-after-return",
-         "Enable asan builtin functions protection",
+         "Enable asan detection of use-after-return bugs",
          1, 0, 1)
 
 DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
          "asan-instrumentation-with-call-threshold",
-         "Use callbacks instead of inline code once number of accesses "
-         " in function becomes greater or equal than this threshold",
-         10000, 0, INT_MAX)
+         "Use callbacks instead of inline code if number of accesses "
+         "in function becomes greater or equal to this number",
+         7000, 0, INT_MAX)
 
 DEFPARAM (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS,
 	  "uninit-control-dep-attempts",
diff --git a/gcc/testsuite/c-c++-common/asan/inc.c b/gcc/testsuite/c-c++-common/asan/inc.c
index b9c6734..865d50a 100644
--- a/gcc/testsuite/c-c++-common/asan/inc.c
+++ b/gcc/testsuite/c-c++-common/asan/inc.c
@@ -16,6 +16,6 @@  main ()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 1 "asan0" } }  */
-/* { dg-final { scan-tree-dump "__builtin___asan_report_load4" "asan0" } }  */
+/* { dg-final { scan-tree-dump-times "ASAN_" 1 "asan0" } }  */
+/* { dg-final { scan-tree-dump "ASAN_LOAD \\(.*, 4\\);" "asan0" } }  */
 /* { dg-final { cleanup-tree-dump "asan0" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c b/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c
index 570f796..04fdad0 100644
--- a/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c
+++ b/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c
@@ -9,8 +9,8 @@  void f(int *a, int *b) {
   x = *b;
 }
 
-/* { dg-final { scan-assembler-not "__asan_store4" } } */
-/* { dg-final { scan-assembler "__asan_report_store4" } } */
+/* { dg-final { scan-assembler "__asan_store4" } } */
+/* { dg-final { scan-assembler-not "__asan_report_store4" } } */
 /* { dg-final { scan-assembler "__asan_load4" } } */
 /* { dg-final { scan-assembler-not "__asan_report_load4" } } */
 /* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c
index c7c594e..028f8d7 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c
@@ -2,7 +2,7 @@ 
    location in the same basic block, the second reference should not
    be instrumented by the Address Sanitizer.  */
 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -62,7 +62,7 @@  main ()
   return test0 () && test1 (0);
 }
 
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 3 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 1 "asan0" }  } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 3 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 1 "sanopt" }  } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c
index 143312f..a58411c 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c
@@ -3,7 +3,7 @@ 
    be instrumented by the Address Sanitizer.  But in case of access to
    overlapping regions we must be precise.  */
 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -20,7 +20,7 @@  main ()
   __builtin_memset (tab, 1, 3);
 }
 
-/* { dg-final { scan-tree-dump-times "& 7" 3 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "asan0" }  } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "& 7" 3 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "sanopt" }  } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c
index 420a263..5193ae0 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -12,7 +12,7 @@  foo (__INT32_TYPE__ *p)
   return ret; 
 }
 
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store" 1 "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store" 1 "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c
index da91cd5..c3632aa 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -10,8 +10,8 @@  foo  (int *a, char *b, char *c)
   /* For a total of 5 checks.  */
 }
 
-/* { dg-final { scan-tree-dump-times "& 7" 5 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c
index 134be66..077ea34 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -10,9 +10,9 @@  foo  (int *a, char *b, char *c)
   /* For a total of 5 checks.  */
 }
 
-/* { dg-final { scan-tree-dump-times "& 7" 5 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c
index 55c8ee3..6d87104 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -12,9 +12,9 @@  foo  (int *a, char *b, char *c)
   /* For a total of 8 checks.  */
 }
 
-/* { dg-final { scan-tree-dump-times "& 7" 8 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 2 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 2 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "& 7" 8 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 2 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 2 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c
index a04956d..5baa10d 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -21,7 +21,7 @@  foo  (int *a, char *b, char *c)
   return d;
 }
 
-/* { dg-final { scan-tree-dump-times "& 7" 6 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 4 "asan0" } } */
-/* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "& 7" 6 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 4 "sanopt" } } */
+/* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c
index 308a133..2a4c081 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -12,9 +12,9 @@  foo  (int *a, char *b, char *c)
   /* For a total of 5 checks.  */
 }
 
-/* { dg-final { scan-tree-dump-times "& 7" 5 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "asan0" } } */
-/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */
+/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c
index c6575ad..9449de5 100644
--- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c
+++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c
@@ -1,4 +1,4 @@ 
-/* { dg-options "-fdump-tree-asan0" } */
+/* { dg-options "-fdump-tree-sanopt" } */
 /* { dg-do compile } */
 /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
 
@@ -9,5 +9,5 @@  f (char *a)
   return  __builtin_strlen (a);
 }
 
-/* { dg-final { scan-tree-dump-times "__asan_report_load1" 1 "asan0" } } */
-/* { dg-final { cleanup-tree-dump "asan0" } } */
+/* { dg-final { scan-tree-dump-times "__asan_report_load1" 1 "sanopt" } } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */