Index: cfgexpand.c
===================================================================
--- cfgexpand.c	(revision 205123)
+++ cfgexpand.c	(working copy)
@@ -3785,6 +3785,7 @@ expand_debug_expr (tree exp)
       /* Fall through.  */
 
     adjust_mode:
+    case ADD_RESTRICT:
     case PAREN_EXPR:
     case NOP_EXPR:
     case CONVERT_EXPR:
Index: expr.c
===================================================================
--- expr.c	(revision 205123)
+++ expr.c	(working copy)
@@ -7988,6 +7988,41 @@ expand_cond_expr_using_cmove (tree treeo
   return NULL_RTX;
 }
 
+/* Given a memory pointer PTR, expand an RTL asm statement
+   that merely clobbers memory reachable from that pointer
+   via arbitrary offsets.  */
+
+void
+expand_pointer_clobber (tree ptr, location_t loc)
+{
+  tree ref = build_simple_mem_ref (ptr);
+  rtx op = expand_expr (ref, NULL_RTX, BLKmode, EXPAND_MEMORY);
+  rtx body;
+
+  op = validize_mem (op);
+
+  /* There's no way to construct a tree expression doing exactly what
+     we need (representing a reference to arbitrarily memory reachable
+     from a given pointer, i.e. with arbitrary offsets.  Hence
+     construct that by massaging the MEM attributes.  */
+  clear_mem_offset (op);
+  clear_mem_size (op);
+  PUT_MODE (op, BLKmode);
+
+  rtvec argvec = rtvec_alloc (0);
+  rtvec constraintvec = rtvec_alloc (0);
+  rtvec labelvec = rtvec_alloc (0);
+
+  body = gen_rtx_ASM_OPERANDS (BLKmode,
+			       ggc_strdup (""),
+			       ggc_strdup ("=m"), 0, argvec, constraintvec,
+			       labelvec, loc);
+
+  MEM_VOLATILE_P (body) = 1;
+
+  emit_insn (gen_rtx_SET (VOIDmode, op, body));
+}
+
 rtx
 expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 		    enum expand_modifier modifier)
