aboutsummaryrefslogtreecommitdiffstats
path: root/lib/hipe
diff options
context:
space:
mode:
Diffstat (limited to 'lib/hipe')
-rw-r--r--lib/hipe/arm/hipe_arm_assemble.erl2
-rw-r--r--lib/hipe/cerl/erl_bif_types.erl5
-rw-r--r--lib/hipe/icode/hipe_beam_to_icode.erl13
-rw-r--r--lib/hipe/icode/hipe_icode_range.erl20
-rw-r--r--lib/hipe/llvm/hipe_llvm_merge.erl2
-rw-r--r--lib/hipe/misc/hipe_consttab.erl15
-rw-r--r--lib/hipe/misc/hipe_pack_constants.erl12
-rw-r--r--lib/hipe/ppc/hipe_ppc_assemble.erl2
-rw-r--r--lib/hipe/regalloc/hipe_coalescing_regalloc.erl2
-rw-r--r--lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl6
-rw-r--r--lib/hipe/regalloc/hipe_optimistic_regalloc.erl2
-rw-r--r--lib/hipe/sparc/hipe_sparc_assemble.erl2
-rw-r--r--lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl42
-rw-r--r--lib/hipe/x86/hipe_x86_assemble.erl2
14 files changed, 87 insertions, 40 deletions
diff --git a/lib/hipe/arm/hipe_arm_assemble.erl b/lib/hipe/arm/hipe_arm_assemble.erl
index 713c148742..9aa730afa9 100644
--- a/lib/hipe/arm/hipe_arm_assemble.erl
+++ b/lib/hipe/arm/hipe_arm_assemble.erl
@@ -31,7 +31,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
|| {MFA, Defun} <- CompiledCode],
%%
{ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, 4),
+ hipe_pack_constants:pack_constants(Code),
%%
{CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} =
encode(translate(Code, ConstMap), Options),
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl
index 8c96e60229..9321750d44 100644
--- a/lib/hipe/cerl/erl_bif_types.erl
+++ b/lib/hipe/cerl/erl_bif_types.erl
@@ -2029,17 +2029,14 @@ arith_rem(Min1, Max1, Min2, Max2) ->
Min1_geq_zero = infinity_geq(Min1, 0),
Max1_leq_zero = infinity_geq(0, Max1),
Max_range2 = infinity_max([infinity_abs(Min2), infinity_abs(Max2)]),
- Max_range2_leq_zero = infinity_geq(0, Max_range2),
- New_min =
+ New_min =
if Min1_geq_zero -> 0;
Max_range2 =:= 0 -> 0;
- Max_range2_leq_zero -> infinity_add(Max_range2, 1);
true -> infinity_add(infinity_inv(Max_range2), 1)
end,
New_max =
if Max1_leq_zero -> 0;
Max_range2 =:= 0 -> 0;
- Max_range2_leq_zero -> infinity_add(infinity_inv(Max_range2), -1);
true -> infinity_add(Max_range2, -1)
end,
{New_min, New_max}.
diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl
index 610578dfbc..2abecf7f18 100644
--- a/lib/hipe/icode/hipe_beam_to_icode.erl
+++ b/lib/hipe/icode/hipe_beam_to_icode.erl
@@ -513,6 +513,19 @@ trans_fun([{test,test_arity,{f,Lbl},[Reg,N]}|Instructions], Env) ->
I = hipe_icode:mk_type([trans_arg(Reg)],{tuple,N},
hipe_icode:label_name(True),map_label(Lbl)),
[I,True | trans_fun(Instructions,Env)];
+%%--- test_is_tagged_tuple ---
+trans_fun([{test,is_tagged_tuple,{f,Lbl},[Reg,N,Atom]}|Instructions], Env) ->
+ TrueArity = mk_label(new),
+ IArity = hipe_icode:mk_type([trans_arg(Reg)],{tuple,N},
+ hipe_icode:label_name(TrueArity),map_label(Lbl)),
+ Var = hipe_icode:mk_new_var(),
+ IGet = hipe_icode:mk_primop([Var],
+ #unsafe_element{index=1},
+ [trans_arg(Reg)]),
+ TrueAtom = mk_label(new),
+ IEQ = hipe_icode:mk_type([Var], Atom, hipe_icode:label_name(TrueAtom),
+ map_label(Lbl)),
+ [IArity,TrueArity,IGet,IEQ,TrueAtom | trans_fun(Instructions,Env)];
%%--- is_map ---
trans_fun([{test,is_map,{f,Lbl},[Arg]}|Instructions], Env) ->
{Code,Env1} = trans_type_test(map,Lbl,Arg,Env),
diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl
index b884132327..287b1c80fe 100644
--- a/lib/hipe/icode/hipe_icode_range.erl
+++ b/lib/hipe/icode/hipe_icode_range.erl
@@ -392,14 +392,17 @@ widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) ->
-spec analyse_call(#icode_call{}, call_fun()) -> #icode_call{}.
analyse_call(Call, LookupFun) ->
+ Args = hipe_icode:args(Call),
+ Fun = hipe_icode:call_fun(Call),
+ Type = hipe_icode:call_type(Call),
+ %% This call has side-effects (it might call LookupFun which sends messages to
+ %% hipe_icode_coordinator to update the argument ranges of Fun), and must thus
+ %% not be moved into the case statement.
+ DstRanges = analyse_call_or_enter_fun(Fun, Args, Type, LookupFun),
case hipe_icode:call_dstlist(Call) of
[] ->
Call;
Dsts ->
- Args = hipe_icode:args(Call),
- Fun = hipe_icode:call_fun(Call),
- Type = hipe_icode:call_type(Call),
- DstRanges = analyse_call_or_enter_fun(Fun, Args, Type, LookupFun),
NewDefs = [update_info(Var, R) || {Var,R} <- lists:zip(Dsts, DstRanges)],
hipe_icode:subst_defines(lists:zip(Dsts, NewDefs), Call)
end.
@@ -1306,16 +1309,15 @@ range_rem(Range1, Range2) ->
Min1_geq_zero = inf_geq(Min1, 0),
Max1_leq_zero = inf_geq(0, Max1),
Max_range2 = inf_max([inf_abs(Min2), inf_abs(Max2)]),
- Max_range2_leq_zero = inf_geq(0, Max_range2),
New_min =
if Min1_geq_zero -> 0;
- Max_range2_leq_zero -> Max_range2;
- true -> inf_inv(Max_range2)
+ Max_range2 =:= 0 -> 0;
+ true -> inf_add(inf_inv(Max_range2), 1)
end,
New_max =
if Max1_leq_zero -> 0;
- Max_range2_leq_zero -> inf_inv(Max_range2);
- true -> Max_range2
+ Max_range2 =:= 0 -> 0;
+ true -> inf_add(Max_range2, -1)
end,
range_init({New_min, New_max}, false).
diff --git a/lib/hipe/llvm/hipe_llvm_merge.erl b/lib/hipe/llvm/hipe_llvm_merge.erl
index 6e891ac3b0..58d862fbb2 100644
--- a/lib/hipe/llvm/hipe_llvm_merge.erl
+++ b/lib/hipe/llvm/hipe_llvm_merge.erl
@@ -13,7 +13,7 @@ finalize(CompiledCode, Closures, Exports) ->
Code = [{MFA, [], ConstTab}
|| {MFA, _, _ , ConstTab, _, _} <- CompiledCode1],
{ConstAlign, ConstSize, ConstMap, RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, ?ARCH_REGISTERS:alignment()),
+ hipe_pack_constants:pack_constants(Code),
%% Compute total code size separately as a sanity check for alignment
CodeSize = compute_code_size(CompiledCode1, 0),
%% io:format("Code Size (pre-computed): ~w~n", [CodeSize]),
diff --git a/lib/hipe/misc/hipe_consttab.erl b/lib/hipe/misc/hipe_consttab.erl
index 64e3d3ccaa..741bdb2094 100644
--- a/lib/hipe/misc/hipe_consttab.erl
+++ b/lib/hipe/misc/hipe_consttab.erl
@@ -63,9 +63,7 @@
%% A hipe_consttab is a tuple {Data, ReferedLabels, NextConstLabel}
%% @type hipe_constlbl().
%% An abstract datatype for referring to data.
-%% @type element_type() = byte | word | ctab_array()
-%% @type ctab_array() = {ctab_array, Type::element_type(),
-%% NoElements::pos_integer()}
+%% @type element_type() = byte | word
%% @type block() = [integer() | label_ref()]
%% @type label_ref() = {label, Label::code_label()}
%% @type code_label() = hipe_sparc:label_name() | hipe_x86:label_name()
@@ -110,8 +108,7 @@
-type label_ref() :: {'label', code_label()}.
-type block() :: [hipe_constlbl() | label_ref()].
--type ctab_array() :: {'ctab_array', 'byte' | 'word', pos_integer()}.
--type element_type() :: 'byte' | 'word' | ctab_array().
+-type element_type() :: 'byte' | 'word'.
-type sort_order() :: term(). % XXX: FIXME
@@ -187,7 +184,7 @@ insert_block({ConstTab, RefToLabels, NextLabel}, ElementType, InitList) ->
ReferredLabels = get_labels(InitList, []),
NewRefTo = ReferredLabels ++ RefToLabels,
{NewTa, Id} = insert_const({ConstTab, NewRefTo, NextLabel},
- block, word_size(), false,
+ block, size_of(ElementType), false,
{ElementType,InitList}),
{insert_backrefs(NewTa, Id, ReferredLabels), Id}.
@@ -256,13 +253,9 @@ get_labels([], Acc) ->
%% @spec size_of(element_type()) -> pos_integer()
%% @doc Returns the size in bytes of an element_type.
-%% The is_atom/1 guard in the clause handling arrays
-%% constraints the argument to 'byte' | 'word'
-spec size_of(element_type()) -> pos_integer().
size_of(byte) -> 1;
-size_of(word) -> word_size();
-size_of({ctab_array,S,N}) when is_atom(S), is_integer(N), N > 0 ->
- N * size_of(S).
+size_of(word) -> word_size().
%% @spec decompose({element_type(), block()}) -> [byte()]
%% @doc Turns a block into a list of bytes.
diff --git a/lib/hipe/misc/hipe_pack_constants.erl b/lib/hipe/misc/hipe_pack_constants.erl
index 9dd18bce0f..6736d1f503 100644
--- a/lib/hipe/misc/hipe_pack_constants.erl
+++ b/lib/hipe/misc/hipe_pack_constants.erl
@@ -13,7 +13,7 @@
%% limitations under the License.
-module(hipe_pack_constants).
--export([pack_constants/2, slim_refs/1, slim_constmap/1,
+-export([pack_constants/1, slim_refs/1, slim_constmap/1,
find_const/2, mk_data_relocs/2, slim_sorted_exportmap/3]).
-include("hipe_consttab.hrl").
@@ -37,8 +37,8 @@
-record(pcm_entry, {mfa :: mfa(),
label :: hipe_constlbl(),
- const_num :: const_num(),
- start :: addr(),
+ const_num :: const_num(),
+ start :: addr(),
type :: 0 | 1 | 2,
raw_data :: raw_data()}).
-type pcm_entry() :: #pcm_entry{}.
@@ -53,11 +53,11 @@
%%-----------------------------------------------------------------------------
--spec pack_constants([{mfa(),[_],hipe_consttab()}], ct_alignment()) ->
+-spec pack_constants([{mfa(),[_],hipe_consttab()}]) ->
{ct_alignment(), non_neg_integer(), packed_const_map(), mfa_refs_map()}.
-pack_constants(Data, Align) ->
- pack_constants(Data, 0, Align, 0, [], []).
+pack_constants(Data) ->
+ pack_constants(Data, 0, 1, 0, [], []). % 1 = byte alignment
pack_constants([{MFA,_,ConstTab}|Rest], Size, Align, ConstNo, Acc, Refs) ->
Labels = hipe_consttab:labels(ConstTab),
diff --git a/lib/hipe/ppc/hipe_ppc_assemble.erl b/lib/hipe/ppc/hipe_ppc_assemble.erl
index 66817837df..b0f57e5582 100644
--- a/lib/hipe/ppc/hipe_ppc_assemble.erl
+++ b/lib/hipe/ppc/hipe_ppc_assemble.erl
@@ -32,7 +32,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
|| {MFA, Defun} <- CompiledCode],
%%
{ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, hipe_rtl_arch:word_size()),
+ hipe_pack_constants:pack_constants(Code),
%%
{CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} =
encode(translate(Code, ConstMap), Options),
diff --git a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
index e8ccbec9f1..b8f0a1974c 100644
--- a/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_coalescing_regalloc.erl
@@ -914,7 +914,7 @@ findCheapest([Node|Nodes], IG, Cost, Cheapest, SpillLimit) ->
%% limit are extremely expensive.
getCost(Node, IG, SpillLimit) ->
- case Node > SpillLimit of
+ case Node >= SpillLimit of
true -> inf;
false -> hipe_ig:node_spill_cost(Node, IG)
end.
diff --git a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
index 07aa812f4a..f82d3a2cbc 100644
--- a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl
@@ -209,8 +209,8 @@ color(IG, Spill, PhysRegs, SpillIx, SpillLimit, NumNodes, Target,
%% Any nodes above the spillimit must be colored first...
MustNotSpill =
- if NumNodes > SpillLimit+1 ->
- sort_on_degree(lists:seq(SpillLimit+1,NumNodes-1) -- Low,IG);
+ if NumNodes > SpillLimit ->
+ sort_on_degree(lists:seq(SpillLimit,NumNodes-1) -- Low,IG);
true -> []
end,
@@ -401,7 +401,7 @@ spill_costs([{N,Info}|Ns], IG, Vis, Spill, SpillLimit, Target) ->
true ->
spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target);
false ->
- if N > SpillLimit ->
+ if N >= SpillLimit ->
spill_costs(Ns, IG, Vis, Spill, SpillLimit, Target);
true ->
[{spill_cost_of(N,Spill)/Deg,N} |
diff --git a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
index b96920cbcf..a019c46b90 100644
--- a/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
+++ b/lib/hipe/regalloc/hipe_optimistic_regalloc.erl
@@ -1933,7 +1933,7 @@ findCheapest([Node|Nodes], IG, Cost, Cheapest, SpillLimit) ->
%% limit are extremely expensive.
getCost(Node, IG, SpillLimit) ->
- case Node > SpillLimit of
+ case Node >= SpillLimit of
true -> inf;
false ->
SpillCost = hipe_ig:node_spill_cost(Node, IG),
diff --git a/lib/hipe/sparc/hipe_sparc_assemble.erl b/lib/hipe/sparc/hipe_sparc_assemble.erl
index 08bd47c4d2..2b82f41d23 100644
--- a/lib/hipe/sparc/hipe_sparc_assemble.erl
+++ b/lib/hipe/sparc/hipe_sparc_assemble.erl
@@ -32,7 +32,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
|| {MFA, Defun} <- CompiledCode],
%%
{ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, 4),
+ hipe_pack_constants:pack_constants(Code),
%%
{CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} =
encode(translate(Code, ConstMap), Options),
diff --git a/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl b/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
index caa0e71d0b..430e097b91 100644
--- a/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
+++ b/lib/hipe/test/basic_SUITE_data/basic_bugs_hipe.erl
@@ -18,6 +18,7 @@ test() ->
ok = test_R12B5_seg_fault(),
ok = test_switch_neg_int(),
ok = test_icode_range_anal(),
+ ok = test_icode_range_call(),
ok.
%%-----------------------------------------------------------------------
@@ -461,3 +462,44 @@ g(X, Z) ->
test -> non_zero_test;
other -> other
end.
+
+%%-----------------------------------------------------------------------
+%% From: Rich Neswold
+%% Date: Oct 5, 2016
+%%
+%% The following was a bug in the HiPE compiler's range analysis. The
+%% function range_client/2 below would would not stop when N reached 0,
+%% but keep recursing into the second clause forever.
+%%
+%% The problem turned out to be in hipe_icode_range:analyse_call/2,
+%% which would note update the argument ranges of the callee if the
+%% result of the call was ignored.
+%% -----------------------------------------------------------------------
+-define(TIMEOUT, 42).
+
+test_icode_range_call() ->
+ Self = self(),
+ Client = spawn_link(fun() -> range_client(Self, 4) end),
+ range_server(4, Client).
+
+range_server(0, _Client) ->
+ receive
+ stopping -> ok;
+ {called_with, 0} -> error(failure)
+ after ?TIMEOUT -> error(timeout)
+ end;
+range_server(N, Client) ->
+ receive
+ {called_with, N} ->
+ Client ! proceed
+ after ?TIMEOUT -> error(timeout)
+ end,
+ range_server(N-1, Client). % tailcall (so the bug does not affect it)
+
+range_client(Server, 0) ->
+ Server ! stopping;
+range_client(Server, N) ->
+ Server ! {called_with, N},
+ receive proceed -> ok end,
+ range_client(Server, N - 1), % non-tailrecursive call with ignored result
+ ok.
diff --git a/lib/hipe/x86/hipe_x86_assemble.erl b/lib/hipe/x86/hipe_x86_assemble.erl
index fb0beba293..50919bdf4e 100644
--- a/lib/hipe/x86/hipe_x86_assemble.erl
+++ b/lib/hipe/x86/hipe_x86_assemble.erl
@@ -63,7 +63,7 @@ assemble(CompiledCode, Closures, Exports, Options) ->
|| {MFA, Defun} <- CompiledCode],
%%
{ConstAlign,ConstSize,ConstMap,RefsFromConsts} =
- hipe_pack_constants:pack_constants(Code, ?HIPE_X86_REGISTERS:alignment()),
+ hipe_pack_constants:pack_constants(Code),
%%
{CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} =
encode(translate(Code, ConstMap, Options), Options),