anchor.diff:          _ -> I
       end.
   
  -simplify_args(Args, Sub, Ts) ->
  -    [simplify_arg(Arg, Sub, Ts) || Arg <- Args].
  -
  -simplify_arg(#b_var{}=Arg0, Sub, Ts) ->
  +simplify_args(Args, Ts, Sub) ->
  +    [simplify_arg(Arg, Ts, Sub) || Arg <- Args].
  +
  +simplify_arg(#b_var{}=Arg0, Ts, Sub) ->
       case sub_arg(Arg0, Sub) of
           #b_literal{}=LitArg ->
               LitArg;
  
positive.code:                    %% literal, which would trick 'succeeded' into thinking it
                     %% can't fail.
                     type(succeeded, [Arg], Anno, Ts0, Ds0);
                 #{} ->
                     Args = simplify_args([Arg], Sub0, Ts0),
                     type(succeeded, Args, Anno, Ts0, Ds0)
             end,
      case beam_types:get_singleton_value(Type) of
          {ok, Lit} ->
              Sub = Sub0#{ Dst => #b_literal{val=Lit} },
              opt_is([], Ts0, Ds0, Fdb, D, Sub, Acc);
          error ->
              Ts = Ts0#{ Dst => Type },
              Ds = Ds0#{ Dst => I },
              opt_is([], Ts, Ds, Fdb, D, Sub0, [I | Acc])
      end;
  opt_is([#b_set{args=Args0}=I0|Is],
         Ts, Ds, Fdb, D, Sub, Acc) ->
      Args = simplify_args(Args0, Sub, Ts),
      I = beam_ssa:normalize(I0#b_set{args=Args}),
      opt_simplify(I, Is, Ts, Ds, Fdb, D, Sub, Acc);
  opt_is([], Ts, Ds, Fdb, _D, Sub, Acc) ->
      {reverse(Acc), Ts, Ds, Fdb, Sub}.
  
  opt_simplify(#b_set{dst=Dst}=I0, Is, Ts0, Ds0, Fdb, D, Sub0, Acc) ->
      case simplify(I0, Ts0) of
          #b_set{}=I2 ->
              I = beam_ssa:normalize(I2),
              Ts = update_types(I, Ts0, Ds0),
              Ds = Ds0#{ Dst => I },
              opt_is(Is, Ts, Ds, Fdb, D, Sub0, [I|Acc]);
          #b_literal{}=Lit ->
              Sub = Sub0#{ Dst => Lit },
              opt_is(Is, Ts0, Ds0, Fdb, D, Sub, Acc);
          #b_var{}=Var ->
              case Is of
                  [#b_set{op=succeeded,dst=SuccDst,args=[Dst]}] ->
                      %% We must remove this 'succeeded' instruction since the
                      %% variable it checks is gone.
                      Sub = Sub0#{ Dst => Var, SuccDst => #b_literal{val=true} },
                      opt_is([], Ts0, Ds0, Fdb, D, Sub, Acc);
                  _ ->
                      Sub = Sub0#{ Dst => Var},
                      opt_is(Is, Ts0, Ds0, Fdb, D, Sub, Acc)
              end
      end.
  
  opt_call(#b_set{dst=Dst,args=[#b_local{}=Callee|Args]}=I0, Ts, Fdb0, D) ->
      I = opt_local_call_return(I0, Callee, Fdb0, Ts),
      case Fdb0 of
          #{ Callee := #func_info{exported=false,arg_types=ArgTypes0}=Info } ->
              Types = argument_types(Args, Ts),
  
              %% Update the argument types of *this exact call*, the types
              %% will be joined later when the callee is optimized.
              CallId = {D#d.func_id, Dst},
              ArgTypes = update_arg_types(Types, ArgTypes0, CallId),
  
              Fdb = Fdb0#{ Callee => Info#func_info{arg_types=ArgTypes} },
              {I, Fdb};
          #{} ->
              %% We can't narrow the argument types of exported functions as they
              %% can receive anything as part of an external call.
              {I, Fdb0}
      end;
  opt_call(I, _Ts, Fdb, _D) ->
      {I, Fdb}.
  
  opt_local_call_return(#b_set{args=[_|Args]}=I, Callee, Fdb, Ts) ->
      case Fdb of
          #{ Callee := #func_info{succ_types=[_|_]=SuccTypes} } ->
              ArgTypes = argument_types(Args, Ts),
  
              case return_type(SuccTypes, ArgTypes) of
                  any -> I;
                  Type -> beam_ssa:add_anno(result_type, Type, I)
              end;
          #{} ->
              I
      end.
  
  %% While we have no way to know which arguments a fun will be called with, we
  %% do know its free variables and can update their types as if this were a
  %% local call.
  opt_make_fun(#b_set{op=make_fun,
                      dst=Dst,
                      args=[#b_local{}=Callee | FreeVars]}=I,
               D, Ts0, Ds0, Fdb0) ->
      Ts = update_types(I, Ts0, Ds0),
      Ds = Ds0#{ Dst => I },
      case Fdb0 of
          #{ Callee := #func_info{exported=false,arg_types=ArgTypes0}=Info } ->
              ArgCount = Callee#b_local.arity - length(FreeVars),
  
              FVTypes = [raw_type(FreeVar, Ts) || FreeVar <- FreeVars],
              Types = duplicate(ArgCount, any) ++ FVTypes,
  
              CallId = {D#d.func_id, Dst},
              ArgTypes = update_arg_types(Types, ArgTypes0, CallId),
  
              Fdb = Fdb0#{ Callee => Info#func_info{arg_types=ArgTypes} },
              {Ts, Ds, Fdb, I};
          #{} ->
              %% We can't narrow the argument types of exported functions as they
              %% can receive anything as part of an external call.
              {Ts, Ds, Fdb0, I}
      end.
  
  update_arg_types([ArgType | ArgTypes], [TypeMap0 | TypeMaps], CallId) ->
      TypeMap = TypeMap0#{ CallId => ArgType },
      [TypeMap | update_arg_types(ArgTypes, TypeMaps, CallId)];
  update_arg_types([], [], _CallId) ->
      [].
  
  %%%
  %%% Optimization helpers
  %%%
  
  simplify_terminator(#b_br{bool=Bool}=Br0, Sub, Ts, Ds) ->
      Br = beam_ssa:normalize(Br0#b_br{bool=simplify_arg(Bool, Sub, Ts)}),
      simplify_not(Br, Sub, Ts, Ds);
  simplify_terminator(#b_switch{arg=Arg0}=Sw0, Sub, Ts, Ds) ->
      Arg = simplify_arg(Arg0, Sub, Ts),
      Sw = Sw0#b_switch{arg=Arg},
  
      case beam_types:is_boolean_type(raw_type(Arg, Ts)) of
          true -> simplify_switch_bool(Sw, Sub, Ts, Ds);
          false -> beam_ssa:normalize(Sw)
      end;
  simplify_terminator(#b_ret{arg=Arg}=Ret, Sub, Ts, Ds) ->
      %% Reducing the result of a call to a literal (fairly common for 'ok')
      %% breaks tail call optimization.
      case Ds of
          #{ Arg := #b_set{op=call}} -> Ret;
          #{} -> Ret#b_ret{arg=simplify_arg(Arg, Sub, Ts)}
      end.
  
  simplify(#b_set{op={bif,'and'},args=Args}=I, Ts) ->
  
negative.code: 
  -define(UNICODE_MAX, (16#10FFFF)).
  
  %% Constant metadata used by both subpasses.
  -record(metadata,
          { func_id :: func_id(),
            params :: [beam_ssa:b_var()],
            used_once :: cerl_sets:set(beam_ssa:b_var()) }).
  
  -type type_db() :: #{ beam_ssa:var_name() := type() }.
  
  -spec opt_start(Linear, Args, Anno, FuncDb) -> {Linear, FuncDb} when
        Linear :: [{non_neg_integer(), beam_ssa:b_blk()}],
  