@@ -8047,6 +8082,13 @@ expand_expr_real_2 (sepops ops, rtx targ
 
   switch (code)
     {
+    case ADD_RESTRICT:
+      /* We can handle add_restrict like a conversion, treeop1 will be
+         ignored.  But do create a barrier to contain the restrict
+	 section.  */
+      expand_pointer_clobber (treeop0, loc);
+
+      /* FALLTHRU.  */
     case NON_LVALUE_EXPR:
     case PAREN_EXPR:
     CASE_CONVERT:
Index: expr.h
===================================================================
--- expr.h	(revision 205123)
+++ expr.h	(working copy)
@@ -719,6 +719,8 @@ extern rtx extract_low_bits (enum machin
 extern rtx expand_mult (enum machine_mode, rtx, rtx, rtx, int);
 extern rtx expand_mult_highpart_adjust (enum machine_mode, rtx, rtx, rtx, rtx, int);
 
+extern void expand_pointer_clobber (tree, location_t);
+
 extern rtx assemble_static_space (unsigned HOST_WIDE_INT);
 extern int safe_from_p (const_rtx, tree, int);
 extern bool split_comparison (enum rtx_code, enum machine_mode,
Index: function.c
===================================================================
--- function.c	(revision 205123)
+++ function.c	(working copy)
@@ -3595,10 +3595,11 @@ gimplify_parm_type (tree *tp, int *walk_
 /* Gimplify the parameter list for current_function_decl.  This involves
    evaluating SAVE_EXPRs of variable sized parameters and generating code
    to implement callee-copies reference parameters.  Returns a sequence of
-   statements to add to the beginning of the function.  */
+   statements to add to the beginning of the function and another
+   sequence to add to the end of the function (via *STMT_AFTER).  */
 
 gimple_seq
-gimplify_parameters (void)
+gimplify_parameters (gimple_seq *stmts_after)
 {
   struct assign_parm_data_all all;
   tree parm;
@@ -3606,6 +3607,7 @@ gimplify_parameters (void)
   vec<tree> fnargs;
   unsigned i;
 
+  *stmts_after = NULL;
   assign_parms_initialize_all (&all);
   fnargs = assign_parms_augmented_arg_list (&all);
 
@@ -3690,6 +3692,17 @@ gimplify_parameters (void)
 	      DECL_HAS_VALUE_EXPR_P (parm) = 1;
 	    }
 	}
+      if (POINTER_TYPE_P (TREE_TYPE (parm))
+	  && TYPE_RESTRICT (TREE_TYPE (parm))
+	  && !DECL_HAS_VALUE_EXPR_P (parm))
+	{
+	  tree t = fold_build2 (ADD_RESTRICT, TREE_TYPE (parm), parm,
+				build_int_cst (integer_type_node,
+					       allocate_decl_uid ()));
+	  gimplify_assign (parm, t, &stmts);
+	  gimple g = gimple_build_call_internal (IFN_DEL_RESTRICT, 1, parm);
+	  gimple_seq_add_stmt (stmts_after, g);
+	}
     }
 
   fnargs.release ();
Index: function.h
===================================================================
--- function.h	(revision 205123)
+++ function.h	(working copy)
@@ -841,6 +841,6 @@ extern void preserve_temp_slots (rtx);
 extern int aggregate_value_p (const_tree, const_tree);
 extern void push_function_context (void);
 extern void pop_function_context (void);
-extern gimple_seq gimplify_parameters (void);
+extern gimple_seq gimplify_parameters (gimple_seq *);
 
 #endif  /* GCC_FUNCTION_H */
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c	(revision 205123)
+++ gimple-pretty-print.c	(working copy)
@@ -348,6 +348,7 @@ dump_binary_rhs (pretty_printer *buffer,
     case COMPLEX_EXPR:
     case MIN_EXPR:
     case MAX_EXPR:
+    case ADD_RESTRICT:
     case VEC_WIDEN_MULT_HI_EXPR:
     case VEC_WIDEN_MULT_LO_EXPR:
     case VEC_WIDEN_MULT_EVEN_EXPR:
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 205123)
+++ gimplify.c	(working copy)
@@ -1005,8 +1005,9 @@ gimplify_bind_expr (tree *expr_p, gimple
 	  && !DECL_HARD_REGISTER (t)
 	  && !TREE_THIS_VOLATILE (t)
 	  && !DECL_HAS_VALUE_EXPR_P (t)
-	  /* Only care for variables that have to be in memory.  Others
-	     will be rewritten into SSA names, hence moved to the top-level.  */
+	  /* Only care for variables that have to be in memory.
+	     Others will be rewritten into SSA names, hence moved
+	     to the top-level.  */
 	  && !is_gimple_reg (t)
 	  && flag_stack_reuse != SR_NONE)
 	{
@@ -8356,7 +8357,7 @@ gimple
 gimplify_body (tree fndecl, bool do_parms)
 {
   location_t saved_location = input_location;
-  gimple_seq parm_stmts, seq;
+  gimple_seq parm_stmts, parm_stmts_after, seq;
   gimple outer_bind;
   struct gimplify_ctx gctx;
   struct cgraph_node *cgn;
@@ -8393,7 +8394,8 @@ gimplify_body (tree fndecl, bool do_parm
 
   /* Resolve callee-copies.  This has to be done before processing
      the body so that DECL_VALUE_EXPR gets processed correctly.  */
-  parm_stmts = do_parms ? gimplify_parameters () : NULL;
+  parm_stmts_after = NULL;
+  parm_stmts = do_parms ? gimplify_parameters (&parm_stmts_after) : NULL;
 
   /* Gimplify the function's body.  */
   seq = NULL;
@@ -8432,6 +8434,10 @@ gimplify_body (tree fndecl, bool do_parm
 	    DECL_IGNORED_P (parm) = 0;
 	  }
     }
+  /* Same for statements that need to come after the body.  */
+  if (!gimple_seq_empty_p (parm_stmts_after))
+    gimplify_seq_add_seq (gimple_bind_body_ptr (outer_bind),
+			  parm_stmts_after);
 
   if (nonlocal_vlas)
     {
Index: internal-fn.c
===================================================================
--- internal-fn.c	(revision 205123)
+++ internal-fn.c	(working copy)
@@ -148,6 +148,16 @@ expand_UBSAN_NULL (gimple stmt ATTRIBUTE
   gcc_unreachable ();
 }
 
+/* Expand the DEL_RESTRICT internal function into a RTL
+   asm that merely clobbers memory reachable via the pointer.  */
+
+static void
+expand_DEL_RESTRICT (gimple stmt)
+{
+  tree ptr = gimple_call_arg (stmt, 0);
+  expand_pointer_clobber (ptr, gimple_location (stmt));
+}
+
 /* Routines to expand each internal function, indexed by function number.
    Each routine has the prototype:
 
Index: internal-fn.def
===================================================================
--- internal-fn.def	(revision 205123)
+++ internal-fn.def	(working copy)
@@ -45,3 +45,4 @@ DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST
 DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (ANNOTATE,  ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (DEL_RESTRICT,  /*ECF_LEAF |*/ ECF_NOTHROW)
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 205123)
+++ tree-cfg.c	(working copy)
@@ -3627,6 +3627,21 @@ verify_gimple_assign_binary (gimple stmt
 	return false;
       }
 
+    case ADD_RESTRICT:
+      {
+	if (!POINTER_TYPE_P (rhs1_type)
+	    || !useless_type_conversion_p (lhs_type, rhs1_type)
+	    || !useless_type_conversion_p (integer_type_node, rhs2_type))
+	  {
+	    error ("Invalid use of add_restrict");
+	    debug_generic_stmt (lhs_type);
+	    debug_generic_stmt (rhs1_type);
+	    debug_generic_stmt (rhs2_type);
+	    return true;
+	  }
+	return false;
+      }
+
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_AND_EXPR:
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 205123)
+++ tree-inline.c	(working copy)
@@ -3580,6 +3580,7 @@ estimate_operator_cost (enum tree_code c
     case COMPLEX_EXPR:
     case PAREN_EXPR:
     case VIEW_CONVERT_EXPR:
+    case ADD_RESTRICT:
       return 0;
 
     /* Assign cost of 1 to usual operations.
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 205123)
+++ tree-pretty-print.c	(working copy)
@@ -1927,6 +1927,14 @@ dump_generic_node (pretty_printer *buffe
       pp_greater (buffer);
       break;
 
+    case ADD_RESTRICT:
+      pp_string (buffer, "ADD_RESTRICT <");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_string (buffer, ", ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      pp_character (buffer, '>');
+      break;
+
     case ABS_EXPR:
       pp_string (buffer, "ABS_EXPR <");
       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
Index: tree-ssa-dce.c
===================================================================
--- tree-ssa-dce.c	(revision 205123)
+++ tree-ssa-dce.c	(working copy)
@@ -828,6 +828,10 @@ propagate_necessity (bool aggressive)
 		      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
 		continue;
 
+	      if (gimple_call_internal_p (stmt)
+		  && gimple_call_internal_fn (stmt) == IFN_DEL_RESTRICT)
+		continue;
+
 	      /* Calls implicitly load from memory, their arguments
 	         in addition may explicitly perform memory loads.  */
 	      mark_all_reaching_defs_necessary (stmt);
Index: tree-ssa-structalias.c
===================================================================
--- tree-ssa-structalias.c	(revision 205123)
+++ tree-ssa-structalias.c	(working copy)
@@ -3741,31 +3741,43 @@ make_transitive_closure_constraints (var
 /* Temporary storage for fake var decls.  */
 struct obstack fake_var_decl_obstack;
 
-/* Build a fake VAR_DECL acting as referrer to a DECL_UID.  */
+/* Build a fake VAR_DECL with DECL_UID being UID (which probably has
+   to be ultimately allocated by allocate_decl_uid()).  */
 
 static tree
-build_fake_var_decl (tree type)
+build_fake_var_decl_uid (tree type, int uid)
 {
   tree decl = (tree) XOBNEW (&fake_var_decl_obstack, struct tree_var_decl);
   memset (decl, 0, sizeof (struct tree_var_decl));
   TREE_SET_CODE (decl, VAR_DECL);
   TREE_TYPE (decl) = type;
-  DECL_UID (decl) = allocate_decl_uid ();
+  DECL_UID (decl) = uid;
   SET_DECL_PT_UID (decl, -1);
   layout_decl (decl, 0);
   return decl;
 }
 
-/* Create a new artificial heap variable with NAME.
-   Return the created variable.  */
+/* Build a fake VAR_DECL acting as referrer to a DECL_UID.  */
+
+static tree
+build_fake_var_decl (tree type)
+{
+  return build_fake_var_decl_uid (type, allocate_decl_uid ());
+}
+
+/* Create a new artificial heap variable with NAME and UID.
+   If UID is -1 allocate a new one.  Return the created variable.  */
 
 static varinfo_t
-make_heapvar (const char *name)
+make_heapvar (const char *name, int uid)
 {
   varinfo_t vi;
   tree heapvar;
   
-  heapvar = build_fake_var_decl (ptr_type_node);
+  if (uid == -1)
+    heapvar = build_fake_var_decl (ptr_type_node);
+  else
+    heapvar = build_fake_var_decl_uid (ptr_type_node, uid);
   DECL_EXTERNAL (heapvar) = 1;
 
   vi = new_var_info (heapvar, name);
@@ -3781,22 +3793,34 @@ make_heapvar (const char *name)
   return vi;
 }
 
-/* Create a new artificial heap variable with NAME and make a
+/* Create a new artificial heap variable with NAME and UID and make a
    constraint from it to LHS.  Set flags according to a tag used
    for tracking restrict pointers.  */
 
 static varinfo_t
-make_constraint_from_restrict (varinfo_t lhs, const char *name)
+make_constraint_from_restrict_uid (varinfo_t lhs, const char *name, int uid)
 {
-  varinfo_t vi = make_heapvar (name);
-  vi->is_global_var = 1;
-  vi->may_have_pointers = 1;
+  varinfo_t vi;
+  vi = make_heapvar (name, uid);
   make_constraint_from (lhs, vi->id);
+  vi->is_global_var = 0;
+  /*vi->is_special_var = 1;*/
+  vi->may_have_pointers = 1;
   return vi;
 }
 
 /* Create a new artificial heap variable with NAME and make a
    constraint from it to LHS.  Set flags according to a tag used
+   for tracking restrict pointers.  */
+
+static varinfo_t
+make_constraint_from_restrict (varinfo_t lhs, const char *name)
+{
+  return make_constraint_from_restrict_uid (lhs, name, -1);
+}
+
+/* Create a new artificial heap variable with NAME and make a
+   constraint from it to LHS.  Set flags according to a tag used
    for tracking restrict pointers and make the artificial heap
    point to global memory.  */
 
@@ -3804,6 +3828,7 @@ static varinfo_t
 make_constraint_from_global_restrict (varinfo_t lhs, const char *name)
 {
   varinfo_t vi = make_constraint_from_restrict (lhs, name);
+  vi->is_global_var = 1;
   make_copy_constraint (vi, nonlocal_id);
   return vi;
 }
@@ -3999,7 +4024,7 @@ handle_lhs_call (gimple stmt, tree lhs,
       varinfo_t vi;
       struct constraint_expr tmpc;
       rhsc.create (0);
-      vi = make_heapvar ("HEAP");
+      vi = make_heapvar ("HEAP", -1);
       /* We marking allocated storage local, we deal with it becoming
          global by escaping and setting of vars_contains_escaped_heap.  */
       DECL_EXTERNAL (vi->decl) = 0;
@@ -4490,6 +4515,28 @@ find_func_aliases_for_builtin_call (gimp
   return false;
 }
 
+/* Create constraints for the internal call T.  Return true if the call
+   was handled, otherwise false.  */
+
+static bool
+find_func_aliases_for_internal_call (gimple t)
+{
+  switch (gimple_call_internal_fn (t))
+    {
+    case IFN_DEL_RESTRICT:
+      {
+	/* DEL_RESTRICT is a barrier for what its argument points to.  */
+	tree ptr = gimple_call_arg (t, 0);
+	make_constraint_to (get_call_clobber_vi (t)->id, ptr);
+	return true;
+      }
+
+    default:
+      /* Fallthru to general call handling.  */;
+    }
+  return false;
+}
+ 
 /* Create constraints for the call T.  */
 
 static void
@@ -4505,6 +4552,10 @@ find_func_aliases_for_call (gimple t)
       && find_func_aliases_for_builtin_call (t))
     return;
 
+  if (gimple_call_internal_p (t)
+      && find_func_aliases_for_internal_call (t))
+    return;
+
   fi = get_fi_for_callee (t);
   if (!in_ipa_mode
       || (fndecl && !fi->is_fn_info))
@@ -4715,6 +4766,16 @@ find_func_aliases (gimple origt)
 	    /* Truth value results are not pointer (parts).  Or at least
 	       very very unreasonable obfuscation of a part.  */
 	    ;
+	  else if (gimple_assign_rhs_code (t) == ADD_RESTRICT)
+	    {
+	      /* Add the specified restrict tag and merge from
+	         the incoming pointer.  */
+	      make_constraint_from_restrict_uid (get_vi_for_tree (lhsop),
+						 "RESTRICT_TAG",
+						 TREE_INT_CST_LOW
+						   (gimple_assign_rhs2 (t)));
+	      get_constraint_for_rhs (gimple_assign_rhs1 (t), &rhsc);
+	    }
 	  else
 	    {
 	      /* All other operations are merges.  */
@@ -5852,50 +5913,10 @@ intra_create_variable_infos (void)
     {
       varinfo_t p = get_vi_for_tree (t);
 
-      /* For restrict qualified pointers to objects passed by
-         reference build a real representative for the pointed-to object.
-	 Treat restrict qualified references the same.  */
-      if (TYPE_RESTRICT (TREE_TYPE (t))
-	  && ((DECL_BY_REFERENCE (t) && POINTER_TYPE_P (TREE_TYPE (t)))
-	      || TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
-	  && !type_contains_placeholder_p (TREE_TYPE (TREE_TYPE (t))))
-	{
-	  struct constraint_expr lhsc, rhsc;
-	  varinfo_t vi;
-	  tree heapvar = build_fake_var_decl (TREE_TYPE (TREE_TYPE (t)));
-	  DECL_EXTERNAL (heapvar) = 1;
-	  vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
-	  insert_vi_for_tree (heapvar, vi);
-	  lhsc.var = p->id;
-	  lhsc.type = SCALAR;
-	  lhsc.offset = 0;
-	  rhsc.var = vi->id;
-	  rhsc.type = ADDRESSOF;
-	  rhsc.offset = 0;
-	  process_constraint (new_constraint (lhsc, rhsc));
-	  for (; vi; vi = vi_next (vi))
-	    if (vi->may_have_pointers)
-	      {
-		if (vi->only_restrict_pointers)
-		  make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
-		else
-		  make_copy_constraint (vi, nonlocal_id);
-	      }
-	  continue;
-	}
-
-      if (POINTER_TYPE_P (TREE_TYPE (t))
-	  && TYPE_RESTRICT (TREE_TYPE (t)))
-	make_constraint_from_global_restrict (p, "PARM_RESTRICT");
-      else
+      for (; p; p = vi_next (p))
 	{
-	  for (; p; p = vi_next (p))
-	    {
-	      if (p->only_restrict_pointers)
-		make_constraint_from_global_restrict (p, "PARM_RESTRICT");
-	      else if (p->may_have_pointers)
-		make_constraint_from (p, nonlocal_id);
-	    }
+	  if (p->may_have_pointers)
+	    make_constraint_from (p, nonlocal_id);
 	}
     }
 
@@ -6022,7 +6043,7 @@ set_uids_in_ptset (bitmap into, bitmap f
 	      && bitmap_bit_p (escaped_vi->solution, i)))
 	{
 	  pt->vars_contains_escaped = true;
-	  pt->vars_contains_escaped_heap = vi->is_heap_var;
+	  pt->vars_contains_escaped_heap |= vi->is_heap_var;
 	}
 
       if (TREE_CODE (vi->decl) == VAR_DECL
@@ -6045,10 +6066,10 @@ set_uids_in_ptset (bitmap into, bitmap f
 }
 
 
-/* Compute the points-to solution *PT for the variable VI.  */
+/* Compute the points-to solution *PT for the variable VI, part one.  */
 
 static struct pt_solution
-find_what_var_points_to (varinfo_t orig_vi)
+find_what_var_points_to_1 (varinfo_t orig_vi)
 {
   unsigned int i;
   bitmap_iterator bi;
@@ -6096,7 +6117,7 @@ find_what_var_points_to (varinfo_t orig_
 	    /* Nobody cares.  */
 	    ;
 	  else if (vi->id == anything_id
-		   || vi->id == integer_id)
+		    || vi->id == integer_id)
 	    pt->anything = 1;
 	}
     }
@@ -6126,6 +6147,71 @@ find_what_var_points_to (varinfo_t orig_
   return *pt;
 }
 
+/* Compute the points-to solution *PT for the variable VI, part two.
+   This modifies the points-to solution to cater for restrict pointers.
+   
+   Restrict is modelled as a may-be restrict problem together with
+   a must-be restrict problem.  From the must-be restrict solution we
+   can later deduce non-aliasing (if the points-to sets don't intersect
+   the two references can't alias).  The may-be restrict problem provides
+   a sort of conservative cap for that such that a pointer p1 that is even
+   remotely related to a restrict pointer r2 points to a superset of what
+   p1 points to.  In particular we want to handle this situation:
+
+      1 int * restrict p1 = ...;
+      2 temp = p1;
+      3 int * restrict p2;
+      4 p2 = temp;
+
+      Suppose that 'temp' is address taken, so (2) is a store and
+      (4) a load.  We want to make sure that p1 and p2 are tagged
+      the same (remember we're not handling just the C language
+      definition of restrict).  To ensure this we need to look through
+      memory (and even handle second level effects, like when a restrict
+      pointer is stored into a global variable).
+
+   That's why we use the points-to solver for the may-be restrict problem
+   (which handles memory conservatively correct).  The must-be restrict
+   part then is formulated as a post-processing on the conservatively
+   correct points-to solution.  For a set of variables their solution
+   is pruned.  This pruned solution is returned here.  */
+
+static struct pt_solution
+find_what_var_points_to (varinfo_t vi)
+{
+  struct pt_solution pt;
+
+  pt = find_what_var_points_to_1 (vi);
+
+  if (vi->decl && TREE_CODE (vi->decl) == SSA_NAME)
+    {
+      gimple g = SSA_NAME_DEF_STMT (vi->decl);
+      if (g && is_gimple_assign (g)
+	  && gimple_assign_rhs_code (g) == ADD_RESTRICT)
+	{
+	  /* Restrict pointers only point to their tags.  For now
+	     we leave also the other decls in the points-to set:
+	     changing the set would imply possibly unsharing the bitmap,
+	     and furthermore it's actually good to have precise
+	     decls in there in some cases, e.g. if it's local variables.
+
+	     In effect this means removing the nonlocal flags.  To
+	     not regard stores via such pointers as inherently useless
+	     we need to set the vars_contains_escaped_heap flag, if the
+	     input contained some nonlocals.  */
+	  if (pt.vars_contains_nonlocal
+	      || pt.nonlocal
+	      || pt.vars_contains_escaped)
+	    pt.vars_contains_escaped_heap = 1;
+	  pt.nonlocal = 0;
+	  pt.vars_contains_escaped = 0;
+	  pt.vars_contains_nonlocal = 0;
+	}
+    }
+
+  return pt;
+}
+
 /* Given a pointer variable P, fill in its points-to set.  */
 
 static void
@@ -6866,10 +6952,14 @@ compute_points_to_sets (void)
 	      *pt = find_what_var_points_to (vi);
 	      /* Escaped (and thus nonlocal) variables are always
 	         implicitly used by calls.  */
-	      /* ???  ESCAPED can be empty even though NONLOCAL
-		 always escaped.  */
-	      pt->nonlocal = 1;
-	      pt->escaped = 1;
+	      if (!gimple_call_internal_p (stmt)
+		  || gimple_call_internal_fn (stmt) != IFN_DEL_RESTRICT)
+		{
+		  /* ???  ESCAPED can be empty even though NONLOCAL
+		     always escaped.  */
+		  pt->nonlocal = 1;
+		  pt->escaped = 1;
+		}
 	    }
 	  else
 	    {
@@ -6887,10 +6977,14 @@ compute_points_to_sets (void)
 	      *pt = find_what_var_points_to (vi);
 	      /* Escaped (and thus nonlocal) variables are always
 	         implicitly clobbered by calls.  */
-	      /* ???  ESCAPED can be empty even though NONLOCAL
-		 always escaped.  */
-	      pt->nonlocal = 1;
-	      pt->escaped = 1;
+	      if (!gimple_call_internal_p (stmt)
+		  || gimple_call_internal_fn (stmt) != IFN_DEL_RESTRICT)
+		{
+		  /* ???  ESCAPED can be empty even though NONLOCAL
+		     always escaped.  */
+		  pt->nonlocal = 1;
+		  pt->escaped = 1;
+		}
 	    }
 	  else
 	    {
Index: tree.def
===================================================================
--- tree.def	(revision 205123)
+++ tree.def	(working copy)
@@ -977,6 +977,8 @@ DEFTREECODE (WITH_SIZE_EXPR, "with_size_
    generated by the builtin targetm.vectorize.mask_for_load_builtin_decl.  */
 DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3)
 
+DEFTREECODE (ADD_RESTRICT, "add_restrict", tcc_binary, 2)
+
 /* Low-level memory addressing.  Operands are BASE (address of static or
    global variable or register), OFFSET (integer constant),
    INDEX (register), STEP (integer constant), INDEX2 (register),
