anchor.diff:      Tdb = copy_type(V, Val, Tdb1),
       Sub#sub{v=orddict:store(V, Val, S),s=gb_sets:add(V, Scope),t=Tdb}.
   
  -sub_del_var(#c_var{name=V}, #sub{v=S,t=Tdb}=Sub) ->
  -    Sub#sub{v=orddict:erase(V, S),t=kill_types(V, Tdb)}.
  +sub_del_var(#c_var{name=V}, #sub{v=S,s=Scope,t=Tdb}=Sub) ->
  +    %% Profiling shows that for programs with many record operations,
  +    %% sub_del_var/2 is a bottleneck. Since the scope contains all
  +    %% variables that are live, we know that V cannot be present in S
  +    %% if it is not in the scope.
  +    case gb_sets:is_member(V, Scope) of
  +	false ->
  +	    Sub#sub{s=gb_sets:insert(V, Scope)};
  +	true ->
  +	    Sub#sub{v=orddict:erase(V, S),t=kill_types(V, Tdb)}
  +    end.
   
   sub_subst_var(#c_var{name=V}, Val, #sub{v=S0}) ->
       %% Fold chained substitutions.
  
positive.code:     S = [{-1,#c_var{name=Sv}} || Sv <- gb_sets:to_list(Scope)]++S0,
      Sub#sub{v=S}.
  
  sub_is_val(#c_var{name=V}, #sub{v=S}) ->
      v_is_value(V, S).
  
  v_is_value(Var, Sub) ->
      any(fun ({_,#c_var{name=Val}}) when Val =:= Var -> true;
  	    (_) -> false
  	end, Sub).
  
  %% clauses(E, [Clause], TopLevel, Context, Sub) -> [Clause].
  %%  Trim the clauses by removing all clauses AFTER the first one which
  
negative.code: %%  chains so we never have to search more than once.  Use orddict so
  %%  we know the format.
  %%
  %%  In addition to the list of substitutions, we also keep track of
  %%  all variable currently live (the scope).
  %%
  %%  sub_subst_scope/1 adds dummy substitutions for all variables
  %%  in the scope in order to force renaming if variables in the
  %%  scope occurs as pattern variables.
  