Skip to content

Commit d1ad931

Browse files
committed
JIT: make imported functions available to compiler
Optimize + and - as well as < and > when types are integers of known range. Also fix array functions of armv6m backend for higher indexes (>= 32). Signed-off-by: Paul Guyot <[email protected]>
1 parent 1db55ab commit d1ad931

21 files changed

+1300
-82
lines changed

libs/estdlib/src/code_server.erl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
atom_resolver/2,
4040
literal_resolver/2,
4141
type_resolver/2,
42+
import_resolver/2,
4243
set_native_code/3
4344
]).
4445

@@ -135,6 +136,14 @@ literal_resolver(_Module, _Index) ->
135136
type_resolver(_Module, _Index) ->
136137
erlang:nif_error(undefined).
137138

139+
%% @doc Get an imported function triplet from its index
140+
%% @return The imported function as {Module, Function, Arity}
141+
%% @param Module module to get the imported function from
142+
%% @param Index imported function index in the module
143+
-spec import_resolver(Module :: module(), Index :: non_neg_integer()) -> {atom(), atom(), non_neg_integer()}.
144+
import_resolver(_Module, _Index) ->
145+
erlang:nif_error(undefined).
146+
138147
%% @doc Associate a native code stream with a module
139148
%% @return ok
140149
%% @param Module module to set the native code of
@@ -164,13 +173,17 @@ load(Module) ->
164173
code_server:literal_resolver(Module, Index)
165174
end,
166175
TypeResolver = fun(Index) -> code_server:type_resolver(Module, Index) end,
176+
ImportResolver = fun(Index) ->
177+
code_server:import_resolver(Module, Index)
178+
end,
167179
{StreamModule, Stream0} = jit:stream(jit_mmap_size(byte_size(Code))),
168180
{BackendModule, BackendState0} = jit:backend(StreamModule, Stream0),
169181
{LabelsCount, BackendState1} = jit:compile(
170182
Code,
171183
AtomResolver,
172184
LiteralResolver,
173185
TypeResolver,
186+
ImportResolver,
174187
BackendModule,
175188
BackendState0
176189
),

libs/jit/src/jit.erl

Lines changed: 269 additions & 31 deletions
Large diffs are not rendered by default.

libs/jit/src/jit_aarch64.erl

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
-type condition() ::
155155
{aarch64_register(), '<', integer()}
156156
| {maybe_free_aarch64_register(), '<', aarch64_register()}
157+
| {integer(), '<', maybe_free_aarch64_register()}
157158
| {maybe_free_aarch64_register(), '==', integer()}
158159
| {maybe_free_aarch64_register(), '!=', aarch64_register() | integer()}
159160
| {'(int)', maybe_free_aarch64_register(), '==', integer()}
@@ -757,15 +758,47 @@ if_else_block(
757758
jit_aarch64_asm:cc() | {tbz | tbnz, atom(), 0..63} | {cbz, atom()},
758759
non_neg_integer()
759760
}.
760-
if_block_cond(#state{stream_module = StreamModule, stream = Stream0} = State0, {Reg, '<', 0}) ->
761+
if_block_cond(#state{stream_module = StreamModule, stream = Stream0} = State0, {RegOrTuple, '<', 0}) ->
762+
Reg =
763+
case RegOrTuple of
764+
{free, Reg0} -> Reg0;
765+
RegOrTuple -> RegOrTuple
766+
end,
761767
I = jit_aarch64_asm:tbz(Reg, 63, 0),
762768
Stream1 = StreamModule:append(Stream0, I),
763-
State1 = State0#state{stream = Stream1},
764-
{State1, {tbz, Reg, 63}, 0};
769+
State1 = if_block_free_reg(RegOrTuple, State0),
770+
State2 = State1#state{stream = Stream1},
771+
{State2, {tbz, Reg, 63}, 0};
772+
% Handle {Val, '<', Reg} - means Val < Reg, jump if false (i.e., if Val >= Reg or Reg <= Val)
765773
if_block_cond(
766774
#state{stream_module = StreamModule, stream = Stream0} = State0,
767-
{Reg, '<', Val}
768-
) when is_atom(Reg), is_integer(Val) ->
775+
{Val, '<', RegOrTuple}
776+
) when is_integer(Val) ->
777+
Reg =
778+
case RegOrTuple of
779+
{free, Reg0} -> Reg0;
780+
RegOrTuple -> RegOrTuple
781+
end,
782+
I1 = jit_aarch64_asm:cmp(Reg, Val),
783+
% le = less than or equal
784+
I2 = jit_aarch64_asm:bcc(le, 0),
785+
Code = <<
786+
I1/binary,
787+
I2/binary
788+
>>,
789+
Stream1 = StreamModule:append(Stream0, Code),
790+
State1 = if_block_free_reg(RegOrTuple, State0),
791+
State2 = State1#state{stream = Stream1},
792+
{State2, le, byte_size(I1)};
793+
if_block_cond(
794+
#state{stream_module = StreamModule, stream = Stream0} = State0,
795+
{RegOrTuple, '<', Val}
796+
) when is_integer(Val), Val =/= 0 ->
797+
Reg =
798+
case RegOrTuple of
799+
{free, Reg0} -> Reg0;
800+
RegOrTuple -> RegOrTuple
801+
end,
769802
I1 = jit_aarch64_asm:cmp(Reg, Val),
770803
% ge = greater than or equal
771804
I2 = jit_aarch64_asm:bcc(ge, 0),
@@ -774,8 +807,9 @@ if_block_cond(
774807
I2/binary
775808
>>,
776809
Stream1 = StreamModule:append(Stream0, Code),
777-
State1 = State0#state{stream = Stream1},
778-
{State1, ge, byte_size(I1)};
810+
State1 = if_block_free_reg(RegOrTuple, State0),
811+
State2 = State1#state{stream = Stream1},
812+
{State2, ge, byte_size(I1)};
779813
if_block_cond(
780814
#state{stream_module = StreamModule, stream = Stream0} = State0,
781815
{RegOrTuple, '<', RegB}
@@ -2073,8 +2107,10 @@ add(State, Reg, Val) ->
20732107
%% @param Val immediate value to subtract
20742108
%% @return Updated backend state
20752109
%%-----------------------------------------------------------------------------
2076-
-spec sub(state(), aarch64_register(), integer()) -> state().
2077-
sub(#state{stream_module = StreamModule, stream = Stream0} = State, Reg, Val) ->
2110+
-spec sub(state(), aarch64_register(), integer() | aarch64_register()) -> state().
2111+
sub(State, Reg, Val) when is_integer(Val) ->
2112+
op_imm(State, sub, Reg, Reg, Val);
2113+
sub(#state{stream_module = StreamModule, stream = Stream0} = State, Reg, Val) when is_atom(Val) ->
20782114
I1 = jit_aarch64_asm:sub(Reg, Reg, Val),
20792115
Stream1 = StreamModule:append(Stream0, I1),
20802116
State#state{stream = Stream1}.

libs/jit/src/jit_aarch64_asm.erl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,8 @@ sub(Rd, Rn, Imm) when is_atom(Rd), is_atom(Rn), is_integer(Imm), Imm >= 0, Imm =
948948
RdNum = reg_to_num(Rd),
949949
RnNum = reg_to_num(Rn),
950950
<<(16#D1000000 bor ((Imm band 16#FFF) bsl 10) bor (RnNum bsl 5) bor RdNum):32/little>>;
951+
sub(_Rd, _Rn, Imm) when is_integer(Imm) ->
952+
error({unencodable_immediate, Imm});
951953
sub(Rd, Rn, Rm) when is_atom(Rd), is_atom(Rn), is_atom(Rm) ->
952954
sub(Rd, Rn, Rm, {lsl, 0}).
953955

0 commit comments

Comments
 (0)